Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs fix from Al Viro:
"Amir's copy_file_range() fix"

* tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
vfs: fix copy_file_range() averts filesystem freeze protection

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