@@ -622,3 +622,10 @@ in your dentry operations instead.
alloc_file_clone(file, flags, ops) does not affect any caller's references.
On success you get a new struct file sharing the mount/dentry with the
original, on failure - ERR_PTR().
+--
+[mandatory]
+ ->copy_file_range() may now be passed files which belong to two
+ different superblocks of the same file system type or which belong
+ to two different filesystems types all together. As before, the
+ destination's copy_file_range() is the function which is called.
+ If it cannot copy ranges from the source, it should return -EXDEV.
@@ -1114,6 +1114,9 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
unsigned int xid = get_xid();
ssize_t rc;
+ if (file_inode(src_file)->i_sb != file_inode(dst_file)->i_sb)
+ return -EXDEV;
+
rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
len, flags);
free_xid(xid);
@@ -135,6 +135,9 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
{
ssize_t ret;
+ if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
+ return -EXDEV;
+
if (file_inode(file_in) == file_inode(file_out))
return -EINVAL;
retry:
@@ -483,6 +483,9 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t len, unsigned int flags)
{
+ if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
+ return -EXDEV;
+
return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags,
OVL_COPY);
}
@@ -1594,11 +1594,10 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
}
}
- if (inode_in->i_sb == inode_out->i_sb &&
- file_out->f_op->copy_file_range) {
+ if (file_out->f_op->copy_file_range) {
ret = file_out->f_op->copy_file_range(file_in, pos_in, file_out,
pos_out, len, flags);
- if (ret != -EOPNOTSUPP)
+ if (ret != -EOPNOTSUPP && ret != -EXDEV)
goto done;
}