+3
-3
fs/ksmbd/vfs.c
+3
-3
fs/ksmbd/vfs.c
···
1794
1794
ret = vfs_copy_file_range(src_fp->filp, src_off,
1795
1795
dst_fp->filp, dst_off, len, 0);
1796
1796
if (ret == -EOPNOTSUPP || ret == -EXDEV)
1797
-
ret = generic_copy_file_range(src_fp->filp, src_off,
1798
-
dst_fp->filp, dst_off,
1799
-
len, 0);
1797
+
ret = vfs_copy_file_range(src_fp->filp, src_off,
1798
+
dst_fp->filp, dst_off, len,
1799
+
COPY_FILE_SPLICE);
1800
1800
if (ret < 0)
1801
1801
return ret;
1802
1802
+2
-2
fs/nfsd/vfs.c
+2
-2
fs/nfsd/vfs.c
···
596
596
ret = vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
597
597
598
598
if (ret == -EOPNOTSUPP || ret == -EXDEV)
599
-
ret = generic_copy_file_range(src, src_pos, dst, dst_pos,
600
-
count, 0);
599
+
ret = vfs_copy_file_range(src, src_pos, dst, dst_pos, count,
600
+
COPY_FILE_SPLICE);
601
601
return ret;
602
602
}
603
603
+15
-4
fs/read_write.c
+15
-4
fs/read_write.c
···
1388
1388
struct file *file_out, loff_t pos_out,
1389
1389
size_t len, unsigned int flags)
1390
1390
{
1391
+
lockdep_assert(sb_write_started(file_inode(file_out)->i_sb));
1392
+
1391
1393
return do_splice_direct(file_in, &pos_in, file_out, &pos_out,
1392
1394
len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
1393
1395
}
···
1426
1424
* and several different sets of file_operations, but they all end up
1427
1425
* using the same ->copy_file_range() function pointer.
1428
1426
*/
1429
-
if (file_out->f_op->copy_file_range) {
1427
+
if (flags & COPY_FILE_SPLICE) {
1428
+
/* cross sb splice is allowed */
1429
+
} else if (file_out->f_op->copy_file_range) {
1430
1430
if (file_in->f_op->copy_file_range !=
1431
1431
file_out->f_op->copy_file_range)
1432
1432
return -EXDEV;
···
1478
1474
size_t len, unsigned int flags)
1479
1475
{
1480
1476
ssize_t ret;
1477
+
bool splice = flags & COPY_FILE_SPLICE;
1481
1478
1482
-
if (flags != 0)
1479
+
if (flags & ~COPY_FILE_SPLICE)
1483
1480
return -EINVAL;
1484
1481
1485
1482
ret = generic_copy_file_checks(file_in, pos_in, file_out, pos_out, &len,
···
1506
1501
* same sb using clone, but for filesystems where both clone and copy
1507
1502
* are supported (e.g. nfs,cifs), we only call the copy method.
1508
1503
*/
1509
-
if (file_out->f_op->copy_file_range) {
1504
+
if (!splice && file_out->f_op->copy_file_range) {
1510
1505
ret = file_out->f_op->copy_file_range(file_in, pos_in,
1511
1506
file_out, pos_out,
1512
1507
len, flags);
1513
1508
goto done;
1514
1509
}
1515
1510
1516
-
if (file_in->f_op->remap_file_range &&
1511
+
if (!splice && file_in->f_op->remap_file_range &&
1517
1512
file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) {
1518
1513
ret = file_in->f_op->remap_file_range(file_in, pos_in,
1519
1514
file_out, pos_out,
···
1533
1528
* consistent story about which filesystems support copy_file_range()
1534
1529
* and which filesystems do not, that will allow userspace tools to
1535
1530
* make consistent desicions w.r.t using copy_file_range().
1531
+
*
1532
+
* We also get here if caller (e.g. nfsd) requested COPY_FILE_SPLICE.
1536
1533
*/
1537
1534
ret = generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
1538
1535
flags);
···
1588
1581
} else {
1589
1582
pos_out = f_out.file->f_pos;
1590
1583
}
1584
+
1585
+
ret = -EINVAL;
1586
+
if (flags != 0)
1587
+
goto out;
1591
1588
1592
1589
ret = vfs_copy_file_range(f_in.file, pos_in, f_out.file, pos_out, len,
1593
1590
flags);
+8
include/linux/fs.h
+8
include/linux/fs.h
···
2089
2089
*/
2090
2090
#define REMAP_FILE_ADVISORY (REMAP_FILE_CAN_SHORTEN)
2091
2091
2092
+
/*
2093
+
* These flags control the behavior of vfs_copy_file_range().
2094
+
* They are not available to the user via syscall.
2095
+
*
2096
+
* COPY_FILE_SPLICE: call splice direct instead of fs clone/copy ops
2097
+
*/
2098
+
#define COPY_FILE_SPLICE (1 << 0)
2099
+
2092
2100
struct iov_iter;
2093
2101
struct io_uring_cmd;
2094
2102