[RFC][PATCH 5/5] ovl: add support for copy file range to another fs

Amir Goldstein <[email protected]> Thu, 23 Jul 2026 13:48:48 +0200
Newsgroups org.kernel.vger.linux-unionfs,org.kernel.vger.linux-fsdevel
Message-ID <[email protected]>
It is technically possible for overlayfs to copy_file_range() to
the base fs of the real layer.

Implementation of copy to other fs is a bit more subtle, because
we must not take the other fs locks in overlayfs code.

Signed-off-by: Amir Goldstein <[email protected]>
---
 fs/overlayfs/file.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index 169a48de565e9..cc52ccc35961f 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -535,10 +535,23 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
 
 	/*
 	 * Overlayfs may be able to copy to a non overlayfs dst which is on the
-	 * same sb or same fs type as real file_in fs, but not implemented yet.
+	 * same sb or same fs type as real file_in fs, but we must avoid taking
+	 * the locks on the foreign fs.
 	 */
-	if (WARN_ON_ONCE(!is_ovl_fs(inode_out->i_sb)))
-		return -EXDEV;
+	if (unlikely(!is_ovl_fs(inode_out->i_sb))) {
+		if (WARN_ON_ONCE(op != OVL_COPY) ||
+		    WARN_ON_ONCE(!is_ovl_fs(file_inode(file_in)->i_sb)))
+			return -EXDEV;
+
+		realfile_in = ovl_real_file(file_in);
+		if (IS_ERR(realfile_in))
+			return PTR_ERR(realfile_in);
+
+		with_ovl_creds(file_inode(file_in)->i_sb)
+			return vfs_copy_file_range(realfile_in, pos_in,
+						   file_out, pos_out, len,
+						   flags);
+	}
 
 	inode_lock(inode_out);
 	if (op != OVL_DEDUPE) {
-- 
2.54.0