Loading fs/fuse/file.c +33 −17 Original line number Original line Diff line number Diff line Loading @@ -19,14 +19,15 @@ #include <linux/uio.h> #include <linux/uio.h> #include <linux/fs.h> #include <linux/fs.h> static int fuse_send_open(struct fuse_mount *fm, u64 nodeid, struct file *file, static int fuse_send_open(struct fuse_mount *fm, u64 nodeid, int opcode, struct fuse_open_out *outargp) unsigned int open_flags, int opcode, struct fuse_open_out *outargp) { { struct fuse_open_in inarg; struct fuse_open_in inarg; FUSE_ARGS(args); FUSE_ARGS(args); memset(&inarg, 0, sizeof(inarg)); memset(&inarg, 0, sizeof(inarg)); inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); inarg.flags = open_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); if (!fm->fc->atomic_o_trunc) if (!fm->fc->atomic_o_trunc) inarg.flags &= ~O_TRUNC; inarg.flags &= ~O_TRUNC; Loading Loading @@ -123,8 +124,8 @@ static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir) } } } } int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, bool isdir) unsigned int open_flags, bool isdir) { { struct fuse_conn *fc = fm->fc; struct fuse_conn *fc = fm->fc; struct fuse_file *ff; struct fuse_file *ff; Loading @@ -132,7 +133,7 @@ int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, ff = fuse_file_alloc(fm); ff = fuse_file_alloc(fm); if (!ff) if (!ff) return -ENOMEM; return ERR_PTR(-ENOMEM); ff->fh = 0; ff->fh = 0; /* Default for no-open */ /* Default for no-open */ Loading @@ -141,14 +142,14 @@ int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, struct fuse_open_out outarg; struct fuse_open_out outarg; int err; int err; err = fuse_send_open(fm, nodeid, file, opcode, &outarg); err = fuse_send_open(fm, nodeid, open_flags, opcode, &outarg); if (!err) { if (!err) { ff->fh = outarg.fh; ff->fh = outarg.fh; ff->open_flags = outarg.open_flags; ff->open_flags = outarg.open_flags; } else if (err != -ENOSYS) { } else if (err != -ENOSYS) { fuse_file_free(ff); fuse_file_free(ff); return err; return ERR_PTR(err); } else { } else { if (isdir) if (isdir) fc->no_opendir = 1; fc->no_opendir = 1; Loading @@ -161,9 +162,19 @@ int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, ff->open_flags &= ~FOPEN_DIRECT_IO; ff->open_flags &= ~FOPEN_DIRECT_IO; ff->nodeid = nodeid; ff->nodeid = nodeid; return ff; } int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, bool isdir) { struct fuse_file *ff = fuse_file_open(fm, nodeid, file->f_flags, isdir); if (!IS_ERR(ff)) file->private_data = ff; file->private_data = ff; return 0; return PTR_ERR_OR_ZERO(ff); } } EXPORT_SYMBOL_GPL(fuse_do_open); EXPORT_SYMBOL_GPL(fuse_do_open); Loading Loading @@ -284,22 +295,21 @@ static void fuse_prepare_release(struct fuse_inode *fi, struct fuse_file *ff, ra->args.nocreds = true; ra->args.nocreds = true; } } void fuse_release_common(struct file *file, bool isdir) void fuse_file_release(struct inode *inode, struct fuse_file *ff, unsigned int open_flags, fl_owner_t id, bool isdir) { { struct fuse_inode *fi = get_fuse_inode(file_inode(file)); struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_file *ff = file->private_data; struct fuse_release_args *ra = ff->release_args; struct fuse_release_args *ra = ff->release_args; int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; fuse_prepare_release(fi, ff, file->f_flags, opcode); fuse_prepare_release(fi, ff, open_flags, opcode); if (ff->flock) { if (ff->flock) { ra->inarg.release_flags |= FUSE_RELEASE_FLOCK_UNLOCK; ra->inarg.release_flags |= FUSE_RELEASE_FLOCK_UNLOCK; ra->inarg.lock_owner = fuse_lock_owner_id(ff->fm->fc, ra->inarg.lock_owner = fuse_lock_owner_id(ff->fm->fc, id); (fl_owner_t) file); } } /* Hold inode until release is finished */ /* Hold inode until release is finished */ ra->inode = igrab(file_inode(file)); ra->inode = igrab(inode); /* /* * Normally this will send the RELEASE request, however if * Normally this will send the RELEASE request, however if Loading @@ -313,6 +323,12 @@ void fuse_release_common(struct file *file, bool isdir) fuse_file_put(ff, ff->fm->fc->destroy, isdir); fuse_file_put(ff, ff->fm->fc->destroy, isdir); } } void fuse_release_common(struct file *file, bool isdir) { fuse_file_release(file_inode(file), file->private_data, file->f_flags, (fl_owner_t) file, isdir); } static int fuse_open(struct inode *inode, struct file *file) static int fuse_open(struct inode *inode, struct file *file) { { return fuse_open_common(inode, file, false); return fuse_open_common(inode, file, false); Loading fs/fuse/fuse_i.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -1242,4 +1242,11 @@ long fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); unsigned long arg); /* file.c */ struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, unsigned int open_flags, bool isdir); void fuse_file_release(struct inode *inode, struct fuse_file *ff, unsigned int open_flags, fl_owner_t id, bool isdir); #endif /* _FS_FUSE_I_H */ #endif /* _FS_FUSE_I_H */ Loading
fs/fuse/file.c +33 −17 Original line number Original line Diff line number Diff line Loading @@ -19,14 +19,15 @@ #include <linux/uio.h> #include <linux/uio.h> #include <linux/fs.h> #include <linux/fs.h> static int fuse_send_open(struct fuse_mount *fm, u64 nodeid, struct file *file, static int fuse_send_open(struct fuse_mount *fm, u64 nodeid, int opcode, struct fuse_open_out *outargp) unsigned int open_flags, int opcode, struct fuse_open_out *outargp) { { struct fuse_open_in inarg; struct fuse_open_in inarg; FUSE_ARGS(args); FUSE_ARGS(args); memset(&inarg, 0, sizeof(inarg)); memset(&inarg, 0, sizeof(inarg)); inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); inarg.flags = open_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); if (!fm->fc->atomic_o_trunc) if (!fm->fc->atomic_o_trunc) inarg.flags &= ~O_TRUNC; inarg.flags &= ~O_TRUNC; Loading Loading @@ -123,8 +124,8 @@ static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir) } } } } int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, bool isdir) unsigned int open_flags, bool isdir) { { struct fuse_conn *fc = fm->fc; struct fuse_conn *fc = fm->fc; struct fuse_file *ff; struct fuse_file *ff; Loading @@ -132,7 +133,7 @@ int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, ff = fuse_file_alloc(fm); ff = fuse_file_alloc(fm); if (!ff) if (!ff) return -ENOMEM; return ERR_PTR(-ENOMEM); ff->fh = 0; ff->fh = 0; /* Default for no-open */ /* Default for no-open */ Loading @@ -141,14 +142,14 @@ int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, struct fuse_open_out outarg; struct fuse_open_out outarg; int err; int err; err = fuse_send_open(fm, nodeid, file, opcode, &outarg); err = fuse_send_open(fm, nodeid, open_flags, opcode, &outarg); if (!err) { if (!err) { ff->fh = outarg.fh; ff->fh = outarg.fh; ff->open_flags = outarg.open_flags; ff->open_flags = outarg.open_flags; } else if (err != -ENOSYS) { } else if (err != -ENOSYS) { fuse_file_free(ff); fuse_file_free(ff); return err; return ERR_PTR(err); } else { } else { if (isdir) if (isdir) fc->no_opendir = 1; fc->no_opendir = 1; Loading @@ -161,9 +162,19 @@ int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, ff->open_flags &= ~FOPEN_DIRECT_IO; ff->open_flags &= ~FOPEN_DIRECT_IO; ff->nodeid = nodeid; ff->nodeid = nodeid; return ff; } int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, bool isdir) { struct fuse_file *ff = fuse_file_open(fm, nodeid, file->f_flags, isdir); if (!IS_ERR(ff)) file->private_data = ff; file->private_data = ff; return 0; return PTR_ERR_OR_ZERO(ff); } } EXPORT_SYMBOL_GPL(fuse_do_open); EXPORT_SYMBOL_GPL(fuse_do_open); Loading Loading @@ -284,22 +295,21 @@ static void fuse_prepare_release(struct fuse_inode *fi, struct fuse_file *ff, ra->args.nocreds = true; ra->args.nocreds = true; } } void fuse_release_common(struct file *file, bool isdir) void fuse_file_release(struct inode *inode, struct fuse_file *ff, unsigned int open_flags, fl_owner_t id, bool isdir) { { struct fuse_inode *fi = get_fuse_inode(file_inode(file)); struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_file *ff = file->private_data; struct fuse_release_args *ra = ff->release_args; struct fuse_release_args *ra = ff->release_args; int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; fuse_prepare_release(fi, ff, file->f_flags, opcode); fuse_prepare_release(fi, ff, open_flags, opcode); if (ff->flock) { if (ff->flock) { ra->inarg.release_flags |= FUSE_RELEASE_FLOCK_UNLOCK; ra->inarg.release_flags |= FUSE_RELEASE_FLOCK_UNLOCK; ra->inarg.lock_owner = fuse_lock_owner_id(ff->fm->fc, ra->inarg.lock_owner = fuse_lock_owner_id(ff->fm->fc, id); (fl_owner_t) file); } } /* Hold inode until release is finished */ /* Hold inode until release is finished */ ra->inode = igrab(file_inode(file)); ra->inode = igrab(inode); /* /* * Normally this will send the RELEASE request, however if * Normally this will send the RELEASE request, however if Loading @@ -313,6 +323,12 @@ void fuse_release_common(struct file *file, bool isdir) fuse_file_put(ff, ff->fm->fc->destroy, isdir); fuse_file_put(ff, ff->fm->fc->destroy, isdir); } } void fuse_release_common(struct file *file, bool isdir) { fuse_file_release(file_inode(file), file->private_data, file->f_flags, (fl_owner_t) file, isdir); } static int fuse_open(struct inode *inode, struct file *file) static int fuse_open(struct inode *inode, struct file *file) { { return fuse_open_common(inode, file, false); return fuse_open_common(inode, file, false); Loading
fs/fuse/fuse_i.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -1242,4 +1242,11 @@ long fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); unsigned long arg); /* file.c */ struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, unsigned int open_flags, bool isdir); void fuse_file_release(struct inode *inode, struct fuse_file *ff, unsigned int open_flags, fl_owner_t id, bool isdir); #endif /* _FS_FUSE_I_H */ #endif /* _FS_FUSE_I_H */