This patch implement the "check_flags" operation that passes the flag setting by fcntl() and ioctl(fd, FIONBIO, &on) to fuse-based applications. This patch depends on the following: [PATCH] VFS: pass the flag setting by fcntl() to vfs Signed-off-by: Enke Chen <enkechen@xxxxxxxxx> Version: 4.6.0_rc6_next_20160505 fs/fuse/file.c | 43 +++++++++++++++++++++++++++++++++++++++++++ fs/fuse/fuse_i.h | 3 +++ include/uapi/linux/fuse.h | 10 ++++++++++ 3 files changed, 56 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 9154f86..b457a40 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -3010,6 +3010,47 @@ out: return err; } +static int fuse_do_setfl(unsigned int flags, struct file *file) +{ + struct inode *inode = file_inode(file); + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_file *ff = file->private_data; + struct fuse_setfl_in inarg; + FUSE_ARGS(args); + int err; + + if (is_bad_inode(inode)) + return -EIO; + + if (fc->no_setfl) + return 0; + + inarg.fh = ff->fh; + inarg.flags = flags; + inarg.setting = 1; + args.in.h.opcode = FUSE_SETFL; + args.in.h.nodeid = get_node_id(inode); + args.in.numargs = 1; + args.in.args[0].size = sizeof(inarg); + args.in.args[0].value = &inarg; + err = fuse_simple_request(fc, &args); + if (err == -ENOSYS) { + fc->no_setfl = 1; + err = 0; + } + + return err; +} + +static int fuse_file_check_flags(unsigned int flags, struct file *file, + int setting) +{ + if (!setting) + return 0; + + return fuse_do_setfl(flags, file); +} + static const struct file_operations fuse_file_operations = { .llseek = fuse_file_llseek, .read_iter = fuse_file_read_iter, @@ -3026,6 +3067,7 @@ static const struct file_operations fuse_file_operations = { .compat_ioctl = fuse_file_compat_ioctl, .poll = fuse_file_poll, .fallocate = fuse_file_fallocate, + .check_flags = fuse_file_check_flags, }; static const struct file_operations fuse_direct_io_file_operations = { @@ -3044,6 +3086,7 @@ static const struct file_operations fuse_direct_io_file_operations = { .poll = fuse_file_poll, .fallocate = fuse_file_fallocate, /* no splice_read */ + .check_flags = fuse_file_check_flags, }; static const struct address_space_operations fuse_file_aops = { diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index eddbe02..70b4f8d 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -617,6 +617,9 @@ struct fuse_conn { /** Is lseek not implemented by fs? */ unsigned no_lseek:1; + /** Is setfl implemented by fs? */ + unsigned no_setfl:1; + /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 5974fae..c068650 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -105,6 +105,9 @@ * * 7.24 * - add FUSE_LSEEK for SEEK_HOLE and SEEK_DATA support + * + * 7.25 + * - add FUSE_SETFL */ #ifndef _LINUX_FUSE_H @@ -362,6 +365,7 @@ enum fuse_opcode { FUSE_READDIRPLUS = 44, FUSE_RENAME2 = 45, FUSE_LSEEK = 46, + FUSE_SETFL = 47, /* CUSE specific operations */ CUSE_INIT = 4096, @@ -773,4 +777,10 @@ struct fuse_lseek_out { uint64_t offset; }; +struct fuse_setfl_in { + uint64_t fh; + uint32_t flags; + uint32_t setting; +}; + #endif /* _LINUX_FUSE_H */ -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html