An authoritative mapping knows about all the folios in the mapping. If read() finds a missing folio, there's no reason to allocate one and try to read it because we know it's a zero region of the file. We can just call iov_iter_zero() instead. Signed-off-by: Matthew Wilcox (Oracle) --- include/linux/pagemap.h | 11 +++++++++++ mm/filemap.c | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 346b77fa95ef..bd6a6275a4e9 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -210,6 +210,7 @@ enum mapping_flags { AS_WRITEBACK_MAY_DEADLOCK_ON_RECLAIM = 9, AS_KERNEL_FILE = 10, /* mapping for a fake kernel file that shouldn't account usage to user cgroups */ + AS_AUTHORITATIVE = 11, /* If we miss in the page cache, it's a hole */ /* Bits 16-25 are used for FOLIO_ORDER */ AS_FOLIO_ORDER_BITS = 5, AS_FOLIO_ORDER_MIN = 16, @@ -345,6 +346,16 @@ static inline bool mapping_writeback_may_deadlock_on_reclaim(const struct addres return test_bit(AS_WRITEBACK_MAY_DEADLOCK_ON_RECLAIM, &mapping->flags); } +static inline void mapping_set_authoritative(struct address_space *mapping) +{ + set_bit(AS_AUTHORITATIVE, &mapping->flags); +} + +static inline bool mapping_is_authoritative(const struct address_space *mapping) +{ + return test_bit(AS_AUTHORITATIVE, &mapping->flags); +} + static inline gfp_t mapping_gfp_mask(const struct address_space *mapping) { return mapping->gfp_mask; diff --git a/mm/filemap.c b/mm/filemap.c index 0f3ada4d8cff..f662cda81dc7 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2697,6 +2697,8 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, if (!folio_batch_count(fbatch)) { DEFINE_READAHEAD(ractl, filp, &filp->f_ra, mapping, index); + if (mapping_is_authoritative(mapping)) + return 0; if (iocb->ki_flags & IOCB_NOIO) return -EAGAIN; if (iocb->ki_flags & IOCB_NOWAIT) @@ -2853,6 +2855,22 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, goto put_folios; end_offset = min_t(loff_t, isize, iocb->ki_pos + iter->count); + if (!folio_batch_count(&fbatch)) { + size_t fsize = mapping_min_folio_nrbytes(mapping); + size_t offset = iocb->ki_pos & (fsize - 1); + size_t bytes = min_t(loff_t, end_offset - iocb->ki_pos, + fsize - offset); + size_t copied = iov_iter_zero(bytes, iter); + + already_read += copied; + iocb->ki_pos += copied; + last_pos = iocb->ki_pos; + + if (copied < bytes) + error = -EFAULT; + continue; + } + /* * Once we start copying data, we don't want to be touching any * cachelines that might be contended: -- 2.47.3