From: Pankaj Raghav <p.raghav@xxxxxxxxxxx> When huge_page=always is set in tmpfs, it will zero out the whole page even if only a small part of it is written, and it updates the uptodate flag of the whole huge page. Once the per-block uptodate tracking is implemented for tmpfs hugepages, pipe_buf_confirm only needs to check the range it needs to splice to be uptodate and not the whole folio as we don't set uptodate flag for partial writes. Signed-off-by: Pankaj Raghav <p.raghav@xxxxxxxxxxx> Signed-off-by: Daniel Gomez <da.gomez@xxxxxxxxxxx> --- Other option here is to have a separate implementation of page_cache_pipe_buf_ops for tmpfs instead of changing the page_cache_pipe_buf_confirm. fs/splice.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fs/splice.c b/fs/splice.c index 218e24b1ac40..e6ac57795590 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -120,7 +120,9 @@ static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { struct folio *folio = page_folio(buf->page); + const struct address_space_operations *ops; int err; + off_t off = folio_page_idx(folio, buf->page) * PAGE_SIZE + buf->offset; if (!folio_test_uptodate(folio)) { folio_lock(folio); @@ -134,12 +136,21 @@ static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe, goto error; } + ops = folio->mapping->a_ops; /* * Uh oh, read-error from disk. */ - if (!folio_test_uptodate(folio)) { - err = -EIO; - goto error; + if (!ops->is_partially_uptodate) { + if (!folio_test_uptodate(folio)) { + err = -EIO; + goto error; + } + } else { + if (!ops->is_partially_uptodate(folio, off, + buf->len)) { + err = -EIO; + goto error; + } } /* Folio is ok after all, we are done */ -- 2.43.0