@@ -1745,6 +1745,69 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
1745
1745
return ret ;
1746
1746
}
1747
1747
1748
+ /*
1749
+ * Wrap filemap_splice_read with checks for cap bits on the inode.
1750
+ * Atomically grab references, so that those bits are not released
1751
+ * back to the MDS mid-read.
1752
+ */
1753
+ static ssize_t ceph_splice_read (struct file * in , loff_t * ppos ,
1754
+ struct pipe_inode_info * pipe ,
1755
+ size_t len , unsigned int flags )
1756
+ {
1757
+ struct ceph_file_info * fi = in -> private_data ;
1758
+ struct inode * inode = file_inode (in );
1759
+ struct ceph_inode_info * ci = ceph_inode (inode );
1760
+ ssize_t ret ;
1761
+ int want = 0 , got = 0 ;
1762
+ CEPH_DEFINE_RW_CONTEXT (rw_ctx , 0 );
1763
+
1764
+ dout ("splice_read %p %llx.%llx %llu~%zu trying to get caps on %p\n" ,
1765
+ inode , ceph_vinop (inode ), * ppos , len , inode );
1766
+
1767
+ if (ceph_inode_is_shutdown (inode ))
1768
+ return - ESTALE ;
1769
+
1770
+ if (ceph_has_inline_data (ci ) ||
1771
+ (fi -> flags & CEPH_F_SYNC ))
1772
+ return copy_splice_read (in , ppos , pipe , len , flags );
1773
+
1774
+ ceph_start_io_read (inode );
1775
+
1776
+ want = CEPH_CAP_FILE_CACHE ;
1777
+ if (fi -> fmode & CEPH_FILE_MODE_LAZY )
1778
+ want |= CEPH_CAP_FILE_LAZYIO ;
1779
+
1780
+ ret = ceph_get_caps (in , CEPH_CAP_FILE_RD , want , -1 , & got );
1781
+ if (ret < 0 )
1782
+ goto out_end ;
1783
+
1784
+ if ((got & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO )) == 0 ) {
1785
+ dout ("splice_read/sync %p %llx.%llx %llu~%zu got cap refs on %s\n" ,
1786
+ inode , ceph_vinop (inode ), * ppos , len ,
1787
+ ceph_cap_string (got ));
1788
+
1789
+ ceph_put_cap_refs (ci , got );
1790
+ ceph_end_io_read (inode );
1791
+ return copy_splice_read (in , ppos , pipe , len , flags );
1792
+ }
1793
+
1794
+ dout ("splice_read %p %llx.%llx %llu~%zu got cap refs on %s\n" ,
1795
+ inode , ceph_vinop (inode ), * ppos , len , ceph_cap_string (got ));
1796
+
1797
+ rw_ctx .caps = got ;
1798
+ ceph_add_rw_context (fi , & rw_ctx );
1799
+ ret = filemap_splice_read (in , ppos , pipe , len , flags );
1800
+ ceph_del_rw_context (fi , & rw_ctx );
1801
+
1802
+ dout ("splice_read %p %llx.%llx dropping cap refs on %s = %zd\n" ,
1803
+ inode , ceph_vinop (inode ), ceph_cap_string (got ), ret );
1804
+
1805
+ ceph_put_cap_refs (ci , got );
1806
+ out_end :
1807
+ ceph_end_io_read (inode );
1808
+ return ret ;
1809
+ }
1810
+
1748
1811
/*
1749
1812
* Take cap references to avoid releasing caps to MDS mid-write.
1750
1813
*
@@ -2593,7 +2656,7 @@ const struct file_operations ceph_file_fops = {
2593
2656
.lock = ceph_lock ,
2594
2657
.setlease = simple_nosetlease ,
2595
2658
.flock = ceph_flock ,
2596
- .splice_read = generic_file_splice_read ,
2659
+ .splice_read = ceph_splice_read ,
2597
2660
.splice_write = iter_file_splice_write ,
2598
2661
.unlocked_ioctl = ceph_ioctl ,
2599
2662
.compat_ioctl = compat_ptr_ioctl ,
0 commit comments