[PATCH 1/7] filemap: Export filemap_invalidate_pages() to modules

"Matthew Wilcox (Oracle)" <[email protected]>
Newsgroups org.kernel.vger.linux-btrfs,dev.linux.lists.fuse-devel,org.kernel.vger.linux-block,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, &sector, &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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.