]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs: factor out backing_file_splice_{read,write}() helpers
authorAmir Goldstein <amir73il@gmail.com>
Fri, 13 Oct 2023 09:13:12 +0000 (12:13 +0300)
committerAmir Goldstein <amir73il@gmail.com>
Sat, 23 Dec 2023 14:35:09 +0000 (16:35 +0200)
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>
fs/backing-file.c
fs/overlayfs/file.c
include/linux/backing-file.h

index 323187a49da3d72a952a779492d897d5d85183e1..ddd35c1d6c71fac43fa3e1fef62db53aadeda43b 100644 (file)
@@ -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",
index 1b578cb27a26c9a2c8ed437f06d6f4407461befe..69b52d2f9c74e5cff20d991f34c4a6f0220a74fb 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/xattr.h>
 #include <linux/uio.h>
 #include <linux/uaccess.h>
-#include <linux/splice.h>
 #include <linux/security.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
@@ -332,20 +331,21 @@ static ssize_t ovl_splice_read(struct file *in, loff_t *ppos,
                               struct pipe_inode_info *pipe, size_t len,
                               unsigned int flags)
 {
-       const struct cred *old_cred;
        struct fd real;
        ssize_t ret;
+       struct backing_file_ctx ctx = {
+               .cred = ovl_creds(file_inode(in)->i_sb),
+               .user_file = in,
+               .accessed = ovl_file_accessed,
+       };
 
        ret = ovl_real_fdget(in, &real);
        if (ret)
                return ret;
 
-       old_cred = ovl_override_creds(file_inode(in)->i_sb);
-       ret = vfs_splice_read(real.file, ppos, pipe, len, flags);
-       revert_creds(old_cred);
-       ovl_file_accessed(in);
-
+       ret = backing_file_splice_read(real.file, ppos, pipe, len, flags, &ctx);
        fdput(real);
+
        return ret;
 }
 
@@ -361,30 +361,23 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
                                loff_t *ppos, size_t len, unsigned int flags)
 {
        struct fd real;
-       const struct cred *old_cred;
        struct inode *inode = file_inode(out);
        ssize_t ret;
+       struct backing_file_ctx ctx = {
+               .cred = ovl_creds(inode->i_sb),
+               .user_file = out,
+               .end_write = ovl_file_modified,
+       };
 
        inode_lock(inode);
        /* Update mode */
        ovl_copyattr(inode);
-       ret = file_remove_privs(out);
-       if (ret)
-               goto out_unlock;
 
        ret = ovl_real_fdget(out, &real);
        if (ret)
                goto out_unlock;
 
-       old_cred = ovl_override_creds(inode->i_sb);
-       file_start_write(real.file);
-
-       ret = iter_file_splice_write(pipe, real.file, ppos, len, flags);
-
-       file_end_write(real.file);
-       /* Update size */
-       ovl_file_modified(out);
-       revert_creds(old_cred);
+       ret = backing_file_splice_write(pipe, real.file, ppos, len, flags, &ctx);
        fdput(real);
 
 out_unlock:
index 0648d548a4180617c3fd2aa8864d916da902843f..0546d5b1c9f59b73aed7a0389f3ac91c50194191 100644 (file)
@@ -28,5 +28,13 @@ ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
 ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter,
                                struct kiocb *iocb, int flags,
                                struct backing_file_ctx *ctx);
+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);
+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);
 
 #endif /* _LINUX_BACKING_FILE_H */