@@ -1388,6 +1388,8 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
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
}
@@ -1424,7 +1426,9 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
1424
1426
* and several different sets of file_operations, but they all end up
1425
1427
* using the same ->copy_file_range() function pointer.
1426
1428
*/
1427
- if (file_out -> f_op -> copy_file_range ) {
1429
+ if (flags & COPY_FILE_SPLICE ) {
1430
+ /* cross sb splice is allowed */
1431
+ } else if (file_out -> f_op -> copy_file_range ) {
1428
1432
if (file_in -> f_op -> copy_file_range !=
1429
1433
file_out -> f_op -> copy_file_range )
1430
1434
return - EXDEV ;
@@ -1474,8 +1478,9 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
1474
1478
size_t len , unsigned int flags )
1475
1479
{
1476
1480
ssize_t ret ;
1481
+ bool splice = flags & COPY_FILE_SPLICE ;
1477
1482
1478
- if (flags != 0 )
1483
+ if (flags & ~ COPY_FILE_SPLICE )
1479
1484
return - EINVAL ;
1480
1485
1481
1486
ret = generic_copy_file_checks (file_in , pos_in , file_out , pos_out , & len ,
@@ -1501,14 +1506,14 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
1501
1506
* same sb using clone, but for filesystems where both clone and copy
1502
1507
* are supported (e.g. nfs,cifs), we only call the copy method.
1503
1508
*/
1504
- if (file_out -> f_op -> copy_file_range ) {
1509
+ if (! splice && file_out -> f_op -> copy_file_range ) {
1505
1510
ret = file_out -> f_op -> copy_file_range (file_in , pos_in ,
1506
1511
file_out , pos_out ,
1507
1512
len , flags );
1508
1513
goto done ;
1509
1514
}
1510
1515
1511
- if (file_in -> f_op -> remap_file_range &&
1516
+ if (! splice && file_in -> f_op -> remap_file_range &&
1512
1517
file_inode (file_in )-> i_sb == file_inode (file_out )-> i_sb ) {
1513
1518
ret = file_in -> f_op -> remap_file_range (file_in , pos_in ,
1514
1519
file_out , pos_out ,
@@ -1528,6 +1533,8 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
1528
1533
* consistent story about which filesystems support copy_file_range()
1529
1534
* and which filesystems do not, that will allow userspace tools to
1530
1535
* make consistent desicions w.r.t using copy_file_range().
1536
+ *
1537
+ * We also get here if caller (e.g. nfsd) requested COPY_FILE_SPLICE.
1531
1538
*/
1532
1539
ret = generic_copy_file_range (file_in , pos_in , file_out , pos_out , len ,
1533
1540
flags );
@@ -1582,6 +1589,10 @@ SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in,
1582
1589
pos_out = f_out .file -> f_pos ;
1583
1590
}
1584
1591
1592
+ ret = - EINVAL ;
1593
+ if (flags != 0 )
1594
+ goto out ;
1595
+
1585
1596
ret = vfs_copy_file_range (f_in .file , pos_in , f_out .file , pos_out , len ,
1586
1597
flags );
1587
1598
if (ret > 0 ) {
0 commit comments