[PATCH 07/12] shmem: check if a block is uptodate before splice into pipe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The splice_read() path assumes folios are always uptodate. Make sure
all blocks in the given range are uptodate or else, splice zeropage into
the pipe. Maximize the number of blocks that can be spliced into pipe at
once by increasing the 'part' to the latest uptodate block found.

Signed-off-by: Daniel Gomez <da.gomez@xxxxxxxxxxx>
---
 mm/shmem.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 68fe769d91b1..e06cb6438ef8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3223,8 +3223,30 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
 		if (unlikely(*ppos >= isize))
 			break;
 		part = min_t(loff_t, isize - *ppos, len);
+		if (folio && folio_test_large(folio) &&
+		    folio_test_private(folio)) {
+			unsigned long from = offset_in_folio(folio, *ppos);
+			unsigned int bfirst = from >> inode->i_blkbits;
+			unsigned int blast, blast_upd;
+
+			len = min(folio_size(folio) - from, len);
+			blast = (from + len - 1) >> inode->i_blkbits;
+
+			blast_upd = sfs_get_last_block_uptodate(folio, bfirst,
+								blast);
+			if (blast_upd <= blast) {
+				unsigned int bsize = 1 << inode->i_blkbits;
+				unsigned int blks = blast_upd - bfirst + 1;
+				unsigned int bbytes = blks << inode->i_blkbits;
+				unsigned int boff = (*ppos % bsize);
+
+				part = min_t(loff_t, bbytes - boff, len);
+			}
+		}
 
-		if (folio) {
+		if (folio && shmem_is_block_uptodate(
+				     folio, offset_in_folio(folio, *ppos) >>
+						    inode->i_blkbits)) {
 			/*
 			 * If users can be writing to this page using arbitrary
 			 * virtual addresses, take care about potential aliasing
-- 
2.43.0





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux