diff options
author | Amir Goldstein <amir73il@gmail.com> | 2024-02-09 17:03:55 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2024-03-05 13:40:42 +0100 |
commit | fc8ff397b2a91590031ae08534de627f957005cb (patch) | |
tree | 75eccaa695f54d036602532bf38b1b9911434394 /fs/fuse/iomode.c | |
parent | 44350256ab943d424d70aa60a34f45060b3a36e8 (diff) |
fuse: prepare for opening file in passthrough mode
In preparation for opening file in passthrough mode, store the
fuse_open_out argument in ff->args to be passed into fuse_file_io_open()
with the optional backing_id member.
This will be used for setting up passthrough to backing file on open
reply with FOPEN_PASSTHROUGH flag and a valid backing_id.
Opening a file in passthrough mode may fail for several reasons, such as
missing capability, conflicting open flags or inode in caching mode.
Return EIO from fuse_file_io_open() in those cases.
The combination of FOPEN_PASSTHROUGH and FOPEN_DIRECT_IO is allowed -
it mean that read/write operations will go directly to the server,
but mmap will be done to the backing file.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse/iomode.c')
-rw-r--r-- | fs/fuse/iomode.c | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/fs/fuse/iomode.c b/fs/fuse/iomode.c index ea47c76b9df1..2161bdf91db2 100644 --- a/fs/fuse/iomode.c +++ b/fs/fuse/iomode.c @@ -31,7 +31,7 @@ int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff) struct fuse_inode *fi = get_fuse_inode(inode); /* There are no io modes if server does not implement open */ - if (!ff->release_args) + if (!ff->args) return 0; spin_lock(&fi->lock); @@ -103,6 +103,37 @@ void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff) spin_unlock(&fi->lock); } +/* + * Open flags that are allowed in combination with FOPEN_PASSTHROUGH. + * A combination of FOPEN_PASSTHROUGH and FOPEN_DIRECT_IO means that read/write + * operations go directly to the server, but mmap is done on the backing file. + * FOPEN_PASSTHROUGH mode should not co-exist with any users of the fuse inode + * page cache, so FOPEN_KEEP_CACHE is a strange and undesired combination. + */ +#define FOPEN_PASSTHROUGH_MASK \ + (FOPEN_PASSTHROUGH | FOPEN_DIRECT_IO | FOPEN_PARALLEL_DIRECT_WRITES | \ + FOPEN_NOFLUSH) + +static int fuse_file_passthrough_open(struct inode *inode, struct file *file) +{ + struct fuse_file *ff = file->private_data; + struct fuse_conn *fc = get_fuse_conn(inode); + int err; + + /* Check allowed conditions for file open in passthrough mode */ + if (!IS_ENABLED(CONFIG_FUSE_PASSTHROUGH) || !fc->passthrough || + (ff->open_flags & ~FOPEN_PASSTHROUGH_MASK)) + return -EINVAL; + + /* TODO: implement backing file open */ + return -EOPNOTSUPP; + + /* First passthrough file open denies caching inode io mode */ + err = fuse_file_uncached_io_start(inode, ff); + + return err; +} + /* Request access to submit new io to inode via open file */ int fuse_file_io_open(struct file *file, struct inode *inode) { @@ -113,7 +144,7 @@ int fuse_file_io_open(struct file *file, struct inode *inode) * io modes are not relevant with DAX and with server that does not * implement open. */ - if (FUSE_IS_DAX(inode) || !ff->release_args) + if (FUSE_IS_DAX(inode) || !ff->args) return 0; /* @@ -123,16 +154,21 @@ int fuse_file_io_open(struct file *file, struct inode *inode) ff->open_flags &= ~FOPEN_PARALLEL_DIRECT_WRITES; /* + * First passthrough file open denies caching inode io mode. * First caching file open enters caching inode io mode. * * Note that if user opens a file open with O_DIRECT, but server did * not specify FOPEN_DIRECT_IO, a later fcntl() could remove O_DIRECT, * so we put the inode in caching mode to prevent parallel dio. */ - if (ff->open_flags & FOPEN_DIRECT_IO) + if ((ff->open_flags & FOPEN_DIRECT_IO) && + !(ff->open_flags & FOPEN_PASSTHROUGH)) return 0; - err = fuse_file_cached_io_start(inode, ff); + if (ff->open_flags & FOPEN_PASSTHROUGH) + err = fuse_file_passthrough_open(inode, file); + else + err = fuse_file_cached_io_start(inode, ff); if (err) goto fail; |