[PATCH 1/7] filemap: Export filemap_invalidate_pages() to modules
"Matthew Wilcox (Oracle)" <[email protected]>
| Newsgroups | org.kernel.vger.linux-block,dev.linux.lists.fuse-devel,org.kernel.vger.linux-btrfs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-nfs,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
This is a better API for filesystems to use than invalidate_inode_pages2() / invalidate_inode_pages2_range(). However, the 'nowait' argument is unnecessary for them. It's also wrongly implemented as it will call invalidate_inode_pages2_range() even after filemap_range_has_page() returns false. Move the filemap_range_has_page() call into the two existing callers and add kernel-doc. Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> --- block/ioctl.c | 14 ++++++++++---- include/linux/pagemap.h | 2 +- mm/filemap.c | 42 +++++++++++++++++++++++++++-------------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index 3d4ea1537457..db5238b817b4 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -908,10 +908,16 @@ static int blkdev_cmd_discard(struct io_uring_cmd *cmd, if (err) return err; - err = filemap_invalidate_pages(bdev->bd_mapping, start, - start + len - 1, nowait); - if (err) - return err; + if (nowait) { + if (filemap_range_has_page(bdev->bd_mapping, start, + start + len - 1)) + return -EAGAIN; + } else { + err = filemap_invalidate_pages(bdev->bd_mapping, start, + start + len - 1); + if (err) + return err; + } while (true) { bio = blk_alloc_discard_bio(bdev, §or, &nr_sects, gfp); diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 2c3718d592d6..ed99c8ab196a 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -33,7 +33,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, int kiocb_invalidate_pages(struct kiocb *iocb, size_t count); void kiocb_invalidate_post_direct_write(struct kiocb *iocb, size_t count); int filemap_invalidate_pages(struct address_space *mapping, - loff_t pos, loff_t end, bool nowait); + loff_t pos, loff_t end); int write_inode_now(struct inode *, int sync); int filemap_fdatawrite(struct address_space *); diff --git a/mm/filemap.c b/mm/filemap.c index d721986d5f46..fedb521d773f 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2911,20 +2911,27 @@ int kiocb_write_and_wait(struct kiocb *iocb, size_t count) } EXPORT_SYMBOL_GPL(kiocb_write_and_wait); +/** + * filemap_invalidate_pages - Invalidate pages from the page cache + * @mapping: Address space to invalidate + * @pos: First byte to invalidate + * @end: Last byte (inclusive) to invalidate + * + * Invalidates the folios containing @pos and @end from the page cache + * (as well as all folios between them), so may remove more pages from + * the page cache than you ask for. + * + * Context: May sleep. Caller may wish to hold mapping_invalidate_lock to + * prevent new pages being instantiated in this range. + * Return: 0 on success or negative errno. + */ int filemap_invalidate_pages(struct address_space *mapping, - loff_t pos, loff_t end, bool nowait) + loff_t pos, loff_t end) { - int ret; + int ret = filemap_write_and_wait_range(mapping, pos, end); - if (nowait) { - /* we could block if there are any pages in the range */ - if (filemap_range_has_page(mapping, pos, end)) - return -EAGAIN; - } else { - ret = filemap_write_and_wait_range(mapping, pos, end); - if (ret) - return ret; - } + if (ret) + return ret; /* * After a write we want buffered reads to be sure to go to disk to get @@ -2935,14 +2942,21 @@ int filemap_invalidate_pages(struct address_space *mapping, return invalidate_inode_pages2_range(mapping, pos >> PAGE_SHIFT, end >> PAGE_SHIFT); } +EXPORT_SYMBOL_GPL(filemap_invalidate_pages); int kiocb_invalidate_pages(struct kiocb *iocb, size_t count) { struct address_space *mapping = iocb->ki_filp->f_mapping; + loff_t end = iocb->ki_pos + count - 1; + + if (iocb->ki_flags & IOCB_NOWAIT) { + /* we could block if there are any pages in the range */ + if (filemap_range_has_page(mapping, iocb->ki_pos, end)) + return -EAGAIN; + return 0; + } - return filemap_invalidate_pages(mapping, iocb->ki_pos, - iocb->ki_pos + count - 1, - iocb->ki_flags & IOCB_NOWAIT); + return filemap_invalidate_pages(mapping, iocb->ki_pos, end); } EXPORT_SYMBOL_GPL(kiocb_invalidate_pages); -- 2.47.3