VFS: Pass inode pointer from pathwalk to do_dentry_open()

Pass the dentry inode pointer from pathwalk through to do_dentry_open() for
the purposes of emplacing in file->f_inode so that in future unionmount will
be able to point this elsewhere.

Signed-off-by: David Howells <dhowells@redhat.com>
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index d86edc8..0984c93 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -900,7 +900,8 @@
 		v9inode->writeback_fid = (void *) inode_fid;
 	}
 	mutex_unlock(&v9inode->v_mutex);
-	err = finish_open(file, dentry, generic_file_open, opened);
+	err = finish_open(file, dentry, dentry->d_inode,
+			  generic_file_open, opened);
 	if (err)
 		goto error;
 
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 53687bb..b5bf4482 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -357,7 +357,8 @@
 	}
 	mutex_unlock(&v9inode->v_mutex);
 	/* Since we are opening a file, assign the open fid to the file */
-	err = finish_open(file, dentry, generic_file_open, opened);
+	err = finish_open(file, dentry, dentry->d_inode,
+			  generic_file_open, opened);
 	if (err)
 		goto err_clunk_old_fid;
 	file->private_data = ofid;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index bf338d9..ad060ec 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -269,7 +269,7 @@
 		if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
 			*opened |= FILE_CREATED;
 		}
-		err = finish_open(file, dentry, ceph_open, opened);
+		err = finish_open(file, dentry, dentry->d_inode, ceph_open, opened);
 	}
 
 out_err:
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1cd0162..5004aa7 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -475,7 +475,8 @@
 		goto out;
 	}
 
-	rc = finish_open(file, direntry, generic_file_open, opened);
+	rc = finish_open(file, direntry, direntry->d_inode,
+			 generic_file_open, opened);
 	if (rc) {
 		if (server->ops->close)
 			server->ops->close(xid, tcon, &fid);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index ff155224..4e71a47 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -477,7 +477,8 @@
 	d_instantiate(entry, inode);
 	fuse_change_entry_timeout(entry, &outentry);
 	fuse_invalidate_attr(dir);
-	err = finish_open(file, entry, generic_file_open, opened);
+	err = finish_open(file, entry, entry->d_inode,
+			  generic_file_open, opened);
 	if (err) {
 		fuse_sync_release(ff, flags);
 	} else {
diff --git a/fs/namei.c b/fs/namei.c
index 961bc12..75070b6 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2683,7 +2683,7 @@
 	bool will_truncate = (open_flag & O_TRUNC) != 0;
 	bool got_write = false;
 	int acc_mode = op->acc_mode;
-	struct inode *inode;
+	struct inode *inode = nd->inode;
 	bool symlink_ok = false;
 	struct path save_parent = { .dentry = NULL, .mnt = NULL };
 	bool retried = false;
@@ -2781,6 +2781,7 @@
 		open_flag &= ~O_TRUNC;
 		will_truncate = false;
 		acc_mode = MAY_OPEN;
+		inode = path->dentry->d_inode;
 		path_to_nameidata(path, nd);
 		goto finish_open_created;
 	}
@@ -2788,8 +2789,10 @@
 	/*
 	 * create/update audit record if it already exists.
 	 */
-	if (path->dentry->d_inode)
+	if (path->dentry->d_inode) {
 		audit_inode(name, path->dentry, 0);
+		inode = path->dentry->d_inode;
+	}
 
 	/*
 	 * If atomic_open() acquired write access it is dropped now due to
@@ -2856,7 +2859,7 @@
 		goto out;
 	audit_inode(name, nd->path.dentry, 0);
 finish_open:
-	if (!S_ISREG(nd->inode->i_mode))
+	if (!S_ISREG(inode->i_mode))
 		will_truncate = false;
 
 	if (will_truncate) {
@@ -2870,7 +2873,7 @@
 	if (error)
 		goto out;
 	file->f_path.mnt = nd->path.mnt;
-	error = finish_open(file, nd->path.dentry, NULL, opened);
+	error = finish_open(file, nd->path.dentry, inode, NULL, opened);
 	if (error) {
 		if (error == -EOPENSTALE)
 			goto stale_open;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index f23f455..708862a 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1369,7 +1369,7 @@
 			goto out;
 	}
 
-	err = finish_open(file, dentry, do_open, opened);
+	err = finish_open(file, dentry, dentry->d_inode, do_open, opened);
 	if (err)
 		goto out;
 	nfs_file_set_open_context(file, ctx);
diff --git a/fs/open.c b/fs/open.c
index 6835446..13da773 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -689,12 +689,11 @@
 	return 0;
 }
 
-static int do_dentry_open(struct file *f,
+static int do_dentry_open(struct file *f, struct inode *inode,
 			  int (*open)(struct inode *, struct file *),
 			  const struct cred *cred)
 {
 	static const struct file_operations empty_fops = {};
-	struct inode *inode;
 	int error;
 
 	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
@@ -704,7 +703,7 @@
 		f->f_mode = FMODE_PATH;
 
 	path_get(&f->f_path);
-	inode = f->f_inode = f->f_path.dentry->d_inode;
+	f->f_inode = inode;
 	if (f->f_mode & FMODE_WRITE) {
 		error = __get_file_write_access(inode, f->f_path.mnt);
 		if (error)
@@ -782,7 +781,7 @@
  * If the open callback is set to NULL, then the standard f_op->open()
  * filesystem callback is substituted.
  */
-int finish_open(struct file *file, struct dentry *dentry,
+int finish_open(struct file *file, struct dentry *dentry, struct inode *inode,
 		int (*open)(struct inode *, struct file *),
 		int *opened)
 {
@@ -790,7 +789,7 @@
 	BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
 
 	file->f_path.dentry = dentry;
-	error = do_dentry_open(file, open, current_cred());
+	error = do_dentry_open(file, inode, open, current_cred());
 	if (!error)
 		*opened |= FILE_OPENED;
 
@@ -829,7 +828,7 @@
 	if (!IS_ERR(f)) {
 		f->f_flags = flags;
 		f->f_path = *path;
-		error = do_dentry_open(f, NULL, cred);
+		error = do_dentry_open(f, path->dentry->d_inode, NULL, cred);
 		if (!error) {
 			/* from now on we need fput() to dispose of f */
 			error = open_check_o_direct(f);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 74a907b..682432f8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2014,6 +2014,7 @@
 	FILE_OPENED = 2
 };
 extern int finish_open(struct file *file, struct dentry *dentry,
+			struct inode *inode,
 			int (*open)(struct inode *, struct file *),
 			int *opened);
 extern int finish_no_open(struct file *file, struct dentry *dentry);