diff options
author | Amir Goldstein <amir73il@gmail.com> | 2023-10-13 12:13:12 +0300 |
---|---|---|
committer | Amir Goldstein <amir73il@gmail.com> | 2023-12-23 16:35:09 +0200 |
commit | 9b7e9e2f5d5c3d079ec46bc71b114012e362ea6e (patch) | |
tree | a3a6266457b1440aaa4c7ae10e5bb60fa691ecd8 /fs/backing-file.c | |
parent | a6293b3e285cd0d7692141d7981a5f144f0e2f0b (diff) |
fs: factor out backing_file_splice_{read,write}() helpers
There is not much in those helpers, but it makes sense to have them
logically next to the backing_file_{read,write}_iter() helpers as they
may grow more common logic in the future.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Diffstat (limited to 'fs/backing-file.c')
-rw-r--r-- | fs/backing-file.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/fs/backing-file.c b/fs/backing-file.c index 323187a49da3..ddd35c1d6c71 100644 --- a/fs/backing-file.c +++ b/fs/backing-file.c @@ -10,6 +10,7 @@ #include <linux/fs.h> #include <linux/backing-file.h> +#include <linux/splice.h> #include "internal.h" @@ -245,6 +246,56 @@ out: } EXPORT_SYMBOL_GPL(backing_file_write_iter); +ssize_t backing_file_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags, + struct backing_file_ctx *ctx) +{ + const struct cred *old_cred; + ssize_t ret; + + if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING))) + return -EIO; + + old_cred = override_creds(ctx->cred); + ret = vfs_splice_read(in, ppos, pipe, len, flags); + revert_creds(old_cred); + + if (ctx->accessed) + ctx->accessed(ctx->user_file); + + return ret; +} +EXPORT_SYMBOL_GPL(backing_file_splice_read); + +ssize_t backing_file_splice_write(struct pipe_inode_info *pipe, + struct file *out, loff_t *ppos, size_t len, + unsigned int flags, + struct backing_file_ctx *ctx) +{ + const struct cred *old_cred; + ssize_t ret; + + if (WARN_ON_ONCE(!(out->f_mode & FMODE_BACKING))) + return -EIO; + + ret = file_remove_privs(ctx->user_file); + if (ret) + return ret; + + old_cred = override_creds(ctx->cred); + file_start_write(out); + ret = iter_file_splice_write(pipe, out, ppos, len, flags); + file_end_write(out); + revert_creds(old_cred); + + if (ctx->end_write) + ctx->end_write(ctx->user_file); + + return ret; +} +EXPORT_SYMBOL_GPL(backing_file_splice_write); + static int __init backing_aio_init(void) { backing_aio_cachep = kmem_cache_create("backing_aio", |