From: Amir Goldstein <amir73il@gmail.com>
To: Christian Brauner <brauner@kernel.org>
Cc: Miklos Szeredi <miklos@szeredi.hu>,
Daan De Meyer <daan.j.demeyer@gmail.com>,
linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: [RFC][PATCH 2/5] fs: add support for copy file range from another fs
Date: Thu, 23 Jul 2026 13:48:45 +0200 [thread overview]
Message-ID: <20260723114848.1212429-3-amir73il@gmail.com> (raw)
In-Reply-To: <20260723114848.1212429-1-amir73il@gmail.com>
Add a declarative vfs flag FOP_CROSS_FS_COPY for filesystems that may
be able copy from/to other fs and implement the copy from another fs,
which is the easy side.
When filesystem is copying from another fs, it will typically call vfs
read helpers to read from the other fs, so avoid the double accounting
and double fsnotify read hooks in vfs_copy_file_range().
Implementation of copy to another fs is a bit more subtle and will be
handled by a followup patch.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/read_write.c | 18 ++++++++++++++----
include/linux/fs.h | 2 ++
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/fs/read_write.c b/fs/read_write.c
index d1565a56d089d..78596d9c89119 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1477,6 +1477,7 @@ enum {
FS_COPY_SAME_SB = 1,
FS_COPY_SAME_FS = 2,
FS_COPY_CROSS_FS = 3,
+ FS_COPY_FROM_OTHER_FS = 4,
};
/*
@@ -1495,6 +1496,8 @@ static int copy_file_fs_cmp(struct file *f_in, struct file *f_out,
else if (f_out->f_op->copy_file_range &&
f_out->f_op->copy_file_range == f_in->f_op->copy_file_range)
return FS_COPY_SAME_FS;
+ else if (f_out->f_op->fop_flags & FOP_CROSS_FS_COPY)
+ return FS_COPY_FROM_OTHER_FS;
else if (file_inode(f_in)->i_sb == file_inode(f_out)->i_sb)
return FS_COPY_SAME_SB;
else
@@ -1526,10 +1529,13 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
* We allow some filesystems to handle cross sb copy, but passing
* a file of the wrong filesystem type to filesystem driver can result
* in an attempt to dereference the wrong type of ->private_data, so
- * avoid doing that until we really have a good reason.
+ * avoid doing that unless at least one of the filesystems declares
+ * cross fstype copy support with the FOP_CROSS_FS_COPY flag.
*/
if (fscmp == FS_COPY_SPLICE) {
/* cross sb splice is allowed */
+ } else if (fscmp == FS_COPY_FROM_OTHER_FS) {
+ /* Copy from other fs is allowed */
} else if (file_out->f_op->copy_file_range) {
if (fscmp != FS_COPY_SAME_FS)
return -EXDEV;
@@ -1619,6 +1625,7 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
case FS_COPY_SPLICE:
break;
case FS_COPY_SAME_FS:
+ case FS_COPY_FROM_OTHER_FS:
ret = file_out->f_op->copy_file_range(file_in, pos_in,
file_out, pos_out,
len, flags);
@@ -1665,13 +1672,16 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out, len, 0);
done:
if (ret > 0) {
- fsnotify_access(file_in);
- add_rchar(current, ret);
+ if (fscmp != FS_COPY_FROM_OTHER_FS) {
+ fsnotify_access(file_in);
+ add_rchar(current, ret);
+ }
fsnotify_modify(file_out);
add_wchar(current, ret);
}
- inc_syscr(current);
+ if (fscmp != FS_COPY_FROM_OTHER_FS)
+ inc_syscr(current);
inc_syscw(current);
return ret;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d10897b3a1e35..c7573e89557b9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1980,6 +1980,8 @@ struct file_operations {
#define FOP_ASYNC_LOCK ((__force fop_flags_t)(1 << 6))
/* File system supports uncached read/write buffered IO */
#define FOP_DONTCACHE ((__force fop_flags_t)(1 << 7))
+/* Supports copy_file_range() to/from other fs types */
+#define FOP_CROSS_FS_COPY ((__force fop_flags_t)(1 << 8))
/* Wrap a directory iterator that needs exclusive inode access */
int wrap_directory_iterator(struct file *, struct dir_context *,
--
2.54.0
next prev parent reply other threads:[~2026-07-23 11:48 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-23 11:48 [RFC][PATCH 0/5] Proposal for Cross-fs copy_file_range() Amir Goldstein
2026-07-23 11:48 ` [RFC][PATCH 1/5] fs: clarify cross-sb copy_file_range() code Amir Goldstein
2026-07-23 11:48 ` Amir Goldstein [this message]
2026-07-23 11:48 ` [RFC][PATCH 3/5] fs: add support for copy file range to another fs Amir Goldstein
2026-07-23 11:48 ` [RFC][PATCH 4/5] ovl: add support for copy file range from " Amir Goldstein
2026-07-23 11:48 ` [RFC][PATCH 5/5] ovl: add support for copy file range to " Amir Goldstein
2026-07-23 13:05 ` [RFC][PATCH 0/5] Proposal for Cross-fs copy_file_range() Daan De Meyer
2026-07-23 13:36 ` Amir Goldstein
2026-07-23 13:54 ` Daan De Meyer
2026-07-23 14:17 ` Amir Goldstein
2026-07-23 23:29 ` Gao Xiang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260723114848.1212429-3-amir73il@gmail.com \
--to=amir73il@gmail.com \
--cc=brauner@kernel.org \
--cc=daan.j.demeyer@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-unionfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.