summaryrefslogtreecommitdiff
path: root/fs/backing-file.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2023-10-13 12:13:12 +0300
committerAmir Goldstein <amir73il@gmail.com>2023-12-23 17:35:09 +0300
commit9b7e9e2f5d5c3d079ec46bc71b114012e362ea6e (patch)
treea3a6266457b1440aaa4c7ae10e5bb60fa691ecd8 /fs/backing-file.c
parenta6293b3e285cd0d7692141d7981a5f144f0e2f0b (diff)
downloadlinux-9b7e9e2f5d5c3d079ec46bc71b114012e362ea6e.tar.xz
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.c51
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",