propagae fuse_open_out arguments up to fuse_finish_open() with optional backing_id member. This will be used for setting up passthrough to backing file on open reply with FOPEN_PASSTHROUGH flag and on zero backing_id. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/fuse/cuse.c | 3 ++- fs/fuse/dir.c | 2 +- fs/fuse/file.c | 23 +++++++++++++---------- fs/fuse/fuse_i.h | 8 +++++--- fs/fuse/ioctl.c | 3 ++- include/uapi/linux/fuse.h | 2 +- 6 files changed, 24 insertions(+), 17 deletions(-) diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 91e89e68177e..050e97976e1f 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -115,6 +115,7 @@ static int cuse_open(struct inode *inode, struct file *file) { dev_t devt = inode->i_cdev->dev; struct cuse_conn *cc = NULL, *pos; + struct fuse_open_out outarg; int rc; /* look up and get the connection */ @@ -135,7 +136,7 @@ static int cuse_open(struct inode *inode, struct file *file) * Generic permission check is already done against the chrdev * file, proceed to open. */ - rc = fuse_do_open(&cc->fm, 0, file, 0); + rc = fuse_do_open(&cc->fm, 0, file, 0, &outarg); if (rc) fuse_conn_put(&cc->fc); return rc; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index d707e6987da9..f2adcb30852d 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -698,7 +698,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, fuse_sync_release(fi, ff, flags); } else { file->private_data = ff; - fuse_finish_open(inode, file); + fuse_finish_open(inode, file, &outopen); if (fm->fc->atomic_o_trunc && trunc) truncate_pagecache(inode, 0); else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 1cdb6327511e..b0a6189f7662 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -126,7 +126,8 @@ static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir) } struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, - unsigned int open_flags, bool isdir) + unsigned int open_flags, bool isdir, + struct fuse_open_out *outargp) { struct fuse_conn *fc = fm->fc; struct fuse_file *ff; @@ -140,13 +141,12 @@ struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, /* Default for no-open */ ff->open_flags = FOPEN_KEEP_CACHE | (isdir ? FOPEN_CACHE_DIR : 0); if (isdir ? !fc->no_opendir : !fc->no_open) { - struct fuse_open_out outarg; int err; - err = fuse_send_open(fm, nodeid, open_flags, opcode, &outarg); + err = fuse_send_open(fm, nodeid, open_flags, opcode, outargp); if (!err) { - ff->fh = outarg.fh; - ff->open_flags = outarg.open_flags; + ff->fh = outargp->fh; + ff->open_flags = outargp->open_flags; } else if (err != -ENOSYS) { fuse_file_free(ff); @@ -168,9 +168,10 @@ struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, } int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, - bool isdir) + bool isdir, struct fuse_open_out *outargp) { - struct fuse_file *ff = fuse_file_open(fm, nodeid, file->f_flags, isdir); + struct fuse_file *ff = fuse_file_open(fm, nodeid, file->f_flags, isdir, + outargp); if (!IS_ERR(ff)) file->private_data = ff; @@ -194,7 +195,8 @@ static void fuse_link_write_file(struct file *file) spin_unlock(&fi->lock); } -void fuse_finish_open(struct inode *inode, struct file *file) +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_open_out *outargp) { struct fuse_file *ff = file->private_data; struct fuse_conn *fc = get_fuse_conn(inode); @@ -222,6 +224,7 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) { struct fuse_mount *fm = get_fuse_mount(inode); struct fuse_conn *fc = fm->fc; + struct fuse_open_out outarg; int err; bool is_wb_truncate = (file->f_flags & O_TRUNC) && fc->atomic_o_trunc && @@ -249,9 +252,9 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) if (is_wb_truncate || dax_truncate) fuse_set_nowrite(inode); - err = fuse_do_open(fm, get_node_id(inode), file, isdir); + err = fuse_do_open(fm, get_node_id(inode), file, isdir, &outarg); if (!err) - fuse_finish_open(inode, file); + fuse_finish_open(inode, file, &outarg); if (is_wb_truncate || dax_truncate) fuse_release_nowrite(inode); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 5be51358542e..233344773d29 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1038,7 +1038,8 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir); struct fuse_file *fuse_file_alloc(struct fuse_mount *fm); void fuse_file_free(struct fuse_file *ff); -void fuse_finish_open(struct inode *inode, struct file *file); +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_open_out *outargp); void fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff, unsigned int flags); @@ -1259,7 +1260,7 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid, u64 child_nodeid, struct qstr *name, u32 flags); int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, - bool isdir); + bool isdir, struct fuse_open_out *outargp); /** * fuse_direct_io() flags @@ -1351,7 +1352,8 @@ int fuse_fileattr_set(struct mnt_idmap *idmap, /* file.c */ struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, - unsigned int open_flags, bool isdir); + unsigned int open_flags, bool isdir, + struct fuse_open_out *outargp); void fuse_file_release(struct inode *inode, struct fuse_file *ff, unsigned int open_flags, fl_owner_t id, bool isdir); diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c index 726640fa439e..3aeef75c4df3 100644 --- a/fs/fuse/ioctl.c +++ b/fs/fuse/ioctl.c @@ -423,6 +423,7 @@ static struct fuse_file *fuse_priv_ioctl_prepare(struct inode *inode) { struct fuse_mount *fm = get_fuse_mount(inode); bool isdir = S_ISDIR(inode->i_mode); + struct fuse_open_out outarg; if (!fuse_allow_current_process(fm->fc)) return ERR_PTR(-EACCES); @@ -433,7 +434,7 @@ static struct fuse_file *fuse_priv_ioctl_prepare(struct inode *inode) if (!S_ISREG(inode->i_mode) && !isdir) return ERR_PTR(-ENOTTY); - return fuse_file_open(fm, get_node_id(inode), O_RDONLY, isdir); + return fuse_file_open(fm, get_node_id(inode), O_RDONLY, isdir, &outarg); } static void fuse_priv_ioctl_cleanup(struct inode *inode, struct fuse_file *ff) diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index acb42a76f7ff..0e273f372df4 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -766,7 +766,7 @@ struct fuse_create_in { struct fuse_open_out { uint64_t fh; uint32_t open_flags; - uint32_t padding; + int32_t backing_id; }; struct fuse_release_in { -- 2.34.1