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);