linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v15 00/17] Folio support in block + iomap layers
@ 2021-07-19 18:39 Matthew Wilcox (Oracle)
  2021-07-19 18:39 ` [PATCH v15 01/17] block: Add bio_add_folio() Matthew Wilcox (Oracle)
                   ` (17 more replies)
  0 siblings, 18 replies; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle), linux-mm, linux-block

This is (almost) everything necessary to support folios in iomap.
No regressions with an xfstests run on my setup.

v15:
 - Turn the / PAGE_SIZE into >> PAGE_SHIFT, as requested by Darrick
 - Modify the for loop to be in Darrick's preferred form
 - Improve documentation of bio_add_folio()
 - Add documentation for bio_for_each_folio_all() and folio_iter
 - Add bio.h to the generated kernel-doc
 - Rebase on top of folio for-next (which includes the iomap changes in -rc2)
   https://git.infradead.org/users/willy/pagecache.git/shortlog/refs/heads/for-next

Matthew Wilcox (Oracle) (17):
  block: Add bio_add_folio()
  block: Add bio_for_each_folio_all()
  iomap: Convert to_iomap_page to take a folio
  iomap: Convert iomap_page_create to take a folio
  iomap: Convert iomap_page_release to take a folio
  iomap: Convert iomap_releasepage to use a folio
  iomap: Convert iomap_invalidatepage to use a folio
  iomap: Pass the iomap_page into iomap_set_range_uptodate
  iomap: Use folio offsets instead of page offsets
  iomap: Convert bio completions to use folios
  iomap: Convert readahead and readpage to use a folio
  iomap: Convert iomap_page_mkwrite to use a folio
  iomap: Convert iomap_write_begin and iomap_write_end to folios
  iomap: Convert iomap_read_inline_data to take a folio
  iomap: Convert iomap_write_end_inline to take a folio
  iomap: Convert iomap_add_to_ioend to take a folio
  iomap: Convert iomap_migrate_page to use folios

 Documentation/core-api/kernel-api.rst |   1 +
 block/bio.c                           |  21 ++
 fs/iomap/buffered-io.c                | 511 +++++++++++++-------------
 include/linux/bio.h                   |  56 ++-
 4 files changed, 327 insertions(+), 262 deletions(-)

-- 
2.30.2



^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH v15 01/17] block: Add bio_add_folio()
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  1:28   ` Darrick J. Wong
                     ` (2 more replies)
  2021-07-19 18:39 ` [PATCH v15 02/17] block: Add bio_for_each_folio_all() Matthew Wilcox (Oracle)
                   ` (16 subsequent siblings)
  17 siblings, 3 replies; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle), linux-mm, linux-block

This is a thin wrapper around bio_add_page().  The main advantage here
is the documentation that the submitter can expect to see folios in the
completion handler, and that stupidly large folios are not supported.
It's not currently possible to allocate stupidly large folios, but if
it ever becomes possible, this function will fail gracefully instead of
doing I/O to the wrong bytes.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 block/bio.c         | 21 +++++++++++++++++++++
 include/linux/bio.h |  3 ++-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/block/bio.c b/block/bio.c
index 1fab762e079b..c64e35548fb2 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -933,6 +933,27 @@ int bio_add_page(struct bio *bio, struct page *page,
 }
 EXPORT_SYMBOL(bio_add_page);
 
+/**
+ * bio_add_folio - Attempt to add part of a folio to a bio.
+ * @bio: Bio to add to.
+ * @folio: Folio to add.
+ * @len: How many bytes from the folio to add.
+ * @off: First byte in this folio to add.
+ *
+ * Always uses the head page of the folio in the bio.  If a submitter only
+ * uses bio_add_folio(), it can count on never seeing tail pages in the
+ * completion routine.  BIOs do not support folios that are 4GiB or larger.
+ *
+ * Return: The number of bytes from this folio added to the bio.
+ */
+size_t bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
+		size_t off)
+{
+	if (len > UINT_MAX || off > UINT_MAX)
+		return 0;
+	return bio_add_page(bio, &folio->page, len, off);
+}
+
 void bio_release_pages(struct bio *bio, bool mark_dirty)
 {
 	struct bvec_iter_all iter_all;
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 2203b686e1f0..ade93e2de6a1 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -462,7 +462,8 @@ extern void bio_uninit(struct bio *);
 extern void bio_reset(struct bio *);
 void bio_chain(struct bio *, struct bio *);
 
-extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
+int bio_add_page(struct bio *, struct page *, unsigned len, unsigned off);
+size_t bio_add_folio(struct bio *, struct folio *, size_t len, size_t off);
 extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
 			   unsigned int, unsigned int);
 int bio_add_zone_append_page(struct bio *bio, struct page *page,
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 02/17] block: Add bio_for_each_folio_all()
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
  2021-07-19 18:39 ` [PATCH v15 01/17] block: Add bio_add_folio() Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  1:29   ` Darrick J. Wong
                     ` (4 more replies)
  2021-07-19 18:39 ` [PATCH v15 03/17] iomap: Convert to_iomap_page to take a folio Matthew Wilcox (Oracle)
                   ` (15 subsequent siblings)
  17 siblings, 5 replies; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle), linux-mm, linux-block

Allow callers to iterate over each folio instead of each page.  The
bio need not have been constructed using folios originally.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 Documentation/core-api/kernel-api.rst |  1 +
 include/linux/bio.h                   | 53 ++++++++++++++++++++++++++-
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst
index 2a7444e3a4c2..b804605f705e 100644
--- a/Documentation/core-api/kernel-api.rst
+++ b/Documentation/core-api/kernel-api.rst
@@ -279,6 +279,7 @@ Accounting Framework
 Block Devices
 =============
 
+.. kernel-doc:: include/linux/bio.h
 .. kernel-doc:: block/blk-core.c
    :export:
 
diff --git a/include/linux/bio.h b/include/linux/bio.h
index ade93e2de6a1..a90a79ad7bd1 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -189,7 +189,7 @@ static inline void bio_advance_iter_single(const struct bio *bio,
  */
 #define bio_for_each_bvec_all(bvl, bio, i)		\
 	for (i = 0, bvl = bio_first_bvec_all(bio);	\
-	     i < (bio)->bi_vcnt; i++, bvl++)		\
+	     i < (bio)->bi_vcnt; i++, bvl++)
 
 #define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len)
 
@@ -314,6 +314,57 @@ static inline struct bio_vec *bio_last_bvec_all(struct bio *bio)
 	return &bio->bi_io_vec[bio->bi_vcnt - 1];
 }
 
+/**
+ * struct folio_iter - State for iterating all folios in a bio.
+ * @folio: The current folio we're iterating.  NULL after the last folio.
+ * @offset: The byte offset within the current folio.
+ * @length: The number of bytes in this iteration (will not cross folio
+ *	boundary).
+ */
+struct folio_iter {
+	struct folio *folio;
+	size_t offset;
+	size_t length;
+	/* private: for use by the iterator */
+	size_t _seg_count;
+	int _i;
+};
+
+static inline
+void bio_first_folio(struct folio_iter *fi, struct bio *bio, int i)
+{
+	struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
+
+	fi->folio = page_folio(bvec->bv_page);
+	fi->offset = bvec->bv_offset +
+			PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
+	fi->_seg_count = bvec->bv_len;
+	fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
+	fi->_i = i;
+}
+
+static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
+{
+	fi->_seg_count -= fi->length;
+	if (fi->_seg_count) {
+		fi->folio = folio_next(fi->folio);
+		fi->offset = 0;
+		fi->length = min(folio_size(fi->folio), fi->_seg_count);
+	} else if (fi->_i + 1 < bio->bi_vcnt) {
+		bio_first_folio(fi, bio, fi->_i + 1);
+	} else {
+		fi->folio = NULL;
+	}
+}
+
+/**
+ * bio_for_each_folio_all - Iterate over each folio in a bio.
+ * @fi: struct folio_iter which is updated for each folio.
+ * @bio: struct bio to iterate over.
+ */
+#define bio_for_each_folio_all(fi, bio)				\
+	for (bio_first_folio(&fi, bio, 0); fi.folio; bio_next_folio(&fi, bio))
+
 enum bip_flags {
 	BIP_BLOCK_INTEGRITY	= 1 << 0, /* block layer owns integrity data */
 	BIP_MAPPED_INTEGRITY	= 1 << 1, /* ref tag has been remapped */
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 03/17] iomap: Convert to_iomap_page to take a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
  2021-07-19 18:39 ` [PATCH v15 01/17] block: Add bio_add_folio() Matthew Wilcox (Oracle)
  2021-07-19 18:39 ` [PATCH v15 02/17] block: Add bio_for_each_folio_all() Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  6:49   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 04/17] iomap: Convert iomap_page_create " Matthew Wilcox (Oracle)
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

The big comment about only using a head page can go away now that
it takes a folio argument.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 87ccb3438bec..d4870a2691f9 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -22,8 +22,8 @@
 #include "../internal.h"
 
 /*
- * Structure allocated for each page or THP when block size < page size
- * to track sub-page uptodate status and I/O completions.
+ * Structure allocated for each folio when block size < folio size
+ * to track sub-folio uptodate status and I/O completions.
  */
 struct iomap_page {
 	atomic_t		read_bytes_pending;
@@ -32,17 +32,10 @@ struct iomap_page {
 	unsigned long		uptodate[];
 };
 
-static inline struct iomap_page *to_iomap_page(struct page *page)
+static inline struct iomap_page *to_iomap_page(struct folio *folio)
 {
-	/*
-	 * per-block data is stored in the head page.  Callers should
-	 * not be dealing with tail pages (and if they are, they can
-	 * call thp_head() first.
-	 */
-	VM_BUG_ON_PGFLAGS(PageTail(page), page);
-
-	if (page_has_private(page))
-		return (struct iomap_page *)page_private(page);
+	if (folio_test_private(folio))
+		return folio_get_private(folio);
 	return NULL;
 }
 
@@ -51,7 +44,8 @@ static struct bio_set iomap_ioend_bioset;
 static struct iomap_page *
 iomap_page_create(struct inode *inode, struct page *page)
 {
-	struct iomap_page *iop = to_iomap_page(page);
+	struct folio *folio = page_folio(page);
+	struct iomap_page *iop = to_iomap_page(folio);
 	unsigned int nr_blocks = i_blocks_per_page(inode, page);
 
 	if (iop || nr_blocks <= 1)
@@ -144,7 +138,8 @@ iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
 static void
 iomap_iop_set_range_uptodate(struct page *page, unsigned off, unsigned len)
 {
-	struct iomap_page *iop = to_iomap_page(page);
+	struct folio *folio = page_folio(page);
+	struct iomap_page *iop = to_iomap_page(folio);
 	struct inode *inode = page->mapping->host;
 	unsigned first = off >> inode->i_blkbits;
 	unsigned last = (off + len - 1) >> inode->i_blkbits;
@@ -173,7 +168,8 @@ static void
 iomap_read_page_end_io(struct bio_vec *bvec, int error)
 {
 	struct page *page = bvec->bv_page;
-	struct iomap_page *iop = to_iomap_page(page);
+	struct folio *folio = page_folio(page);
+	struct iomap_page *iop = to_iomap_page(folio);
 
 	if (unlikely(error)) {
 		ClearPageUptodate(page);
@@ -435,7 +431,8 @@ int
 iomap_is_partially_uptodate(struct page *page, unsigned long from,
 		unsigned long count)
 {
-	struct iomap_page *iop = to_iomap_page(page);
+	struct folio *folio = page_folio(page);
+	struct iomap_page *iop = to_iomap_page(folio);
 	struct inode *inode = page->mapping->host;
 	unsigned len, first, last;
 	unsigned i;
@@ -1012,7 +1009,8 @@ static void
 iomap_finish_page_writeback(struct inode *inode, struct page *page,
 		int error, unsigned int len)
 {
-	struct iomap_page *iop = to_iomap_page(page);
+	struct folio *folio = page_folio(page);
+	struct iomap_page *iop = to_iomap_page(folio);
 
 	if (error) {
 		SetPageError(page);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 04/17] iomap: Convert iomap_page_create to take a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (2 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 03/17] iomap: Convert to_iomap_page to take a folio Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  6:50   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 05/17] iomap: Convert iomap_page_release " Matthew Wilcox (Oracle)
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

This function already assumed it was being passed a head page, so
just formalise that.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index d4870a2691f9..ec8bdc0c63df 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -42,11 +42,10 @@ static inline struct iomap_page *to_iomap_page(struct folio *folio)
 static struct bio_set iomap_ioend_bioset;
 
 static struct iomap_page *
-iomap_page_create(struct inode *inode, struct page *page)
+iomap_page_create(struct inode *inode, struct folio *folio)
 {
-	struct folio *folio = page_folio(page);
 	struct iomap_page *iop = to_iomap_page(folio);
-	unsigned int nr_blocks = i_blocks_per_page(inode, page);
+	unsigned int nr_blocks = i_blocks_per_folio(inode, folio);
 
 	if (iop || nr_blocks <= 1)
 		return iop;
@@ -54,9 +53,9 @@ iomap_page_create(struct inode *inode, struct page *page)
 	iop = kzalloc(struct_size(iop, uptodate, BITS_TO_LONGS(nr_blocks)),
 			GFP_NOFS | __GFP_NOFAIL);
 	spin_lock_init(&iop->uptodate_lock);
-	if (PageUptodate(page))
+	if (folio_test_uptodate(folio))
 		bitmap_fill(iop->uptodate, nr_blocks);
-	attach_page_private(page, iop);
+	folio_attach_private(folio, iop);
 	return iop;
 }
 
@@ -236,6 +235,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 {
 	struct iomap_readpage_ctx *ctx = data;
 	struct page *page = ctx->cur_page;
+	struct folio *folio = page_folio(page);
 	struct iomap_page *iop;
 	bool same_page = false, is_contig = false;
 	loff_t orig_pos = pos;
@@ -249,7 +249,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 	}
 
 	/* zero post-eof blocks as the page may be mapped */
-	iop = iomap_page_create(inode, page);
+	iop = iomap_page_create(inode, folio);
 	iomap_adjust_read_range(inode, iop, &pos, length, &poff, &plen);
 	if (plen == 0)
 		goto done;
@@ -549,7 +549,8 @@ static int
 __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
 		struct page *page, struct iomap *srcmap)
 {
-	struct iomap_page *iop = iomap_page_create(inode, page);
+	struct folio *folio = page_folio(page);
+	struct iomap_page *iop = iomap_page_create(inode, folio);
 	loff_t block_size = i_blocksize(inode);
 	loff_t block_start = round_down(pos, block_size);
 	loff_t block_end = round_up(pos + len, block_size);
@@ -1303,7 +1304,8 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
 		struct writeback_control *wbc, struct inode *inode,
 		struct page *page, u64 end_offset)
 {
-	struct iomap_page *iop = iomap_page_create(inode, page);
+	struct folio *folio = page_folio(page);
+	struct iomap_page *iop = iomap_page_create(inode, folio);
 	struct iomap_ioend *ioend, *next;
 	unsigned len = i_blocksize(inode);
 	u64 file_offset; /* file offset of page */
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 05/17] iomap: Convert iomap_page_release to take a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (3 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 04/17] iomap: Convert iomap_page_create " Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  6:52   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 06/17] iomap: Convert iomap_releasepage to use " Matthew Wilcox (Oracle)
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

iomap_page_release() was also assuming that it was being passed a
head page.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index ec8bdc0c63df..83eb5fdcbe05 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -59,18 +59,18 @@ iomap_page_create(struct inode *inode, struct folio *folio)
 	return iop;
 }
 
-static void
-iomap_page_release(struct page *page)
+static void iomap_page_release(struct folio *folio)
 {
-	struct iomap_page *iop = detach_page_private(page);
-	unsigned int nr_blocks = i_blocks_per_page(page->mapping->host, page);
+	struct iomap_page *iop = folio_detach_private(folio);
+	unsigned int nr_blocks = i_blocks_per_folio(folio->mapping->host,
+							folio);
 
 	if (!iop)
 		return;
 	WARN_ON_ONCE(atomic_read(&iop->read_bytes_pending));
 	WARN_ON_ONCE(atomic_read(&iop->write_bytes_pending));
 	WARN_ON_ONCE(bitmap_full(iop->uptodate, nr_blocks) !=
-			PageUptodate(page));
+			folio_test_uptodate(folio));
 	kfree(iop);
 }
 
@@ -458,6 +458,8 @@ EXPORT_SYMBOL_GPL(iomap_is_partially_uptodate);
 int
 iomap_releasepage(struct page *page, gfp_t gfp_mask)
 {
+	struct folio *folio = page_folio(page);
+
 	trace_iomap_releasepage(page->mapping->host, page_offset(page),
 			PAGE_SIZE);
 
@@ -468,7 +470,7 @@ iomap_releasepage(struct page *page, gfp_t gfp_mask)
 	 */
 	if (PageDirty(page) || PageWriteback(page))
 		return 0;
-	iomap_page_release(page);
+	iomap_page_release(folio);
 	return 1;
 }
 EXPORT_SYMBOL_GPL(iomap_releasepage);
@@ -476,6 +478,8 @@ EXPORT_SYMBOL_GPL(iomap_releasepage);
 void
 iomap_invalidatepage(struct page *page, unsigned int offset, unsigned int len)
 {
+	struct folio *folio = page_folio(page);
+
 	trace_iomap_invalidatepage(page->mapping->host, offset, len);
 
 	/*
@@ -485,7 +489,7 @@ iomap_invalidatepage(struct page *page, unsigned int offset, unsigned int len)
 	if (offset == 0 && len == PAGE_SIZE) {
 		WARN_ON_ONCE(PageWriteback(page));
 		cancel_dirty_page(page);
-		iomap_page_release(page);
+		iomap_page_release(folio);
 	}
 }
 EXPORT_SYMBOL_GPL(iomap_invalidatepage);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 06/17] iomap: Convert iomap_releasepage to use a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (4 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 05/17] iomap: Convert iomap_page_release " Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  6:54   ` Christoph Hellwig
  2021-07-20 23:56   ` Darrick J. Wong
  2021-07-19 18:39 ` [PATCH v15 07/17] iomap: Convert iomap_invalidatepage " Matthew Wilcox (Oracle)
                   ` (11 subsequent siblings)
  17 siblings, 2 replies; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle), linux-mm, linux-block

This is an address_space operation, so its argument must remain as a
struct page, but we can use a folio internally.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/iomap/buffered-io.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 83eb5fdcbe05..715b25a1c1e6 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -460,15 +460,15 @@ iomap_releasepage(struct page *page, gfp_t gfp_mask)
 {
 	struct folio *folio = page_folio(page);
 
-	trace_iomap_releasepage(page->mapping->host, page_offset(page),
-			PAGE_SIZE);
+	trace_iomap_releasepage(folio->mapping->host, folio_pos(folio),
+			folio_size(folio));
 
 	/*
 	 * mm accommodates an old ext3 case where clean pages might not have had
 	 * the dirty bit cleared. Thus, it can send actual dirty pages to
 	 * ->releasepage() via shrink_active_list(), skip those here.
 	 */
-	if (PageDirty(page) || PageWriteback(page))
+	if (folio_test_dirty(folio) || folio_test_writeback(folio))
 		return 0;
 	iomap_page_release(folio);
 	return 1;
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 07/17] iomap: Convert iomap_invalidatepage to use a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (5 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 06/17] iomap: Convert iomap_releasepage to use " Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  6:55   ` Christoph Hellwig
  2021-07-20 23:57   ` Darrick J. Wong
  2021-07-19 18:39 ` [PATCH v15 08/17] iomap: Pass the iomap_page into iomap_set_range_uptodate Matthew Wilcox (Oracle)
                   ` (10 subsequent siblings)
  17 siblings, 2 replies; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle), linux-mm, linux-block

This is an address_space operation, so its argument must remain as a
struct page, but we can use a folio internally.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/iomap/buffered-io.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 715b25a1c1e6..0d7b6ef4c5cc 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -480,15 +480,15 @@ iomap_invalidatepage(struct page *page, unsigned int offset, unsigned int len)
 {
 	struct folio *folio = page_folio(page);
 
-	trace_iomap_invalidatepage(page->mapping->host, offset, len);
+	trace_iomap_invalidatepage(folio->mapping->host, offset, len);
 
 	/*
 	 * If we are invalidating the entire page, clear the dirty state from it
 	 * and release it to avoid unnecessary buildup of the LRU.
 	 */
-	if (offset == 0 && len == PAGE_SIZE) {
-		WARN_ON_ONCE(PageWriteback(page));
-		cancel_dirty_page(page);
+	if (offset == 0 && len == folio_size(folio)) {
+		WARN_ON_ONCE(folio_test_writeback(folio));
+		folio_cancel_dirty(folio);
 		iomap_page_release(folio);
 	}
 }
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 08/17] iomap: Pass the iomap_page into iomap_set_range_uptodate
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (6 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 07/17] iomap: Convert iomap_invalidatepage " Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  6:57   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 09/17] iomap: Use folio offsets instead of page offsets Matthew Wilcox (Oracle)
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

All but one caller already has the iomap_page, and we can avoid getting
it again.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 0d7b6ef4c5cc..62d8ebcda429 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -134,11 +134,9 @@ iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
 	*lenp = plen;
 }
 
-static void
-iomap_iop_set_range_uptodate(struct page *page, unsigned off, unsigned len)
+static void iomap_iop_set_range_uptodate(struct page *page,
+		struct iomap_page *iop, unsigned off, unsigned len)
 {
-	struct folio *folio = page_folio(page);
-	struct iomap_page *iop = to_iomap_page(folio);
 	struct inode *inode = page->mapping->host;
 	unsigned first = off >> inode->i_blkbits;
 	unsigned last = (off + len - 1) >> inode->i_blkbits;
@@ -151,14 +149,14 @@ iomap_iop_set_range_uptodate(struct page *page, unsigned off, unsigned len)
 	spin_unlock_irqrestore(&iop->uptodate_lock, flags);
 }
 
-static void
-iomap_set_range_uptodate(struct page *page, unsigned off, unsigned len)
+static void iomap_set_range_uptodate(struct page *page,
+		struct iomap_page *iop, unsigned off, unsigned len)
 {
 	if (PageError(page))
 		return;
 
-	if (page_has_private(page))
-		iomap_iop_set_range_uptodate(page, off, len);
+	if (iop)
+		iomap_iop_set_range_uptodate(page, iop, off, len);
 	else
 		SetPageUptodate(page);
 }
@@ -174,7 +172,8 @@ iomap_read_page_end_io(struct bio_vec *bvec, int error)
 		ClearPageUptodate(page);
 		SetPageError(page);
 	} else {
-		iomap_set_range_uptodate(page, bvec->bv_offset, bvec->bv_len);
+		iomap_set_range_uptodate(page, iop, bvec->bv_offset,
+						bvec->bv_len);
 	}
 
 	if (!iop || atomic_sub_and_test(bvec->bv_len, &iop->read_bytes_pending))
@@ -256,7 +255,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 
 	if (iomap_block_needs_zeroing(inode, iomap, pos)) {
 		zero_user(page, poff, plen);
-		iomap_set_range_uptodate(page, poff, plen);
+		iomap_set_range_uptodate(page, iop, poff, plen);
 		goto done;
 	}
 
@@ -585,7 +584,7 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
 			if (status)
 				return status;
 		}
-		iomap_set_range_uptodate(page, poff, plen);
+		iomap_set_range_uptodate(page, iop, poff, plen);
 	} while ((block_start += plen) < block_end);
 
 	return 0;
@@ -647,6 +646,8 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
 static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
 		size_t copied, struct page *page)
 {
+	struct folio *folio = page_folio(page);
+	struct iomap_page *iop = to_iomap_page(folio);
 	flush_dcache_page(page);
 
 	/*
@@ -662,7 +663,7 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
 	 */
 	if (unlikely(copied < len && !PageUptodate(page)))
 		return 0;
-	iomap_set_range_uptodate(page, offset_in_page(pos), len);
+	iomap_set_range_uptodate(page, iop, offset_in_page(pos), len);
 	__set_page_dirty_nobuffers(page);
 	return copied;
 }
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 09/17] iomap: Use folio offsets instead of page offsets
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (7 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 08/17] iomap: Pass the iomap_page into iomap_set_range_uptodate Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  6:59   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 10/17] iomap: Convert bio completions to use folios Matthew Wilcox (Oracle)
                   ` (8 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

Pass a folio around instead of the page, and make sure the offset
is relative to the start of the folio instead of the start of a page.
Also use size_t for offset & length to make it clear that these are byte
counts, and to support >2GB folios in the future.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 83 ++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 40 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 62d8ebcda429..0f70bd185c2a 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -75,18 +75,18 @@ static void iomap_page_release(struct folio *folio)
 }
 
 /*
- * Calculate the range inside the page that we actually need to read.
+ * Calculate the range inside the folio that we actually need to read.
  */
-static void
-iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
-		loff_t *pos, loff_t length, unsigned *offp, unsigned *lenp)
+static void iomap_adjust_read_range(struct inode *inode, struct folio *folio,
+		loff_t *pos, loff_t length, size_t *offp, size_t *lenp)
 {
+	struct iomap_page *iop = to_iomap_page(folio);
 	loff_t orig_pos = *pos;
 	loff_t isize = i_size_read(inode);
 	unsigned block_bits = inode->i_blkbits;
 	unsigned block_size = (1 << block_bits);
-	unsigned poff = offset_in_page(*pos);
-	unsigned plen = min_t(loff_t, PAGE_SIZE - poff, length);
+	size_t poff = offset_in_folio(folio, *pos);
+	size_t plen = min_t(loff_t, folio_size(folio) - poff, length);
 	unsigned first = poff >> block_bits;
 	unsigned last = (poff + plen - 1) >> block_bits;
 
@@ -124,7 +124,7 @@ iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
 	 * page cache for blocks that are entirely outside of i_size.
 	 */
 	if (orig_pos <= isize && orig_pos + length > isize) {
-		unsigned end = offset_in_page(isize - 1) >> block_bits;
+		unsigned end = offset_in_folio(folio, isize - 1) >> block_bits;
 
 		if (first <= end && last > end)
 			plen -= (last - end) * block_size;
@@ -134,31 +134,31 @@ iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
 	*lenp = plen;
 }
 
-static void iomap_iop_set_range_uptodate(struct page *page,
-		struct iomap_page *iop, unsigned off, unsigned len)
+static void iomap_iop_set_range_uptodate(struct folio *folio,
+		struct iomap_page *iop, size_t off, size_t len)
 {
-	struct inode *inode = page->mapping->host;
+	struct inode *inode = folio->mapping->host;
 	unsigned first = off >> inode->i_blkbits;
 	unsigned last = (off + len - 1) >> inode->i_blkbits;
 	unsigned long flags;
 
 	spin_lock_irqsave(&iop->uptodate_lock, flags);
 	bitmap_set(iop->uptodate, first, last - first + 1);
-	if (bitmap_full(iop->uptodate, i_blocks_per_page(inode, page)))
-		SetPageUptodate(page);
+	if (bitmap_full(iop->uptodate, i_blocks_per_folio(inode, folio)))
+		folio_mark_uptodate(folio);
 	spin_unlock_irqrestore(&iop->uptodate_lock, flags);
 }
 
-static void iomap_set_range_uptodate(struct page *page,
-		struct iomap_page *iop, unsigned off, unsigned len)
+static void iomap_set_range_uptodate(struct folio *folio,
+		struct iomap_page *iop, size_t off, size_t len)
 {
-	if (PageError(page))
+	if (folio_test_error(folio))
 		return;
 
 	if (iop)
-		iomap_iop_set_range_uptodate(page, iop, off, len);
+		iomap_iop_set_range_uptodate(folio, iop, off, len);
 	else
-		SetPageUptodate(page);
+		folio_mark_uptodate(folio);
 }
 
 static void
@@ -169,15 +169,17 @@ iomap_read_page_end_io(struct bio_vec *bvec, int error)
 	struct iomap_page *iop = to_iomap_page(folio);
 
 	if (unlikely(error)) {
-		ClearPageUptodate(page);
-		SetPageError(page);
+		folio_clear_uptodate(folio);
+		folio_set_error(folio);
 	} else {
-		iomap_set_range_uptodate(page, iop, bvec->bv_offset,
-						bvec->bv_len);
+		size_t off = (page - &folio->page) * PAGE_SIZE +
+				bvec->bv_offset;
+
+		iomap_set_range_uptodate(folio, iop, off, bvec->bv_len);
 	}
 
 	if (!iop || atomic_sub_and_test(bvec->bv_len, &iop->read_bytes_pending))
-		unlock_page(page);
+		folio_unlock(folio);
 }
 
 static void
@@ -238,7 +240,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 	struct iomap_page *iop;
 	bool same_page = false, is_contig = false;
 	loff_t orig_pos = pos;
-	unsigned poff, plen;
+	size_t poff, plen;
 	sector_t sector;
 
 	if (iomap->type == IOMAP_INLINE) {
@@ -249,13 +251,13 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 
 	/* zero post-eof blocks as the page may be mapped */
 	iop = iomap_page_create(inode, folio);
-	iomap_adjust_read_range(inode, iop, &pos, length, &poff, &plen);
+	iomap_adjust_read_range(inode, folio, &pos, length, &poff, &plen);
 	if (plen == 0)
 		goto done;
 
 	if (iomap_block_needs_zeroing(inode, iomap, pos)) {
-		zero_user(page, poff, plen);
-		iomap_set_range_uptodate(page, iop, poff, plen);
+		zero_user(&folio->page, poff, plen);
+		iomap_set_range_uptodate(folio, iop, poff, plen);
 		goto done;
 	}
 
@@ -266,7 +268,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 	/* Try to merge into a previous segment if we can */
 	sector = iomap_sector(iomap, pos);
 	if (ctx->bio && bio_end_sector(ctx->bio) == sector) {
-		if (__bio_try_merge_page(ctx->bio, page, plen, poff,
+		if (__bio_try_merge_page(ctx->bio, &folio->page, plen, poff,
 				&same_page))
 			goto done;
 		is_contig = true;
@@ -298,7 +300,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 		ctx->bio->bi_end_io = iomap_read_end_io;
 	}
 
-	bio_add_page(ctx->bio, page, plen, poff);
+	bio_add_folio(ctx->bio, folio, plen, poff);
 done:
 	/*
 	 * Move the caller beyond our range so that it keeps making progress.
@@ -533,9 +535,8 @@ iomap_write_failed(struct inode *inode, loff_t pos, unsigned len)
 		truncate_pagecache_range(inode, max(pos, i_size), pos + len);
 }
 
-static int
-iomap_read_page_sync(loff_t block_start, struct page *page, unsigned poff,
-		unsigned plen, struct iomap *iomap)
+static int iomap_read_folio_sync(loff_t block_start, struct folio *folio,
+		size_t poff, size_t plen, struct iomap *iomap)
 {
 	struct bio_vec bvec;
 	struct bio bio;
@@ -544,7 +545,7 @@ iomap_read_page_sync(loff_t block_start, struct page *page, unsigned poff,
 	bio.bi_opf = REQ_OP_READ;
 	bio.bi_iter.bi_sector = iomap_sector(iomap, block_start);
 	bio_set_dev(&bio, iomap->bdev);
-	__bio_add_page(&bio, page, plen, poff);
+	bio_add_folio(&bio, folio, plen, poff);
 	return submit_bio_wait(&bio);
 }
 
@@ -557,14 +558,15 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
 	loff_t block_size = i_blocksize(inode);
 	loff_t block_start = round_down(pos, block_size);
 	loff_t block_end = round_up(pos + len, block_size);
-	unsigned from = offset_in_page(pos), to = from + len, poff, plen;
+	size_t from = offset_in_folio(folio, pos), to = from + len;
+	size_t poff, plen;
 
-	if (PageUptodate(page))
+	if (folio_test_uptodate(folio))
 		return 0;
-	ClearPageError(page);
+	folio_clear_error(folio);
 
 	do {
-		iomap_adjust_read_range(inode, iop, &block_start,
+		iomap_adjust_read_range(inode, folio, &block_start,
 				block_end - block_start, &poff, &plen);
 		if (plen == 0)
 			break;
@@ -577,14 +579,15 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
 		if (iomap_block_needs_zeroing(inode, srcmap, block_start)) {
 			if (WARN_ON_ONCE(flags & IOMAP_WRITE_F_UNSHARE))
 				return -EIO;
-			zero_user_segments(page, poff, from, to, poff + plen);
+			zero_user_segments(&folio->page, poff, from, to,
+						poff + plen);
 		} else {
-			int status = iomap_read_page_sync(block_start, page,
+			int status = iomap_read_folio_sync(block_start, folio,
 					poff, plen, srcmap);
 			if (status)
 				return status;
 		}
-		iomap_set_range_uptodate(page, iop, poff, plen);
+		iomap_set_range_uptodate(folio, iop, poff, plen);
 	} while ((block_start += plen) < block_end);
 
 	return 0;
@@ -663,7 +666,7 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
 	 */
 	if (unlikely(copied < len && !PageUptodate(page)))
 		return 0;
-	iomap_set_range_uptodate(page, iop, offset_in_page(pos), len);
+	iomap_set_range_uptodate(folio, iop, offset_in_folio(folio, pos), len);
 	__set_page_dirty_nobuffers(page);
 	return copied;
 }
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 10/17] iomap: Convert bio completions to use folios
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (8 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 09/17] iomap: Use folio offsets instead of page offsets Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  7:08   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 11/17] iomap: Convert readahead and readpage to use a folio Matthew Wilcox (Oracle)
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

Use bio_for_each_folio() to iterate over each folio in the bio
instead of iterating over each page.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 46 +++++++++++++++++-------------------------
 1 file changed, 18 insertions(+), 28 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 0f70bd185c2a..ee33a4e7b946 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -161,36 +161,29 @@ static void iomap_set_range_uptodate(struct folio *folio,
 		folio_mark_uptodate(folio);
 }
 
-static void
-iomap_read_page_end_io(struct bio_vec *bvec, int error)
+static void iomap_finish_folio_read(struct folio *folio, size_t offset,
+		size_t len, int error)
 {
-	struct page *page = bvec->bv_page;
-	struct folio *folio = page_folio(page);
 	struct iomap_page *iop = to_iomap_page(folio);
 
 	if (unlikely(error)) {
 		folio_clear_uptodate(folio);
 		folio_set_error(folio);
 	} else {
-		size_t off = (page - &folio->page) * PAGE_SIZE +
-				bvec->bv_offset;
-
-		iomap_set_range_uptodate(folio, iop, off, bvec->bv_len);
+		iomap_set_range_uptodate(folio, iop, offset, len);
 	}
 
-	if (!iop || atomic_sub_and_test(bvec->bv_len, &iop->read_bytes_pending))
+	if (!iop || atomic_sub_and_test(len, &iop->read_bytes_pending))
 		folio_unlock(folio);
 }
 
-static void
-iomap_read_end_io(struct bio *bio)
+static void iomap_read_end_io(struct bio *bio)
 {
 	int error = blk_status_to_errno(bio->bi_status);
-	struct bio_vec *bvec;
-	struct bvec_iter_all iter_all;
+	struct folio_iter fi;
 
-	bio_for_each_segment_all(bvec, bio, iter_all)
-		iomap_read_page_end_io(bvec, error);
+	bio_for_each_folio_all(fi, bio)
+		iomap_finish_folio_read(fi.folio, fi.offset, fi.length, error);
 	bio_put(bio);
 }
 
@@ -1014,23 +1007,21 @@ vm_fault_t iomap_page_mkwrite(struct vm_fault *vmf, const struct iomap_ops *ops)
 }
 EXPORT_SYMBOL_GPL(iomap_page_mkwrite);
 
-static void
-iomap_finish_page_writeback(struct inode *inode, struct page *page,
-		int error, unsigned int len)
+static void iomap_finish_folio_write(struct inode *inode, struct folio *folio,
+		size_t len, int error)
 {
-	struct folio *folio = page_folio(page);
 	struct iomap_page *iop = to_iomap_page(folio);
 
 	if (error) {
-		SetPageError(page);
+		folio_set_error(folio);
 		mapping_set_error(inode->i_mapping, -EIO);
 	}
 
-	WARN_ON_ONCE(i_blocks_per_page(inode, page) > 1 && !iop);
+	WARN_ON_ONCE(i_blocks_per_folio(inode, folio) > 1 && !iop);
 	WARN_ON_ONCE(iop && atomic_read(&iop->write_bytes_pending) <= 0);
 
 	if (!iop || atomic_sub_and_test(len, &iop->write_bytes_pending))
-		end_page_writeback(page);
+		folio_end_writeback(folio);
 }
 
 /*
@@ -1049,8 +1040,7 @@ iomap_finish_ioend(struct iomap_ioend *ioend, int error)
 	bool quiet = bio_flagged(bio, BIO_QUIET);
 
 	for (bio = &ioend->io_inline_bio; bio; bio = next) {
-		struct bio_vec *bv;
-		struct bvec_iter_all iter_all;
+		struct folio_iter fi;
 
 		/*
 		 * For the last bio, bi_private points to the ioend, so we
@@ -1061,10 +1051,10 @@ iomap_finish_ioend(struct iomap_ioend *ioend, int error)
 		else
 			next = bio->bi_private;
 
-		/* walk each page on bio, ending page IO on them */
-		bio_for_each_segment_all(bv, bio, iter_all)
-			iomap_finish_page_writeback(inode, bv->bv_page, error,
-					bv->bv_len);
+		/* walk all folios in bio, ending page IO on them */
+		bio_for_each_folio_all(fi, bio)
+			iomap_finish_folio_write(inode, fi.folio, fi.length,
+					error);
 		bio_put(bio);
 	}
 	/* The ioend has been freed by bio_put() */
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 11/17] iomap: Convert readahead and readpage to use a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (9 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 10/17] iomap: Convert bio completions to use folios Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  7:09   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 12/17] iomap: Convert iomap_page_mkwrite " Matthew Wilcox (Oracle)
                   ` (6 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

Handle folios of arbitrary size instead of working in PAGE_SIZE units.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 61 +++++++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 31 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index ee33a4e7b946..dfb2eec520bd 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -188,8 +188,8 @@ static void iomap_read_end_io(struct bio *bio)
 }
 
 struct iomap_readpage_ctx {
-	struct page		*cur_page;
-	bool			cur_page_in_bio;
+	struct folio		*cur_folio;
+	bool			cur_folio_in_bio;
 	struct bio		*bio;
 	struct readahead_control *rac;
 };
@@ -228,8 +228,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 		struct iomap *iomap, struct iomap *srcmap)
 {
 	struct iomap_readpage_ctx *ctx = data;
-	struct page *page = ctx->cur_page;
-	struct folio *folio = page_folio(page);
+	struct folio *folio = ctx->cur_folio;
 	struct iomap_page *iop;
 	bool same_page = false, is_contig = false;
 	loff_t orig_pos = pos;
@@ -238,7 +237,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 
 	if (iomap->type == IOMAP_INLINE) {
 		WARN_ON_ONCE(pos);
-		iomap_read_inline_data(inode, page, iomap);
+		iomap_read_inline_data(inode, &folio->page, iomap);
 		return PAGE_SIZE;
 	}
 
@@ -254,7 +253,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 		goto done;
 	}
 
-	ctx->cur_page_in_bio = true;
+	ctx->cur_folio_in_bio = true;
 	if (iop)
 		atomic_add(plen, &iop->read_bytes_pending);
 
@@ -268,7 +267,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 	}
 
 	if (!is_contig || bio_full(ctx->bio, plen)) {
-		gfp_t gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL);
+		gfp_t gfp = mapping_gfp_constraint(folio->mapping, GFP_KERNEL);
 		gfp_t orig_gfp = gfp;
 		unsigned int nr_vecs = DIV_ROUND_UP(length, PAGE_SIZE);
 
@@ -307,30 +306,31 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 int
 iomap_readpage(struct page *page, const struct iomap_ops *ops)
 {
-	struct iomap_readpage_ctx ctx = { .cur_page = page };
-	struct inode *inode = page->mapping->host;
-	unsigned poff;
+	struct folio *folio = page_folio(page);
+	struct iomap_readpage_ctx ctx = { .cur_folio = folio };
+	struct inode *inode = folio->mapping->host;
+	size_t poff;
 	loff_t ret;
+	size_t len = folio_size(folio);
 
-	trace_iomap_readpage(page->mapping->host, 1);
+	trace_iomap_readpage(inode, 1);
 
-	for (poff = 0; poff < PAGE_SIZE; poff += ret) {
-		ret = iomap_apply(inode, page_offset(page) + poff,
-				PAGE_SIZE - poff, 0, ops, &ctx,
-				iomap_readpage_actor);
+	for (poff = 0; poff < len; poff += ret) {
+		ret = iomap_apply(inode, folio_pos(folio) + poff, len - poff,
+				0, ops, &ctx, iomap_readpage_actor);
 		if (ret <= 0) {
 			WARN_ON_ONCE(ret == 0);
-			SetPageError(page);
+			folio_set_error(folio);
 			break;
 		}
 	}
 
 	if (ctx.bio) {
 		submit_bio(ctx.bio);
-		WARN_ON_ONCE(!ctx.cur_page_in_bio);
+		WARN_ON_ONCE(!ctx.cur_folio_in_bio);
 	} else {
-		WARN_ON_ONCE(ctx.cur_page_in_bio);
-		unlock_page(page);
+		WARN_ON_ONCE(ctx.cur_folio_in_bio);
+		folio_unlock(folio);
 	}
 
 	/*
@@ -350,15 +350,15 @@ iomap_readahead_actor(struct inode *inode, loff_t pos, loff_t length,
 	loff_t done, ret;
 
 	for (done = 0; done < length; done += ret) {
-		if (ctx->cur_page && offset_in_page(pos + done) == 0) {
-			if (!ctx->cur_page_in_bio)
-				unlock_page(ctx->cur_page);
-			put_page(ctx->cur_page);
-			ctx->cur_page = NULL;
+		if (ctx->cur_folio &&
+		    offset_in_folio(ctx->cur_folio, pos + done) == 0) {
+			if (!ctx->cur_folio_in_bio)
+				folio_unlock(ctx->cur_folio);
+			ctx->cur_folio = NULL;
 		}
-		if (!ctx->cur_page) {
-			ctx->cur_page = readahead_page(ctx->rac);
-			ctx->cur_page_in_bio = false;
+		if (!ctx->cur_folio) {
+			ctx->cur_folio = readahead_folio(ctx->rac);
+			ctx->cur_folio_in_bio = false;
 		}
 		ret = iomap_readpage_actor(inode, pos + done, length - done,
 				ctx, iomap, srcmap);
@@ -406,10 +406,9 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops)
 
 	if (ctx.bio)
 		submit_bio(ctx.bio);
-	if (ctx.cur_page) {
-		if (!ctx.cur_page_in_bio)
-			unlock_page(ctx.cur_page);
-		put_page(ctx.cur_page);
+	if (ctx.cur_folio) {
+		if (!ctx.cur_folio_in_bio)
+			folio_unlock(ctx.cur_folio);
 	}
 }
 EXPORT_SYMBOL_GPL(iomap_readahead);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 12/17] iomap: Convert iomap_page_mkwrite to use a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (10 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 11/17] iomap: Convert readahead and readpage to use a folio Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  7:13   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 13/17] iomap: Convert iomap_write_begin and iomap_write_end to folios Matthew Wilcox (Oracle)
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

If we write to any page in a folio, we have to mark the entire
folio as dirty, and potentially COW the entire folio, because it'll
all get written back as one unit.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 41 +++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index dfb2eec520bd..dd05db36e135 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -953,21 +953,22 @@ iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
 }
 EXPORT_SYMBOL_GPL(iomap_truncate_page);
 
-static loff_t
-iomap_page_mkwrite_actor(struct inode *inode, loff_t pos, loff_t length,
-		void *data, struct iomap *iomap, struct iomap *srcmap)
+static loff_t iomap_folio_mkwrite_actor(struct inode *inode, loff_t pos,
+		loff_t length, void *data, struct iomap *iomap,
+		struct iomap *srcmap)
 {
-	struct page *page = data;
+	struct folio *folio = data;
 	int ret;
 
 	if (iomap->flags & IOMAP_F_BUFFER_HEAD) {
-		ret = __block_write_begin_int(page, pos, length, NULL, iomap);
+		ret = __block_write_begin_int(&folio->page, pos, length, NULL,
+						iomap);
 		if (ret)
 			return ret;
-		block_commit_write(page, 0, length);
+		block_commit_write(&folio->page, 0, length);
 	} else {
-		WARN_ON_ONCE(!PageUptodate(page));
-		set_page_dirty(page);
+		WARN_ON_ONCE(!folio_test_uptodate(folio));
+		folio_mark_dirty(folio);
 	}
 
 	return length;
@@ -975,33 +976,33 @@ iomap_page_mkwrite_actor(struct inode *inode, loff_t pos, loff_t length,
 
 vm_fault_t iomap_page_mkwrite(struct vm_fault *vmf, const struct iomap_ops *ops)
 {
-	struct page *page = vmf->page;
+	struct folio *folio = page_folio(vmf->page);
 	struct inode *inode = file_inode(vmf->vma->vm_file);
-	unsigned long length;
-	loff_t offset;
+	size_t length;
+	loff_t pos;
 	ssize_t ret;
 
-	lock_page(page);
-	ret = page_mkwrite_check_truncate(page, inode);
+	folio_lock(folio);
+	ret = folio_mkwrite_check_truncate(folio, inode);
 	if (ret < 0)
 		goto out_unlock;
 	length = ret;
 
-	offset = page_offset(page);
+	pos = folio_pos(folio);
 	while (length > 0) {
-		ret = iomap_apply(inode, offset, length,
-				IOMAP_WRITE | IOMAP_FAULT, ops, page,
-				iomap_page_mkwrite_actor);
+		ret = iomap_apply(inode, pos, length,
+				IOMAP_WRITE | IOMAP_FAULT, ops, folio,
+				iomap_folio_mkwrite_actor);
 		if (unlikely(ret <= 0))
 			goto out_unlock;
-		offset += ret;
+		pos += ret;
 		length -= ret;
 	}
 
-	wait_for_stable_page(page);
+	folio_wait_stable(folio);
 	return VM_FAULT_LOCKED;
 out_unlock:
-	unlock_page(page);
+	folio_unlock(folio);
 	return block_page_mkwrite_return(ret);
 }
 EXPORT_SYMBOL_GPL(iomap_page_mkwrite);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 13/17] iomap: Convert iomap_write_begin and iomap_write_end to folios
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (11 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 12/17] iomap: Convert iomap_page_mkwrite " Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  7:15   ` Christoph Hellwig
  2021-07-20 23:59   ` Darrick J. Wong
  2021-07-19 18:39 ` [PATCH v15 14/17] iomap: Convert iomap_read_inline_data to take a folio Matthew Wilcox (Oracle)
                   ` (4 subsequent siblings)
  17 siblings, 2 replies; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle), linux-mm, linux-block

These functions still only work in PAGE_SIZE chunks, but there are
fewer conversions from head to tail pages as a result of this patch.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/iomap/buffered-io.c | 68 ++++++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 32 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index dd05db36e135..4b02337009bc 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -543,9 +543,8 @@ static int iomap_read_folio_sync(loff_t block_start, struct folio *folio,
 
 static int
 __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
-		struct page *page, struct iomap *srcmap)
+		struct folio *folio, struct iomap *srcmap)
 {
-	struct folio *folio = page_folio(page);
 	struct iomap_page *iop = iomap_page_create(inode, folio);
 	loff_t block_size = i_blocksize(inode);
 	loff_t block_start = round_down(pos, block_size);
@@ -585,12 +584,14 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
 	return 0;
 }
 
-static int
-iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
-		struct page **pagep, struct iomap *iomap, struct iomap *srcmap)
+static int iomap_write_begin(struct inode *inode, loff_t pos, size_t len,
+		unsigned flags, struct folio **foliop, struct iomap *iomap,
+		struct iomap *srcmap)
 {
 	const struct iomap_page_ops *page_ops = iomap->page_ops;
+	struct folio *folio;
 	struct page *page;
+	unsigned fgp = FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE | FGP_NOFS;
 	int status = 0;
 
 	BUG_ON(pos + len > iomap->offset + iomap->length);
@@ -606,30 +607,31 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
 			return status;
 	}
 
-	page = grab_cache_page_write_begin(inode->i_mapping, pos >> PAGE_SHIFT,
-			AOP_FLAG_NOFS);
-	if (!page) {
+	folio = __filemap_get_folio(inode->i_mapping, pos >> PAGE_SHIFT, fgp,
+			mapping_gfp_mask(inode->i_mapping));
+	if (!folio) {
 		status = -ENOMEM;
 		goto out_no_page;
 	}
 
+	page = folio_file_page(folio, pos >> PAGE_SHIFT);
 	if (srcmap->type == IOMAP_INLINE)
 		iomap_read_inline_data(inode, page, srcmap);
 	else if (iomap->flags & IOMAP_F_BUFFER_HEAD)
 		status = __block_write_begin_int(page, pos, len, NULL, srcmap);
 	else
-		status = __iomap_write_begin(inode, pos, len, flags, page,
+		status = __iomap_write_begin(inode, pos, len, flags, folio,
 				srcmap);
 
 	if (unlikely(status))
 		goto out_unlock;
 
-	*pagep = page;
+	*foliop = folio;
 	return 0;
 
 out_unlock:
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 	iomap_write_failed(inode, pos, len);
 
 out_no_page:
@@ -639,11 +641,10 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
 }
 
 static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
-		size_t copied, struct page *page)
+		size_t copied, struct folio *folio)
 {
-	struct folio *folio = page_folio(page);
 	struct iomap_page *iop = to_iomap_page(folio);
-	flush_dcache_page(page);
+	flush_dcache_folio(folio);
 
 	/*
 	 * The blocks that were entirely written will now be uptodate, so we
@@ -656,10 +657,10 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
 	 * uptodate page as a zero-length write, and force the caller to redo
 	 * the whole thing.
 	 */
-	if (unlikely(copied < len && !PageUptodate(page)))
+	if (unlikely(copied < len && !folio_test_uptodate(folio)))
 		return 0;
 	iomap_set_range_uptodate(folio, iop, offset_in_folio(folio, pos), len);
-	__set_page_dirty_nobuffers(page);
+	filemap_dirty_folio(inode->i_mapping, folio);
 	return copied;
 }
 
@@ -682,9 +683,10 @@ static size_t iomap_write_end_inline(struct inode *inode, struct page *page,
 
 /* Returns the number of bytes copied.  May be 0.  Cannot be an errno. */
 static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len,
-		size_t copied, struct page *page, struct iomap *iomap,
+		size_t copied, struct folio *folio, struct iomap *iomap,
 		struct iomap *srcmap)
 {
+	struct page *page = folio_file_page(folio, pos >> PAGE_SHIFT);
 	const struct iomap_page_ops *page_ops = iomap->page_ops;
 	loff_t old_size = inode->i_size;
 	size_t ret;
@@ -695,7 +697,7 @@ static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len,
 		ret = block_write_end(NULL, inode->i_mapping, pos, len, copied,
 				page, NULL);
 	} else {
-		ret = __iomap_write_end(inode, pos, len, copied, page);
+		ret = __iomap_write_end(inode, pos, len, copied, folio);
 	}
 
 	/*
@@ -707,13 +709,13 @@ static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len,
 		i_size_write(inode, pos + ret);
 		iomap->flags |= IOMAP_F_SIZE_CHANGED;
 	}
-	unlock_page(page);
+	folio_unlock(folio);
 
 	if (old_size < pos)
 		pagecache_isize_extended(inode, old_size, pos);
 	if (page_ops && page_ops->page_done)
 		page_ops->page_done(inode, pos, ret, page, iomap);
-	put_page(page);
+	folio_put(folio);
 
 	if (ret < len)
 		iomap_write_failed(inode, pos, len);
@@ -729,6 +731,7 @@ iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 	ssize_t written = 0;
 
 	do {
+		struct folio *folio;
 		struct page *page;
 		unsigned long offset;	/* Offset into pagecache page */
 		unsigned long bytes;	/* Bytes to write to page */
@@ -752,18 +755,19 @@ iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 			break;
 		}
 
-		status = iomap_write_begin(inode, pos, bytes, 0, &page, iomap,
+		status = iomap_write_begin(inode, pos, bytes, 0, &folio, iomap,
 				srcmap);
 		if (unlikely(status))
 			break;
 
+		page = folio_file_page(folio, pos >> PAGE_SHIFT);
 		if (mapping_writably_mapped(inode->i_mapping))
 			flush_dcache_page(page);
 
 		copied = copy_page_from_iter_atomic(page, offset, bytes, i);
 
-		status = iomap_write_end(inode, pos, bytes, copied, page, iomap,
-				srcmap);
+		status = iomap_write_end(inode, pos, bytes, copied, folio,
+				iomap, srcmap);
 
 		if (unlikely(copied != status))
 			iov_iter_revert(i, copied - status);
@@ -827,14 +831,14 @@ iomap_unshare_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 	do {
 		unsigned long offset = offset_in_page(pos);
 		unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length);
-		struct page *page;
+		struct folio *folio;
 
 		status = iomap_write_begin(inode, pos, bytes,
-				IOMAP_WRITE_F_UNSHARE, &page, iomap, srcmap);
+				IOMAP_WRITE_F_UNSHARE, &folio, iomap, srcmap);
 		if (unlikely(status))
 			return status;
 
-		status = iomap_write_end(inode, pos, bytes, bytes, page, iomap,
+		status = iomap_write_end(inode, pos, bytes, bytes, folio, iomap,
 				srcmap);
 		if (WARN_ON_ONCE(status == 0))
 			return -EIO;
@@ -873,19 +877,19 @@ EXPORT_SYMBOL_GPL(iomap_file_unshare);
 static s64 iomap_zero(struct inode *inode, loff_t pos, u64 length,
 		struct iomap *iomap, struct iomap *srcmap)
 {
-	struct page *page;
+	struct folio *folio;
 	int status;
 	unsigned offset = offset_in_page(pos);
 	unsigned bytes = min_t(u64, PAGE_SIZE - offset, length);
 
-	status = iomap_write_begin(inode, pos, bytes, 0, &page, iomap, srcmap);
+	status = iomap_write_begin(inode, pos, bytes, 0, &folio, iomap, srcmap);
 	if (status)
 		return status;
 
-	zero_user(page, offset, bytes);
-	mark_page_accessed(page);
+	zero_user(folio_file_page(folio, pos >> PAGE_SHIFT), offset, bytes);
+	folio_mark_accessed(folio);
 
-	return iomap_write_end(inode, pos, bytes, bytes, page, iomap, srcmap);
+	return iomap_write_end(inode, pos, bytes, bytes, folio, iomap, srcmap);
 }
 
 static loff_t iomap_zero_range_actor(struct inode *inode, loff_t pos,
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 14/17] iomap: Convert iomap_read_inline_data to take a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (12 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 13/17] iomap: Convert iomap_write_begin and iomap_write_end to folios Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  7:16   ` Christoph Hellwig
  2021-07-19 18:39 ` [PATCH v15 15/17] iomap: Convert iomap_write_end_inline " Matthew Wilcox (Oracle)
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

Inline data is restricted to being less than a page in size, so we
don't need to handle multi-page folios.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 4b02337009bc..23ee86aba9d6 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -194,25 +194,25 @@ struct iomap_readpage_ctx {
 	struct readahead_control *rac;
 };
 
-static void
-iomap_read_inline_data(struct inode *inode, struct page *page,
+static void iomap_read_inline_data(struct inode *inode, struct folio *folio,
 		struct iomap *iomap)
 {
 	size_t size = i_size_read(inode);
 	void *addr;
 
-	if (PageUptodate(page))
+	if (folio_test_uptodate(folio))
 		return;
 
-	BUG_ON(page_has_private(page));
-	BUG_ON(page->index);
+	BUG_ON(folio_test_private(folio));
+	BUG_ON(folio->index);
+	BUG_ON(folio_multi(folio));
 	BUG_ON(size > PAGE_SIZE - offset_in_page(iomap->inline_data));
 
-	addr = kmap_atomic(page);
+	addr = kmap_local_folio(folio, 0);
 	memcpy(addr, iomap->inline_data, size);
 	memset(addr + size, 0, PAGE_SIZE - size);
-	kunmap_atomic(addr);
-	SetPageUptodate(page);
+	kunmap_local(addr);
+	folio_mark_uptodate(folio);
 }
 
 static inline bool iomap_block_needs_zeroing(struct inode *inode,
@@ -237,7 +237,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 
 	if (iomap->type == IOMAP_INLINE) {
 		WARN_ON_ONCE(pos);
-		iomap_read_inline_data(inode, &folio->page, iomap);
+		iomap_read_inline_data(inode, folio, iomap);
 		return PAGE_SIZE;
 	}
 
@@ -616,7 +616,7 @@ static int iomap_write_begin(struct inode *inode, loff_t pos, size_t len,
 
 	page = folio_file_page(folio, pos >> PAGE_SHIFT);
 	if (srcmap->type == IOMAP_INLINE)
-		iomap_read_inline_data(inode, page, srcmap);
+		iomap_read_inline_data(inode, folio, srcmap);
 	else if (iomap->flags & IOMAP_F_BUFFER_HEAD)
 		status = __block_write_begin_int(page, pos, len, NULL, srcmap);
 	else
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 15/17] iomap: Convert iomap_write_end_inline to take a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (13 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 14/17] iomap: Convert iomap_read_inline_data to take a folio Matthew Wilcox (Oracle)
@ 2021-07-19 18:39 ` Matthew Wilcox (Oracle)
  2021-07-20  7:17   ` Christoph Hellwig
  2021-07-19 18:40 ` [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend " Matthew Wilcox (Oracle)
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:39 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Matthew Wilcox (Oracle), linux-mm, linux-block, Darrick J . Wong

Inline data only occupies a single page, but using a folio means that
we don't need to call compound_head() in PageUptodate().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/iomap/buffered-io.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 23ee86aba9d6..f8ca307270e7 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -664,18 +664,18 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
 	return copied;
 }
 
-static size_t iomap_write_end_inline(struct inode *inode, struct page *page,
+static size_t iomap_write_end_inline(struct inode *inode, struct folio *folio,
 		struct iomap *iomap, loff_t pos, size_t copied)
 {
 	void *addr;
 
-	WARN_ON_ONCE(!PageUptodate(page));
+	WARN_ON_ONCE(!folio_test_uptodate(folio));
 	BUG_ON(pos + copied > PAGE_SIZE - offset_in_page(iomap->inline_data));
 
-	flush_dcache_page(page);
-	addr = kmap_atomic(page);
+	flush_dcache_folio(folio);
+	addr = kmap_local_folio(folio, 0);
 	memcpy(iomap->inline_data + pos, addr + pos, copied);
-	kunmap_atomic(addr);
+	kunmap_local(addr);
 
 	mark_inode_dirty(inode);
 	return copied;
@@ -692,7 +692,7 @@ static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len,
 	size_t ret;
 
 	if (srcmap->type == IOMAP_INLINE) {
-		ret = iomap_write_end_inline(inode, page, iomap, pos, copied);
+		ret = iomap_write_end_inline(inode, folio, iomap, pos, copied);
 	} else if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
 		ret = block_write_end(NULL, inode->i_mapping, pos, len, copied,
 				page, NULL);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend to take a folio
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (14 preceding siblings ...)
  2021-07-19 18:39 ` [PATCH v15 15/17] iomap: Convert iomap_write_end_inline " Matthew Wilcox (Oracle)
@ 2021-07-19 18:40 ` Matthew Wilcox (Oracle)
  2021-07-20  7:20   ` Christoph Hellwig
  2021-07-21  0:12   ` Darrick J. Wong
  2021-07-19 18:40 ` [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios Matthew Wilcox (Oracle)
  2021-07-20  8:44 ` [PATCH v15 00/17] Folio support in block + iomap layers Christoph Hellwig
  17 siblings, 2 replies; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:40 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle), linux-mm, linux-block

We still iterate one block at a time, but now we call compound_head()
less often.  Rename file_offset to pos to fit the rest of the file.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/iomap/buffered-io.c | 109 ++++++++++++++++++-----------------------
 1 file changed, 48 insertions(+), 61 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index f8ca307270e7..60d3b7af61d1 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -1253,36 +1253,29 @@ iomap_can_add_to_ioend(struct iomap_writepage_ctx *wpc, loff_t offset,
  * first, otherwise finish off the current ioend and start another.
  */
 static void
-iomap_add_to_ioend(struct inode *inode, loff_t offset, struct page *page,
+iomap_add_to_ioend(struct inode *inode, loff_t pos, struct folio *folio,
 		struct iomap_page *iop, struct iomap_writepage_ctx *wpc,
 		struct writeback_control *wbc, struct list_head *iolist)
 {
-	sector_t sector = iomap_sector(&wpc->iomap, offset);
+	sector_t sector = iomap_sector(&wpc->iomap, pos);
 	unsigned len = i_blocksize(inode);
-	unsigned poff = offset & (PAGE_SIZE - 1);
-	bool merged, same_page = false;
+	size_t poff = offset_in_folio(folio, pos);
 
-	if (!wpc->ioend || !iomap_can_add_to_ioend(wpc, offset, sector)) {
+	if (!wpc->ioend || !iomap_can_add_to_ioend(wpc, pos, sector)) {
 		if (wpc->ioend)
 			list_add(&wpc->ioend->io_list, iolist);
-		wpc->ioend = iomap_alloc_ioend(inode, wpc, offset, sector, wbc);
+		wpc->ioend = iomap_alloc_ioend(inode, wpc, pos, sector, wbc);
 	}
 
-	merged = __bio_try_merge_page(wpc->ioend->io_bio, page, len, poff,
-			&same_page);
 	if (iop)
 		atomic_add(len, &iop->write_bytes_pending);
-
-	if (!merged) {
-		if (bio_full(wpc->ioend->io_bio, len)) {
-			wpc->ioend->io_bio =
-				iomap_chain_bio(wpc->ioend->io_bio);
-		}
-		bio_add_page(wpc->ioend->io_bio, page, len, poff);
+	if (!bio_add_folio(wpc->ioend->io_bio, folio, len, poff)) {
+		wpc->ioend->io_bio = iomap_chain_bio(wpc->ioend->io_bio);
+		bio_add_folio(wpc->ioend->io_bio, folio, len, poff);
 	}
 
 	wpc->ioend->io_size += len;
-	wbc_account_cgroup_owner(wbc, page, len);
+	wbc_account_cgroup_owner(wbc, &folio->page, len);
 }
 
 /*
@@ -1304,45 +1297,43 @@ iomap_add_to_ioend(struct inode *inode, loff_t offset, struct page *page,
 static int
 iomap_writepage_map(struct iomap_writepage_ctx *wpc,
 		struct writeback_control *wbc, struct inode *inode,
-		struct page *page, u64 end_offset)
+		struct folio *folio, loff_t end_pos)
 {
-	struct folio *folio = page_folio(page);
 	struct iomap_page *iop = iomap_page_create(inode, folio);
 	struct iomap_ioend *ioend, *next;
 	unsigned len = i_blocksize(inode);
-	u64 file_offset; /* file offset of page */
+	unsigned nblocks = i_blocks_per_folio(inode, folio);
+	loff_t pos = folio_pos(folio);
 	int error = 0, count = 0, i;
 	LIST_HEAD(submit_list);
 
 	WARN_ON_ONCE(iop && atomic_read(&iop->write_bytes_pending) != 0);
 
 	/*
-	 * Walk through the page to find areas to write back. If we run off the
-	 * end of the current map or find the current map invalid, grab a new
-	 * one.
+	 * Walk through the folio to find areas to write back. If we
+	 * run off the end of the current map or find the current map
+	 * invalid, grab a new one.
 	 */
-	for (i = 0, file_offset = page_offset(page);
-	     i < (PAGE_SIZE >> inode->i_blkbits) && file_offset < end_offset;
-	     i++, file_offset += len) {
+	for (i = 0; i < nblocks && pos < end_pos; i++, pos += len) {
 		if (iop && !test_bit(i, iop->uptodate))
 			continue;
 
-		error = wpc->ops->map_blocks(wpc, inode, file_offset);
+		error = wpc->ops->map_blocks(wpc, inode, pos);
 		if (error)
 			break;
 		if (WARN_ON_ONCE(wpc->iomap.type == IOMAP_INLINE))
 			continue;
 		if (wpc->iomap.type == IOMAP_HOLE)
 			continue;
-		iomap_add_to_ioend(inode, file_offset, page, iop, wpc, wbc,
+		iomap_add_to_ioend(inode, pos, folio, iop, wpc, wbc,
 				 &submit_list);
 		count++;
 	}
 
 	WARN_ON_ONCE(!wpc->ioend && !list_empty(&submit_list));
-	WARN_ON_ONCE(!PageLocked(page));
-	WARN_ON_ONCE(PageWriteback(page));
-	WARN_ON_ONCE(PageDirty(page));
+	WARN_ON_ONCE(!folio_test_locked(folio));
+	WARN_ON_ONCE(folio_test_writeback(folio));
+	WARN_ON_ONCE(folio_test_dirty(folio));
 
 	/*
 	 * We cannot cancel the ioend directly here on error.  We may have
@@ -1358,16 +1349,16 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
 		 * now.
 		 */
 		if (wpc->ops->discard_page)
-			wpc->ops->discard_page(page, file_offset);
+			wpc->ops->discard_page(&folio->page, pos);
 		if (!count) {
-			ClearPageUptodate(page);
-			unlock_page(page);
+			folio_clear_uptodate(folio);
+			folio_unlock(folio);
 			goto done;
 		}
 	}
 
-	set_page_writeback(page);
-	unlock_page(page);
+	folio_start_writeback(folio);
+	folio_unlock(folio);
 
 	/*
 	 * Preserve the original error if there was one, otherwise catch
@@ -1388,9 +1379,9 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
 	 * with a partial page truncate on a sub-page block sized filesystem.
 	 */
 	if (!count)
-		end_page_writeback(page);
+		folio_end_writeback(folio);
 done:
-	mapping_set_error(page->mapping, error);
+	mapping_set_error(folio->mapping, error);
 	return error;
 }
 
@@ -1404,16 +1395,15 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
 static int
 iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data)
 {
+	struct folio *folio = page_folio(page);
 	struct iomap_writepage_ctx *wpc = data;
-	struct inode *inode = page->mapping->host;
-	pgoff_t end_index;
-	u64 end_offset;
-	loff_t offset;
+	struct inode *inode = folio->mapping->host;
+	loff_t end_pos, isize;
 
-	trace_iomap_writepage(inode, page_offset(page), PAGE_SIZE);
+	trace_iomap_writepage(inode, folio_pos(folio), folio_size(folio));
 
 	/*
-	 * Refuse to write the page out if we are called from reclaim context.
+	 * Refuse to write the folio out if we are called from reclaim context.
 	 *
 	 * This avoids stack overflows when called from deeply used stacks in
 	 * random callers for direct reclaim or memcg reclaim.  We explicitly
@@ -1427,10 +1417,10 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data)
 		goto redirty;
 
 	/*
-	 * Is this page beyond the end of the file?
+	 * Is this folio beyond the end of the file?
 	 *
-	 * The page index is less than the end_index, adjust the end_offset
-	 * to the highest offset that this page should represent.
+	 * The folio index is less than the end_index, adjust the end_pos
+	 * to the highest offset that this folio should represent.
 	 * -----------------------------------------------------
 	 * |			file mapping	       | <EOF> |
 	 * -----------------------------------------------------
@@ -1439,11 +1429,9 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data)
 	 * |     desired writeback range    |      see else    |
 	 * ---------------------------------^------------------|
 	 */
-	offset = i_size_read(inode);
-	end_index = offset >> PAGE_SHIFT;
-	if (page->index < end_index)
-		end_offset = (loff_t)(page->index + 1) << PAGE_SHIFT;
-	else {
+	isize = i_size_read(inode);
+	end_pos = folio_pos(folio) + folio_size(folio);
+	if (end_pos - 1 >= isize) {
 		/*
 		 * Check whether the page to write out is beyond or straddles
 		 * i_size or not.
@@ -1455,7 +1443,8 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data)
 		 * |				    |      Straddles     |
 		 * ---------------------------------^-----------|--------|
 		 */
-		unsigned offset_into_page = offset & (PAGE_SIZE - 1);
+		size_t poff = offset_in_folio(folio, isize);
+		pgoff_t end_index = isize >> PAGE_SHIFT;
 
 		/*
 		 * Skip the page if it is fully outside i_size, e.g. due to a
@@ -1474,8 +1463,8 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data)
 		 * if the page to write is totally beyond the i_size or if it's
 		 * offset is just equal to the EOF.
 		 */
-		if (page->index > end_index ||
-		    (page->index == end_index && offset_into_page == 0))
+		if (folio->index > end_index ||
+		    (folio->index == end_index && poff == 0))
 			goto redirty;
 
 		/*
@@ -1486,17 +1475,15 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data)
 		 * memory is zeroed when mapped, and writes to that region are
 		 * not written out to the file."
 		 */
-		zero_user_segment(page, offset_into_page, PAGE_SIZE);
-
-		/* Adjust the end_offset to the end of file */
-		end_offset = offset;
+		zero_user_segment(&folio->page, poff, folio_size(folio));
+		end_pos = isize;
 	}
 
-	return iomap_writepage_map(wpc, wbc, inode, page, end_offset);
+	return iomap_writepage_map(wpc, wbc, inode, folio, end_pos);
 
 redirty:
-	redirty_page_for_writepage(wbc, page);
-	unlock_page(page);
+	folio_redirty_for_writepage(wbc, folio);
+	folio_unlock(folio);
 	return 0;
 }
 
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (15 preceding siblings ...)
  2021-07-19 18:40 ` [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend " Matthew Wilcox (Oracle)
@ 2021-07-19 18:40 ` Matthew Wilcox (Oracle)
  2021-07-20  7:21   ` Christoph Hellwig
                     ` (2 more replies)
  2021-07-20  8:44 ` [PATCH v15 00/17] Folio support in block + iomap layers Christoph Hellwig
  17 siblings, 3 replies; 62+ messages in thread
From: Matthew Wilcox (Oracle) @ 2021-07-19 18:40 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle), linux-mm, linux-block

The arguments are still pages for now, but we can use folios internally
and cut out a lot of calls to compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/iomap/buffered-io.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 60d3b7af61d1..cf56b19fb101 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -492,19 +492,21 @@ int
 iomap_migrate_page(struct address_space *mapping, struct page *newpage,
 		struct page *page, enum migrate_mode mode)
 {
+	struct folio *folio = page_folio(page);
+	struct folio *newfolio = page_folio(newpage);
 	int ret;
 
-	ret = migrate_page_move_mapping(mapping, newpage, page, 0);
+	ret = folio_migrate_mapping(mapping, newfolio, folio, 0);
 	if (ret != MIGRATEPAGE_SUCCESS)
 		return ret;
 
-	if (page_has_private(page))
-		attach_page_private(newpage, detach_page_private(page));
+	if (folio_test_private(folio))
+		folio_attach_private(newfolio, folio_detach_private(folio));
 
 	if (mode != MIGRATE_SYNC_NO_COPY)
-		migrate_page_copy(newpage, page);
+		folio_migrate_copy(newfolio, folio);
 	else
-		migrate_page_states(newpage, page);
+		folio_migrate_flags(newfolio, folio);
 	return MIGRATEPAGE_SUCCESS;
 }
 EXPORT_SYMBOL_GPL(iomap_migrate_page);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 01/17] block: Add bio_add_folio()
  2021-07-19 18:39 ` [PATCH v15 01/17] block: Add bio_add_folio() Matthew Wilcox (Oracle)
@ 2021-07-20  1:28   ` Darrick J. Wong
  2021-07-20  6:42   ` Christoph Hellwig
  2021-07-30  8:25   ` Ming Lei
  2 siblings, 0 replies; 62+ messages in thread
From: Darrick J. Wong @ 2021-07-20  1:28 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:45PM +0100, Matthew Wilcox (Oracle) wrote:
> This is a thin wrapper around bio_add_page().  The main advantage here
> is the documentation that the submitter can expect to see folios in the
> completion handler, and that stupidly large folios are not supported.
> It's not currently possible to allocate stupidly large folios, but if
> it ever becomes possible, this function will fail gracefully instead of
> doing I/O to the wrong bytes.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Looks fine to me,
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  block/bio.c         | 21 +++++++++++++++++++++
>  include/linux/bio.h |  3 ++-
>  2 files changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/block/bio.c b/block/bio.c
> index 1fab762e079b..c64e35548fb2 100644
> --- a/block/bio.c
> +++ b/block/bio.c
> @@ -933,6 +933,27 @@ int bio_add_page(struct bio *bio, struct page *page,
>  }
>  EXPORT_SYMBOL(bio_add_page);
>  
> +/**
> + * bio_add_folio - Attempt to add part of a folio to a bio.
> + * @bio: Bio to add to.
> + * @folio: Folio to add.
> + * @len: How many bytes from the folio to add.
> + * @off: First byte in this folio to add.
> + *
> + * Always uses the head page of the folio in the bio.  If a submitter only
> + * uses bio_add_folio(), it can count on never seeing tail pages in the
> + * completion routine.  BIOs do not support folios that are 4GiB or larger.
> + *
> + * Return: The number of bytes from this folio added to the bio.
> + */
> +size_t bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
> +		size_t off)
> +{
> +	if (len > UINT_MAX || off > UINT_MAX)
> +		return 0;
> +	return bio_add_page(bio, &folio->page, len, off);
> +}
> +
>  void bio_release_pages(struct bio *bio, bool mark_dirty)
>  {
>  	struct bvec_iter_all iter_all;
> diff --git a/include/linux/bio.h b/include/linux/bio.h
> index 2203b686e1f0..ade93e2de6a1 100644
> --- a/include/linux/bio.h
> +++ b/include/linux/bio.h
> @@ -462,7 +462,8 @@ extern void bio_uninit(struct bio *);
>  extern void bio_reset(struct bio *);
>  void bio_chain(struct bio *, struct bio *);
>  
> -extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
> +int bio_add_page(struct bio *, struct page *, unsigned len, unsigned off);
> +size_t bio_add_folio(struct bio *, struct folio *, size_t len, size_t off);
>  extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
>  			   unsigned int, unsigned int);
>  int bio_add_zone_append_page(struct bio *bio, struct page *page,
> -- 
> 2.30.2
> 


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 02/17] block: Add bio_for_each_folio_all()
  2021-07-19 18:39 ` [PATCH v15 02/17] block: Add bio_for_each_folio_all() Matthew Wilcox (Oracle)
@ 2021-07-20  1:29   ` Darrick J. Wong
  2021-07-20  1:59     ` Matthew Wilcox
  2021-07-20  6:48   ` Christoph Hellwig
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 62+ messages in thread
From: Darrick J. Wong @ 2021-07-20  1:29 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:46PM +0100, Matthew Wilcox (Oracle) wrote:
> Allow callers to iterate over each folio instead of each page.  The
> bio need not have been constructed using folios originally.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Whoops, I never did remember to circle back and ack this patch.
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  Documentation/core-api/kernel-api.rst |  1 +
>  include/linux/bio.h                   | 53 ++++++++++++++++++++++++++-
>  2 files changed, 53 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst
> index 2a7444e3a4c2..b804605f705e 100644
> --- a/Documentation/core-api/kernel-api.rst
> +++ b/Documentation/core-api/kernel-api.rst
> @@ -279,6 +279,7 @@ Accounting Framework
>  Block Devices
>  =============
>  
> +.. kernel-doc:: include/linux/bio.h
>  .. kernel-doc:: block/blk-core.c
>     :export:
>  
> diff --git a/include/linux/bio.h b/include/linux/bio.h
> index ade93e2de6a1..a90a79ad7bd1 100644
> --- a/include/linux/bio.h
> +++ b/include/linux/bio.h
> @@ -189,7 +189,7 @@ static inline void bio_advance_iter_single(const struct bio *bio,
>   */
>  #define bio_for_each_bvec_all(bvl, bio, i)		\
>  	for (i = 0, bvl = bio_first_bvec_all(bio);	\
> -	     i < (bio)->bi_vcnt; i++, bvl++)		\
> +	     i < (bio)->bi_vcnt; i++, bvl++)
>  
>  #define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len)
>  
> @@ -314,6 +314,57 @@ static inline struct bio_vec *bio_last_bvec_all(struct bio *bio)
>  	return &bio->bi_io_vec[bio->bi_vcnt - 1];
>  }
>  
> +/**
> + * struct folio_iter - State for iterating all folios in a bio.
> + * @folio: The current folio we're iterating.  NULL after the last folio.
> + * @offset: The byte offset within the current folio.
> + * @length: The number of bytes in this iteration (will not cross folio
> + *	boundary).
> + */
> +struct folio_iter {
> +	struct folio *folio;
> +	size_t offset;
> +	size_t length;
> +	/* private: for use by the iterator */
> +	size_t _seg_count;
> +	int _i;
> +};
> +
> +static inline
> +void bio_first_folio(struct folio_iter *fi, struct bio *bio, int i)
> +{
> +	struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
> +
> +	fi->folio = page_folio(bvec->bv_page);
> +	fi->offset = bvec->bv_offset +
> +			PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
> +	fi->_seg_count = bvec->bv_len;
> +	fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
> +	fi->_i = i;
> +}
> +
> +static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
> +{
> +	fi->_seg_count -= fi->length;
> +	if (fi->_seg_count) {
> +		fi->folio = folio_next(fi->folio);
> +		fi->offset = 0;
> +		fi->length = min(folio_size(fi->folio), fi->_seg_count);
> +	} else if (fi->_i + 1 < bio->bi_vcnt) {
> +		bio_first_folio(fi, bio, fi->_i + 1);
> +	} else {
> +		fi->folio = NULL;
> +	}
> +}
> +
> +/**
> + * bio_for_each_folio_all - Iterate over each folio in a bio.
> + * @fi: struct folio_iter which is updated for each folio.
> + * @bio: struct bio to iterate over.
> + */
> +#define bio_for_each_folio_all(fi, bio)				\
> +	for (bio_first_folio(&fi, bio, 0); fi.folio; bio_next_folio(&fi, bio))
> +
>  enum bip_flags {
>  	BIP_BLOCK_INTEGRITY	= 1 << 0, /* block layer owns integrity data */
>  	BIP_MAPPED_INTEGRITY	= 1 << 1, /* ref tag has been remapped */
> -- 
> 2.30.2
> 


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 02/17] block: Add bio_for_each_folio_all()
  2021-07-20  1:29   ` Darrick J. Wong
@ 2021-07-20  1:59     ` Matthew Wilcox
  0 siblings, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-20  1:59 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 06:29:45PM -0700, Darrick J. Wong wrote:
> On Mon, Jul 19, 2021 at 07:39:46PM +0100, Matthew Wilcox (Oracle) wrote:
> > Allow callers to iterate over each folio instead of each page.  The
> > bio need not have been constructed using folios originally.
> > 
> > Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> 
> Whoops, I never did remember to circle back and ack this patch.
> Reviewed-by: Darrick J. Wong <djwong@kernel.org>

That's all good; it made me ask "What more can I do?" and "Add
documentation" as always a good answer ...


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 01/17] block: Add bio_add_folio()
  2021-07-19 18:39 ` [PATCH v15 01/17] block: Add bio_add_folio() Matthew Wilcox (Oracle)
  2021-07-20  1:28   ` Darrick J. Wong
@ 2021-07-20  6:42   ` Christoph Hellwig
  2021-07-20 11:16     ` Matthew Wilcox
  2021-07-22 16:27     ` Matthew Wilcox
  2021-07-30  8:25   ` Ming Lei
  2 siblings, 2 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:42 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:45PM +0100, Matthew Wilcox (Oracle) wrote:
> +/**
> + * bio_add_folio - Attempt to add part of a folio to a bio.
> + * @bio: Bio to add to.
> + * @folio: Folio to add.
> + * @len: How many bytes from the folio to add.
> + * @off: First byte in this folio to add.
> + *
> + * Always uses the head page of the folio in the bio.  If a submitter only
> + * uses bio_add_folio(), it can count on never seeing tail pages in the
> + * completion routine.  BIOs do not support folios that are 4GiB or larger.
> + *
> + * Return: The number of bytes from this folio added to the bio.
> + */
> +size_t bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
> +		size_t off)
> +{
> +	if (len > UINT_MAX || off > UINT_MAX)
> +		return 0;
> +	return bio_add_page(bio, &folio->page, len, off);
> +}

I'd use the opportunity to switch to a true/false return instead of
the length.  This has been on my todo list for bio_add_page for a while,
so it might make sense to start out the new API the right way.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 02/17] block: Add bio_for_each_folio_all()
  2021-07-19 18:39 ` [PATCH v15 02/17] block: Add bio_for_each_folio_all() Matthew Wilcox (Oracle)
  2021-07-20  1:29   ` Darrick J. Wong
@ 2021-07-20  6:48   ` Christoph Hellwig
  2021-07-23  2:40     ` Matthew Wilcox
  2021-07-20 12:05   ` kernel test robot
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:48 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:46PM +0100, Matthew Wilcox (Oracle) wrote:
>  #define bio_for_each_bvec_all(bvl, bio, i)		\
>  	for (i = 0, bvl = bio_first_bvec_all(bio);	\
> -	     i < (bio)->bi_vcnt; i++, bvl++)		\
> +	     i < (bio)->bi_vcnt; i++, bvl++)

Pleae split out this unrelated fixup.

> +static inline
> +void bio_first_folio(struct folio_iter *fi, struct bio *bio, int i)

Please fix the strange formatting.

> +{
> +	struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
> +
> +	fi->folio = page_folio(bvec->bv_page);
> +	fi->offset = bvec->bv_offset +
> +			PAGE_SIZE * (bvec->bv_page - &fi->folio->page);

Can we have a little helper for the offset in folio calculation, like:

static inline size_t offset_of_page_in_folio(struct page *page)
{
	return (bvec->bv_page - &page_folio(page)->page) * PAGE;
}

as that makes the callers a lot easier to read.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 03/17] iomap: Convert to_iomap_page to take a folio
  2021-07-19 18:39 ` [PATCH v15 03/17] iomap: Convert to_iomap_page to take a folio Matthew Wilcox (Oracle)
@ 2021-07-20  6:49   ` Christoph Hellwig
  0 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:49 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:47PM +0100, Matthew Wilcox (Oracle) wrote:
> The big comment about only using a head page can go away now that
> it takes a folio argument.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Reviewed-by: Darrick J. Wong <djwong@kernel.org>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

(all the iomap work is going to cause heavy clashes with the iomap_iter
work, but they should be mostly context, not really functional).


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 04/17] iomap: Convert iomap_page_create to take a folio
  2021-07-19 18:39 ` [PATCH v15 04/17] iomap: Convert iomap_page_create " Matthew Wilcox (Oracle)
@ 2021-07-20  6:50   ` Christoph Hellwig
  0 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:50 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:48PM +0100, Matthew Wilcox (Oracle) wrote:
> This function already assumed it was being passed a head page, so
> just formalise that.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Reviewed-by: Darrick J. Wong <djwong@kernel.org>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 05/17] iomap: Convert iomap_page_release to take a folio
  2021-07-19 18:39 ` [PATCH v15 05/17] iomap: Convert iomap_page_release " Matthew Wilcox (Oracle)
@ 2021-07-20  6:52   ` Christoph Hellwig
  2021-07-20 11:29     ` Matthew Wilcox
  0 siblings, 1 reply; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:52 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:49PM +0100, Matthew Wilcox (Oracle) wrote:
> -static void
> -iomap_page_release(struct page *page)
> +static void iomap_page_release(struct folio *folio)
>  {
> -	struct iomap_page *iop = detach_page_private(page);
> -	unsigned int nr_blocks = i_blocks_per_page(page->mapping->host, page);
> +	struct iomap_page *iop = folio_detach_private(folio);
> +	unsigned int nr_blocks = i_blocks_per_folio(folio->mapping->host,
> +							folio);

Nit: but I find this variant much easier to read:

	unsigned int nr_blocks =
		i_blocks_per_folio(folio->mapping->host, folio);

Otherwise looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 06/17] iomap: Convert iomap_releasepage to use a folio
  2021-07-19 18:39 ` [PATCH v15 06/17] iomap: Convert iomap_releasepage to use " Matthew Wilcox (Oracle)
@ 2021-07-20  6:54   ` Christoph Hellwig
  2021-07-20 23:56   ` Darrick J. Wong
  1 sibling, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:54 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:50PM +0100, Matthew Wilcox (Oracle) wrote:
> This is an address_space operation, so its argument must remain as a
> struct page, but we can use a folio internally.

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 07/17] iomap: Convert iomap_invalidatepage to use a folio
  2021-07-19 18:39 ` [PATCH v15 07/17] iomap: Convert iomap_invalidatepage " Matthew Wilcox (Oracle)
@ 2021-07-20  6:55   ` Christoph Hellwig
  2021-07-20 23:57   ` Darrick J. Wong
  1 sibling, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:55 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:51PM +0100, Matthew Wilcox (Oracle) wrote:
> This is an address_space operation, so its argument must remain as a
> struct page, but we can use a folio internally.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 08/17] iomap: Pass the iomap_page into iomap_set_range_uptodate
  2021-07-19 18:39 ` [PATCH v15 08/17] iomap: Pass the iomap_page into iomap_set_range_uptodate Matthew Wilcox (Oracle)
@ 2021-07-20  6:57   ` Christoph Hellwig
  2021-07-20 11:36     ` Matthew Wilcox
  0 siblings, 1 reply; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:57 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:52PM +0100, Matthew Wilcox (Oracle) wrote:
> All but one caller already has the iomap_page, and we can avoid getting
> it again.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Reviewed-by: Darrick J. Wong <djwong@kernel.org>

In general reloading it from a single pointer should be faster than
passing an extra argument.  What is the rationale here?


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 09/17] iomap: Use folio offsets instead of page offsets
  2021-07-19 18:39 ` [PATCH v15 09/17] iomap: Use folio offsets instead of page offsets Matthew Wilcox (Oracle)
@ 2021-07-20  6:59   ` Christoph Hellwig
  2021-07-20 11:42     ` Matthew Wilcox
  0 siblings, 1 reply; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  6:59 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

> +	size_t poff = offset_in_folio(folio, *pos);
> +	size_t plen = min_t(loff_t, folio_size(folio) - poff, length);

These variables are a little misnamed now.  But I'm not sure what a
better name would be.

> +		size_t off = (page - &folio->page) * PAGE_SIZE +
> +				bvec->bv_offset;

Another use case for the helper I suggested earlier.

Otherwise looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 10/17] iomap: Convert bio completions to use folios
  2021-07-19 18:39 ` [PATCH v15 10/17] iomap: Convert bio completions to use folios Matthew Wilcox (Oracle)
@ 2021-07-20  7:08   ` Christoph Hellwig
  0 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  7:08 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:54PM +0100, Matthew Wilcox (Oracle) wrote:
> Use bio_for_each_folio() to iterate over each folio in the bio
> instead of iterating over each page.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Reviewed-by: Darrick J. Wong <djwong@kernel.org>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 11/17] iomap: Convert readahead and readpage to use a folio
  2021-07-19 18:39 ` [PATCH v15 11/17] iomap: Convert readahead and readpage to use a folio Matthew Wilcox (Oracle)
@ 2021-07-20  7:09   ` Christoph Hellwig
  0 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  7:09 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:55PM +0100, Matthew Wilcox (Oracle) wrote:
> Handle folios of arbitrary size instead of working in PAGE_SIZE units.

Ok, this is a real conflict vs the iter work, but otherwise it looks
fine.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 12/17] iomap: Convert iomap_page_mkwrite to use a folio
  2021-07-19 18:39 ` [PATCH v15 12/17] iomap: Convert iomap_page_mkwrite " Matthew Wilcox (Oracle)
@ 2021-07-20  7:13   ` Christoph Hellwig
  0 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  7:13 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:56PM +0100, Matthew Wilcox (Oracle) wrote:
> -	struct page *page = data;
> +	struct folio *folio = data;
>  	int ret;
>  
>  	if (iomap->flags & IOMAP_F_BUFFER_HEAD) {
> -		ret = __block_write_begin_int(page, pos, length, NULL, iomap);
> +		ret = __block_write_begin_int(&folio->page, pos, length, NULL,
> +						iomap);
>  		if (ret)
>  			return ret;
> -		block_commit_write(page, 0, length);
> +		block_commit_write(&folio->page, 0, length);
>  	} else {
> -		WARN_ON_ONCE(!PageUptodate(page));
> -		set_page_dirty(page);
> +		WARN_ON_ONCE(!folio_test_uptodate(folio));
> +		folio_mark_dirty(folio);

Not that having this else clause code for the !IOMAP_F_BUFFER_HEAD case
here is a bit silly, and becomes more so with folios - it should probably
move into the caller.  I'll see what I can do there in this merge window
to prepare.

Otherwise this looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 13/17] iomap: Convert iomap_write_begin and iomap_write_end to folios
  2021-07-19 18:39 ` [PATCH v15 13/17] iomap: Convert iomap_write_begin and iomap_write_end to folios Matthew Wilcox (Oracle)
@ 2021-07-20  7:15   ` Christoph Hellwig
  2021-07-20 23:59   ` Darrick J. Wong
  1 sibling, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  7:15 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:57PM +0100, Matthew Wilcox (Oracle) wrote:
> These functions still only work in PAGE_SIZE chunks, but there are
> fewer conversions from head to tail pages as a result of this patch.

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 14/17] iomap: Convert iomap_read_inline_data to take a folio
  2021-07-19 18:39 ` [PATCH v15 14/17] iomap: Convert iomap_read_inline_data to take a folio Matthew Wilcox (Oracle)
@ 2021-07-20  7:16   ` Christoph Hellwig
  0 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  7:16 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:58PM +0100, Matthew Wilcox (Oracle) wrote:
> Inline data is restricted to being less than a page in size, so we
> don't need to handle multi-page folios.

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 15/17] iomap: Convert iomap_write_end_inline to take a folio
  2021-07-19 18:39 ` [PATCH v15 15/17] iomap: Convert iomap_write_end_inline " Matthew Wilcox (Oracle)
@ 2021-07-20  7:17   ` Christoph Hellwig
  0 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  7:17 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Mon, Jul 19, 2021 at 07:39:59PM +0100, Matthew Wilcox (Oracle) wrote:
> Inline data only occupies a single page, but using a folio means that
> we don't need to call compound_head() in PageUptodate().
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Reviewed-by: Darrick J. Wong <djwong@kernel.org>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend to take a folio
  2021-07-19 18:40 ` [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend " Matthew Wilcox (Oracle)
@ 2021-07-20  7:20   ` Christoph Hellwig
  2021-07-20 11:45     ` Matthew Wilcox
  2021-07-21  0:12   ` Darrick J. Wong
  1 sibling, 1 reply; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  7:20 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:40:00PM +0100, Matthew Wilcox (Oracle) wrote:
> -	merged = __bio_try_merge_page(wpc->ioend->io_bio, page, len, poff,
> -			&same_page);
>  	if (iop)
>  		atomic_add(len, &iop->write_bytes_pending);
> -
> -	if (!merged) {
> -		if (bio_full(wpc->ioend->io_bio, len)) {
> -			wpc->ioend->io_bio =
> -				iomap_chain_bio(wpc->ioend->io_bio);
> -		}
> -		bio_add_page(wpc->ioend->io_bio, page, len, poff);
> +	if (!bio_add_folio(wpc->ioend->io_bio, folio, len, poff)) {
> +		wpc->ioend->io_bio = iomap_chain_bio(wpc->ioend->io_bio);
> +		bio_add_folio(wpc->ioend->io_bio, folio, len, poff);
>  	}

I actually have pretty similar changes for the red and write path to
avoid __bio_try_merge_page in my queue.  I'll send them out ASAP as
I think such a change should be done separately from the folio
switch.

>  	/*
> -	 * Walk through the page to find areas to write back. If we run off the
> -	 * end of the current map or find the current map invalid, grab a new
> -	 * one.
> +	 * Walk through the folio to find areas to write back. If we
> +	 * run off the end of the current map or find the current map
> +	 * invalid, grab a new one.

Why the reformatting?

Otherwise this looks sane to me.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios
  2021-07-19 18:40 ` [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios Matthew Wilcox (Oracle)
@ 2021-07-20  7:21   ` Christoph Hellwig
  2021-07-20 13:30   ` kernel test robot
  2021-07-21  0:02   ` Darrick J. Wong
  2 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  7:21 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:40:01PM +0100, Matthew Wilcox (Oracle) wrote:
> The arguments are still pages for now, but we can use folios internally
> and cut out a lot of calls to compound_head().
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 00/17] Folio support in block + iomap layers
  2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
                   ` (16 preceding siblings ...)
  2021-07-19 18:40 ` [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios Matthew Wilcox (Oracle)
@ 2021-07-20  8:44 ` Christoph Hellwig
  2021-07-20 11:08   ` Matthew Wilcox
  17 siblings, 1 reply; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20  8:44 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

Btw, this seems to miss a Cc to linux-block.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 00/17] Folio support in block + iomap layers
  2021-07-20  8:44 ` [PATCH v15 00/17] Folio support in block + iomap layers Christoph Hellwig
@ 2021-07-20 11:08   ` Matthew Wilcox
  0 siblings, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-20 11:08 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-fsdevel, linux-mm, linux-block

On Tue, Jul 20, 2021 at 09:44:28AM +0100, Christoph Hellwig wrote:
> Btw, this seems to miss a Cc to linux-block.

hm?  i see it on linux-block, and so does lore.  maybe vger is being
slow again?

https://lore.kernel.org/linux-block/20210719184001.1750630-1-willy@infradead.org/


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 01/17] block: Add bio_add_folio()
  2021-07-20  6:42   ` Christoph Hellwig
@ 2021-07-20 11:16     ` Matthew Wilcox
  2021-07-22 16:27     ` Matthew Wilcox
  1 sibling, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-20 11:16 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-fsdevel, linux-mm, linux-block

On Tue, Jul 20, 2021 at 07:42:00AM +0100, Christoph Hellwig wrote:
> On Mon, Jul 19, 2021 at 07:39:45PM +0100, Matthew Wilcox (Oracle) wrote:
> > +/**
> > + * bio_add_folio - Attempt to add part of a folio to a bio.
> > + * @bio: Bio to add to.
> > + * @folio: Folio to add.
> > + * @len: How many bytes from the folio to add.
> > + * @off: First byte in this folio to add.
> > + *
> > + * Always uses the head page of the folio in the bio.  If a submitter only
> > + * uses bio_add_folio(), it can count on never seeing tail pages in the
> > + * completion routine.  BIOs do not support folios that are 4GiB or larger.
> > + *
> > + * Return: The number of bytes from this folio added to the bio.
> > + */
> > +size_t bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
> > +		size_t off)
> > +{
> > +	if (len > UINT_MAX || off > UINT_MAX)
> > +		return 0;
> > +	return bio_add_page(bio, &folio->page, len, off);
> > +}
> 
> I'd use the opportunity to switch to a true/false return instead of
> the length.  This has been on my todo list for bio_add_page for a while,
> so it might make sense to start out the new API the right way.

ok.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 05/17] iomap: Convert iomap_page_release to take a folio
  2021-07-20  6:52   ` Christoph Hellwig
@ 2021-07-20 11:29     ` Matthew Wilcox
  2021-07-20 11:40       ` Christoph Hellwig
  0 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-20 11:29 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Tue, Jul 20, 2021 at 08:52:43AM +0200, Christoph Hellwig wrote:
> On Mon, Jul 19, 2021 at 07:39:49PM +0100, Matthew Wilcox (Oracle) wrote:
> > -static void
> > -iomap_page_release(struct page *page)
> > +static void iomap_page_release(struct folio *folio)
> >  {
> > -	struct iomap_page *iop = detach_page_private(page);
> > -	unsigned int nr_blocks = i_blocks_per_page(page->mapping->host, page);
> > +	struct iomap_page *iop = folio_detach_private(folio);
> > +	unsigned int nr_blocks = i_blocks_per_folio(folio->mapping->host,
> > +							folio);
> 
> Nit: but I find this variant much easier to read:
> 
> 	unsigned int nr_blocks =
> 		i_blocks_per_folio(folio->mapping->host, folio);

Probably even better ...

	struct inode *inode = folio->mapping->host;
	unsigned int nr_blocks = i_blocks_per_folio(inode, folio);


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 08/17] iomap: Pass the iomap_page into iomap_set_range_uptodate
  2021-07-20  6:57   ` Christoph Hellwig
@ 2021-07-20 11:36     ` Matthew Wilcox
  0 siblings, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-20 11:36 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Tue, Jul 20, 2021 at 08:57:06AM +0200, Christoph Hellwig wrote:
> On Mon, Jul 19, 2021 at 07:39:52PM +0100, Matthew Wilcox (Oracle) wrote:
> > All but one caller already has the iomap_page, and we can avoid getting
> > it again.
> > 
> > Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> > Reviewed-by: Darrick J. Wong <djwong@kernel.org>
> 
> In general reloading it from a single pointer should be faster than
> passing an extra argument.  What is the rationale here?

I'm not sure we can make that determination in general; it's going to
depend on the number of registers the CPU has, the calling conventions,
how much inlining the compiler chooses to do, etc.

The compiler is actually _forced_ to reload the iop from the page
by the test_bit() in PagePrivate() / folio_test_private().  I want
to kill off that bit, but until I have time to work on that, we
don't have a good workaround.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 05/17] iomap: Convert iomap_page_release to take a folio
  2021-07-20 11:29     ` Matthew Wilcox
@ 2021-07-20 11:40       ` Christoph Hellwig
  0 siblings, 0 replies; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-20 11:40 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Christoph Hellwig, linux-fsdevel, linux-mm, linux-block,
	Darrick J . Wong

On Tue, Jul 20, 2021 at 12:29:23PM +0100, Matthew Wilcox wrote:
> Probably even better ...
> 
> 	struct inode *inode = folio->mapping->host;
> 	unsigned int nr_blocks = i_blocks_per_folio(inode, folio);

Fine with me.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 09/17] iomap: Use folio offsets instead of page offsets
  2021-07-20  6:59   ` Christoph Hellwig
@ 2021-07-20 11:42     ` Matthew Wilcox
  0 siblings, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-20 11:42 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-fsdevel, linux-mm, linux-block, Darrick J . Wong

On Tue, Jul 20, 2021 at 08:59:45AM +0200, Christoph Hellwig wrote:
> > +	size_t poff = offset_in_folio(folio, *pos);
> > +	size_t plen = min_t(loff_t, folio_size(folio) - poff, length);
> 
> These variables are a little misnamed now.  But I'm not sure what a
> better name would be.

Yes, foff and flen would be ambiguous -- is f folio or file?  I tend
to prefer 'offset' and 'length', but we already have a loff_t length
and having both a len and a length isn't conducive to understanding.
Maybe rename loff_t length to extent_len?

I'm going to leave it for now unless we have a really good suggestion.

> > +		size_t off = (page - &folio->page) * PAGE_SIZE +
> > +				bvec->bv_offset;
> 
> Another use case for the helper I suggested earlier.

Deleted in the very next patch, alas.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend to take a folio
  2021-07-20  7:20   ` Christoph Hellwig
@ 2021-07-20 11:45     ` Matthew Wilcox
  0 siblings, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-20 11:45 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-fsdevel, linux-mm, linux-block

On Tue, Jul 20, 2021 at 09:20:43AM +0200, Christoph Hellwig wrote:
> >  	/*
> > -	 * Walk through the page to find areas to write back. If we run off the
> > -	 * end of the current map or find the current map invalid, grab a new
> > -	 * one.
> > +	 * Walk through the folio to find areas to write back. If we
> > +	 * run off the end of the current map or find the current map
> > +	 * invalid, grab a new one.
> 
> Why the reformatting?

s/page/folio/ takes the first line over 80 columns, so pass the whole
comment to 'fmt -p \*'


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 02/17] block: Add bio_for_each_folio_all()
  2021-07-19 18:39 ` [PATCH v15 02/17] block: Add bio_for_each_folio_all() Matthew Wilcox (Oracle)
  2021-07-20  1:29   ` Darrick J. Wong
  2021-07-20  6:48   ` Christoph Hellwig
@ 2021-07-20 12:05   ` kernel test robot
  2021-07-20 12:05   ` kernel test robot
  2021-07-20 12:26   ` kernel test robot
  4 siblings, 0 replies; 62+ messages in thread
From: kernel test robot @ 2021-07-20 12:05 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle), linux-fsdevel
  Cc: clang-built-linux, kbuild-all, Matthew Wilcox (Oracle),
	linux-mm, linux-block

[-- Attachment #1: Type: text/plain, Size: 13224 bytes --]

Hi "Matthew,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.14-rc2 next-20210720]
[cannot apply to xfs-linux/for-next block/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Matthew-Wilcox-Oracle/Folio-support-in-block-iomap-layers/20210720-152323
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 2734d6c1b1a089fb593ef6a23d4b70903526fe0c
config: x86_64-randconfig-r016-20210720 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 87039c048c0cbc3d8cbba86187269b006bf2f373)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/d611eec3f37483e1acbcc299bf47e929766afc8d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matthew-Wilcox-Oracle/Folio-support-in-block-iomap-layers/20210720-152323
        git checkout d611eec3f37483e1acbcc299bf47e929766afc8d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from arch/x86/kernel/asm-offsets.c:13:
   In file included from include/linux/suspend.h:5:
   In file included from include/linux/swap.h:9:
   In file included from include/linux/memcontrol.h:22:
   In file included from include/linux/writeback.h:14:
   In file included from include/linux/blk-cgroup.h:23:
   In file included from include/linux/blkdev.h:18:
   include/linux/bio.h:338:14: error: implicit declaration of function 'page_folio' [-Werror,-Wimplicit-function-declaration]
           fi->folio = page_folio(bvec->bv_page);
                       ^
>> include/linux/bio.h:338:12: warning: incompatible integer to pointer conversion assigning to 'struct folio *' from 'int' [-Wint-conversion]
           fi->folio = page_folio(bvec->bv_page);
                     ^ ~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/bio.h:340:43: error: incomplete definition of type 'struct folio'
                           PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
                                                         ~~~~~~~~~^
   include/linux/bio.h:325:9: note: forward declaration of 'struct folio'
           struct folio *folio;
                  ^
   include/linux/bio.h:342:19: error: implicit declaration of function 'folio_size' [-Werror,-Wimplicit-function-declaration]
           fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
                            ^
   include/linux/bio.h:350:15: error: implicit declaration of function 'folio_next' [-Werror,-Wimplicit-function-declaration]
                   fi->folio = folio_next(fi->folio);
                               ^
   include/linux/bio.h:350:13: warning: incompatible integer to pointer conversion assigning to 'struct folio *' from 'int' [-Wint-conversion]
                   fi->folio = folio_next(fi->folio);
                             ^ ~~~~~~~~~~~~~~~~~~~~~
   include/linux/bio.h:352:20: error: implicit declaration of function 'folio_size' [-Werror,-Wimplicit-function-declaration]
                   fi->length = min(folio_size(fi->folio), fi->_seg_count);
                                    ^
>> include/linux/bio.h:352:16: warning: comparison of distinct pointer types ('typeof (folio_size(fi->folio)) *' (aka 'int *') and 'typeof (fi->_seg_count) *' (aka 'unsigned long *')) [-Wcompare-distinct-pointer-types]
                   fi->length = min(folio_size(fi->folio), fi->_seg_count);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/minmax.h:45:19: note: expanded from macro 'min'
   #define min(x, y)       __careful_cmp(x, y, <)
                           ^~~~~~~~~~~~~~~~~~~~~~
   include/linux/minmax.h:36:24: note: expanded from macro '__careful_cmp'
           __builtin_choose_expr(__safe_cmp(x, y), \
                                 ^~~~~~~~~~~~~~~~
   include/linux/minmax.h:26:4: note: expanded from macro '__safe_cmp'
                   (__typecheck(x, y) && __no_side_effects(x, y))
                    ^~~~~~~~~~~~~~~~~
   include/linux/minmax.h:20:28: note: expanded from macro '__typecheck'
           (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
                      ~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~
   3 warnings and 5 errors generated.
--
   In file included from arch/x86/kernel/asm-offsets.c:13:
   In file included from include/linux/suspend.h:5:
   In file included from include/linux/swap.h:9:
   In file included from include/linux/memcontrol.h:22:
   In file included from include/linux/writeback.h:14:
   In file included from include/linux/blk-cgroup.h:23:
   In file included from include/linux/blkdev.h:18:
   include/linux/bio.h:338:14: error: implicit declaration of function 'page_folio' [-Werror,-Wimplicit-function-declaration]
           fi->folio = page_folio(bvec->bv_page);
                       ^
>> include/linux/bio.h:338:12: warning: incompatible integer to pointer conversion assigning to 'struct folio *' from 'int' [-Wint-conversion]
           fi->folio = page_folio(bvec->bv_page);
                     ^ ~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/bio.h:340:43: error: incomplete definition of type 'struct folio'
                           PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
                                                         ~~~~~~~~~^
   include/linux/bio.h:325:9: note: forward declaration of 'struct folio'
           struct folio *folio;
                  ^
   include/linux/bio.h:342:19: error: implicit declaration of function 'folio_size' [-Werror,-Wimplicit-function-declaration]
           fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
                            ^
   include/linux/bio.h:350:15: error: implicit declaration of function 'folio_next' [-Werror,-Wimplicit-function-declaration]
                   fi->folio = folio_next(fi->folio);
                               ^
   include/linux/bio.h:350:13: warning: incompatible integer to pointer conversion assigning to 'struct folio *' from 'int' [-Wint-conversion]
                   fi->folio = folio_next(fi->folio);
                             ^ ~~~~~~~~~~~~~~~~~~~~~
   include/linux/bio.h:352:20: error: implicit declaration of function 'folio_size' [-Werror,-Wimplicit-function-declaration]
                   fi->length = min(folio_size(fi->folio), fi->_seg_count);
                                    ^
>> include/linux/bio.h:352:16: warning: comparison of distinct pointer types ('typeof (folio_size(fi->folio)) *' (aka 'int *') and 'typeof (fi->_seg_count) *' (aka 'unsigned long *')) [-Wcompare-distinct-pointer-types]
                   fi->length = min(folio_size(fi->folio), fi->_seg_count);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/minmax.h:45:19: note: expanded from macro 'min'
   #define min(x, y)       __careful_cmp(x, y, <)
                           ^~~~~~~~~~~~~~~~~~~~~~
   include/linux/minmax.h:36:24: note: expanded from macro '__careful_cmp'
           __builtin_choose_expr(__safe_cmp(x, y), \
                                 ^~~~~~~~~~~~~~~~
   include/linux/minmax.h:26:4: note: expanded from macro '__safe_cmp'
                   (__typecheck(x, y) && __no_side_effects(x, y))
                    ^~~~~~~~~~~~~~~~~
   include/linux/minmax.h:20:28: note: expanded from macro '__typecheck'
           (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
                      ~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~
   3 warnings and 5 errors generated.
   make[2]: *** [scripts/Makefile.build:117: arch/x86/kernel/asm-offsets.s] Error 1
   make[2]: Target '__build' not remade because of errors.
   make[1]: *** [Makefile:1213: prepare0] Error 2
   make[1]: Target 'modules_prepare' not remade because of errors.
   make: *** [Makefile:220: __sub-make] Error 2
   make: Target 'modules_prepare' not remade because of errors.
--
   In file included from arch/x86/kernel/asm-offsets.c:13:
   In file included from include/linux/suspend.h:5:
   In file included from include/linux/swap.h:9:
   In file included from include/linux/memcontrol.h:22:
   In file included from include/linux/writeback.h:14:
   In file included from include/linux/blk-cgroup.h:23:
   In file included from include/linux/blkdev.h:18:
   include/linux/bio.h:338:14: error: implicit declaration of function 'page_folio' [-Werror,-Wimplicit-function-declaration]
           fi->folio = page_folio(bvec->bv_page);
                       ^
>> include/linux/bio.h:338:12: warning: incompatible integer to pointer conversion assigning to 'struct folio *' from 'int' [-Wint-conversion]
           fi->folio = page_folio(bvec->bv_page);
                     ^ ~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/bio.h:340:43: error: incomplete definition of type 'struct folio'
                           PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
                                                         ~~~~~~~~~^
   include/linux/bio.h:325:9: note: forward declaration of 'struct folio'
           struct folio *folio;
                  ^
   include/linux/bio.h:342:19: error: implicit declaration of function 'folio_size' [-Werror,-Wimplicit-function-declaration]
           fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
                            ^
   include/linux/bio.h:350:15: error: implicit declaration of function 'folio_next' [-Werror,-Wimplicit-function-declaration]
                   fi->folio = folio_next(fi->folio);
                               ^
   include/linux/bio.h:350:13: warning: incompatible integer to pointer conversion assigning to 'struct folio *' from 'int' [-Wint-conversion]
                   fi->folio = folio_next(fi->folio);
                             ^ ~~~~~~~~~~~~~~~~~~~~~
   include/linux/bio.h:352:20: error: implicit declaration of function 'folio_size' [-Werror,-Wimplicit-function-declaration]
                   fi->length = min(folio_size(fi->folio), fi->_seg_count);
                                    ^
>> include/linux/bio.h:352:16: warning: comparison of distinct pointer types ('typeof (folio_size(fi->folio)) *' (aka 'int *') and 'typeof (fi->_seg_count) *' (aka 'unsigned long *')) [-Wcompare-distinct-pointer-types]
                   fi->length = min(folio_size(fi->folio), fi->_seg_count);
                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/minmax.h:45:19: note: expanded from macro 'min'
   #define min(x, y)       __careful_cmp(x, y, <)
                           ^~~~~~~~~~~~~~~~~~~~~~
   include/linux/minmax.h:36:24: note: expanded from macro '__careful_cmp'
           __builtin_choose_expr(__safe_cmp(x, y), \
                                 ^~~~~~~~~~~~~~~~
   include/linux/minmax.h:26:4: note: expanded from macro '__safe_cmp'
                   (__typecheck(x, y) && __no_side_effects(x, y))
                    ^~~~~~~~~~~~~~~~~
   include/linux/minmax.h:20:28: note: expanded from macro '__typecheck'
           (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
                      ~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~
   3 warnings and 5 errors generated.
   make[2]: *** [scripts/Makefile.build:117: arch/x86/kernel/asm-offsets.s] Error 1
   make[2]: Target '__build' not remade because of errors.
   make[1]: *** [Makefile:1213: prepare0] Error 2
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [Makefile:220: __sub-make] Error 2
   make: Target 'prepare' not remade because of errors.


vim +338 include/linux/bio.h

   332	
   333	static inline
   334	void bio_first_folio(struct folio_iter *fi, struct bio *bio, int i)
   335	{
   336		struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
   337	
 > 338		fi->folio = page_folio(bvec->bv_page);
   339		fi->offset = bvec->bv_offset +
   340				PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
   341		fi->_seg_count = bvec->bv_len;
   342		fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
   343		fi->_i = i;
   344	}
   345	
   346	static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
   347	{
   348		fi->_seg_count -= fi->length;
   349		if (fi->_seg_count) {
   350			fi->folio = folio_next(fi->folio);
   351			fi->offset = 0;
 > 352			fi->length = min(folio_size(fi->folio), fi->_seg_count);
   353		} else if (fi->_i + 1 < bio->bi_vcnt) {
   354			bio_first_folio(fi, bio, fi->_i + 1);
   355		} else {
   356			fi->folio = NULL;
   357		}
   358	}
   359	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46021 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 02/17] block: Add bio_for_each_folio_all()
  2021-07-19 18:39 ` [PATCH v15 02/17] block: Add bio_for_each_folio_all() Matthew Wilcox (Oracle)
                     ` (2 preceding siblings ...)
  2021-07-20 12:05   ` kernel test robot
@ 2021-07-20 12:05   ` kernel test robot
  2021-07-20 12:26   ` kernel test robot
  4 siblings, 0 replies; 62+ messages in thread
From: kernel test robot @ 2021-07-20 12:05 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle), linux-fsdevel
  Cc: kbuild-all, Matthew Wilcox (Oracle), linux-mm, linux-block

[-- Attachment #1: Type: text/plain, Size: 14817 bytes --]

Hi "Matthew,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.14-rc2 next-20210720]
[cannot apply to xfs-linux/for-next block/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Matthew-Wilcox-Oracle/Folio-support-in-block-iomap-layers/20210720-152323
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 2734d6c1b1a089fb593ef6a23d4b70903526fe0c
config: sparc-randconfig-r015-20210720 (attached as .config)
compiler: sparc64-linux-gcc (GCC) 10.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/d611eec3f37483e1acbcc299bf47e929766afc8d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matthew-Wilcox-Oracle/Folio-support-in-block-iomap-layers/20210720-152323
        git checkout d611eec3f37483e1acbcc299bf47e929766afc8d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-10.3.0 make.cross ARCH=sparc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/linux/tracehook.h:50,
                    from arch/sparc/kernel/signal_64.c:18:
   include/linux/bio.h: In function 'bio_first_folio':
   include/linux/bio.h:338:14: error: implicit declaration of function 'page_folio' [-Werror=implicit-function-declaration]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |              ^~~~~~~~~~
>> include/linux/bio.h:338:12: error: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |            ^
   include/linux/bio.h:340:43: error: invalid use of undefined type 'struct folio'
     340 |    PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
         |                                           ^~
   In file included from include/linux/kernel.h:16,
                    from include/linux/list.h:9,
                    from include/linux/rculist.h:10,
                    from include/linux/pid.h:5,
                    from include/linux/sched.h:14,
                    from arch/sparc/kernel/signal_64.c:12:
   include/linux/bio.h:342:19: error: implicit declaration of function 'folio_size' [-Werror=implicit-function-declaration]
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |                   ^~~~~~~~~~
   include/linux/minmax.h:20:21: note: in definition of macro '__typecheck'
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                     ^
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:342:15: note: in expansion of macro 'min'
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |               ^~~
   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/linux/tracehook.h:50,
                    from arch/sparc/kernel/signal_64.c:18:
   include/linux/bio.h: In function 'bio_next_folio':
   include/linux/bio.h:350:15: error: implicit declaration of function 'folio_next' [-Werror=implicit-function-declaration]
     350 |   fi->folio = folio_next(fi->folio);
         |               ^~~~~~~~~~
   include/linux/bio.h:350:13: error: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion]
     350 |   fi->folio = folio_next(fi->folio);
         |             ^
   In file included from include/linux/kernel.h:16,
                    from include/linux/list.h:9,
                    from include/linux/rculist.h:10,
                    from include/linux/pid.h:5,
                    from include/linux/sched.h:14,
                    from arch/sparc/kernel/signal_64.c:12:
   include/linux/minmax.h:20:28: error: comparison of distinct pointer types lacks a cast [-Werror]
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                            ^~
   include/linux/minmax.h:26:4: note: in expansion of macro '__typecheck'
      26 |   (__typecheck(x, y) && __no_side_effects(x, y))
         |    ^~~~~~~~~~~
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:352:16: note: in expansion of macro 'min'
     352 |   fi->length = min(folio_size(fi->folio), fi->_seg_count);
         |                ^~~
   cc1: all warnings being treated as errors
--
   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/linux/swap.h:9,
                    from arch/sparc/include/asm/tlb_64.h:5,
                    from arch/sparc/include/asm/tlb.h:5,
                    from arch/sparc/kernel/smp_64.c:49:
   include/linux/bio.h: In function 'bio_first_folio':
   include/linux/bio.h:338:14: error: implicit declaration of function 'page_folio'; did you mean 'page_endio'? [-Werror=implicit-function-declaration]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |              ^~~~~~~~~~
         |              page_endio
>> include/linux/bio.h:338:12: error: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |            ^
   include/linux/bio.h:340:43: error: invalid use of undefined type 'struct folio'
     340 |    PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
         |                                           ^~
   In file included from include/linux/kernel.h:16,
                    from arch/sparc/kernel/smp_64.c:8:
   include/linux/bio.h:342:19: error: implicit declaration of function 'folio_size' [-Werror=implicit-function-declaration]
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |                   ^~~~~~~~~~
   include/linux/minmax.h:20:21: note: in definition of macro '__typecheck'
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                     ^
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:342:15: note: in expansion of macro 'min'
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |               ^~~
   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/linux/swap.h:9,
                    from arch/sparc/include/asm/tlb_64.h:5,
                    from arch/sparc/include/asm/tlb.h:5,
                    from arch/sparc/kernel/smp_64.c:49:
   include/linux/bio.h: In function 'bio_next_folio':
   include/linux/bio.h:350:15: error: implicit declaration of function 'folio_next' [-Werror=implicit-function-declaration]
     350 |   fi->folio = folio_next(fi->folio);
         |               ^~~~~~~~~~
   include/linux/bio.h:350:13: error: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion]
     350 |   fi->folio = folio_next(fi->folio);
         |             ^
   In file included from include/linux/kernel.h:16,
                    from arch/sparc/kernel/smp_64.c:8:
   include/linux/minmax.h:20:28: error: comparison of distinct pointer types lacks a cast [-Werror]
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                            ^~
   include/linux/minmax.h:26:4: note: in expansion of macro '__typecheck'
      26 |   (__typecheck(x, y) && __no_side_effects(x, y))
         |    ^~~~~~~~~~~
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:352:16: note: in expansion of macro 'min'
     352 |   fi->length = min(folio_size(fi->folio), fi->_seg_count);
         |                ^~~
   cc1: all warnings being treated as errors
--
   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/net/sock.h:53,
                    from include/linux/tcp.h:19,
                    from include/linux/ipv6.h:88,
                    from arch/sparc/kernel/sys_sparc32.c:33:
   include/linux/bio.h: In function 'bio_first_folio':
   include/linux/bio.h:338:14: error: implicit declaration of function 'page_folio' [-Werror=implicit-function-declaration]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |              ^~~~~~~~~~
>> include/linux/bio.h:338:12: error: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |            ^
   include/linux/bio.h:340:43: error: invalid use of undefined type 'struct folio'
     340 |    PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
         |                                           ^~
   In file included from include/linux/kernel.h:16,
                    from arch/sparc/kernel/sys_sparc32.c:11:
   include/linux/bio.h:342:19: error: implicit declaration of function 'folio_size' [-Werror=implicit-function-declaration]
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |                   ^~~~~~~~~~
   include/linux/minmax.h:20:21: note: in definition of macro '__typecheck'
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                     ^
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:342:15: note: in expansion of macro 'min'
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |               ^~~
   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/net/sock.h:53,
                    from include/linux/tcp.h:19,
                    from include/linux/ipv6.h:88,
                    from arch/sparc/kernel/sys_sparc32.c:33:
   include/linux/bio.h: In function 'bio_next_folio':
   include/linux/bio.h:350:15: error: implicit declaration of function 'folio_next'; did you mean 'nla_next'? [-Werror=implicit-function-declaration]
     350 |   fi->folio = folio_next(fi->folio);
         |               ^~~~~~~~~~
         |               nla_next
   include/linux/bio.h:350:13: error: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Werror=int-conversion]
     350 |   fi->folio = folio_next(fi->folio);
         |             ^
   In file included from include/linux/kernel.h:16,
                    from arch/sparc/kernel/sys_sparc32.c:11:
   include/linux/minmax.h:20:28: error: comparison of distinct pointer types lacks a cast [-Werror]
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                            ^~
   include/linux/minmax.h:26:4: note: in expansion of macro '__typecheck'
      26 |   (__typecheck(x, y) && __no_side_effects(x, y))
         |    ^~~~~~~~~~~
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:352:16: note: in expansion of macro 'min'
     352 |   fi->length = min(folio_size(fi->folio), fi->_seg_count);
         |                ^~~
   cc1: all warnings being treated as errors


vim +338 include/linux/bio.h

   332	
   333	static inline
   334	void bio_first_folio(struct folio_iter *fi, struct bio *bio, int i)
   335	{
   336		struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
   337	
 > 338		fi->folio = page_folio(bvec->bv_page);
   339		fi->offset = bvec->bv_offset +
   340				PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
   341		fi->_seg_count = bvec->bv_len;
   342		fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
   343		fi->_i = i;
   344	}
   345	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 37403 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 02/17] block: Add bio_for_each_folio_all()
  2021-07-19 18:39 ` [PATCH v15 02/17] block: Add bio_for_each_folio_all() Matthew Wilcox (Oracle)
                     ` (3 preceding siblings ...)
  2021-07-20 12:05   ` kernel test robot
@ 2021-07-20 12:26   ` kernel test robot
  4 siblings, 0 replies; 62+ messages in thread
From: kernel test robot @ 2021-07-20 12:26 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle), linux-fsdevel
  Cc: kbuild-all, Matthew Wilcox (Oracle), linux-mm, linux-block

[-- Attachment #1: Type: text/plain, Size: 10978 bytes --]

Hi "Matthew,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.14-rc2 next-20210720]
[cannot apply to xfs-linux/for-next block/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Matthew-Wilcox-Oracle/Folio-support-in-block-iomap-layers/20210720-152323
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 2734d6c1b1a089fb593ef6a23d4b70903526fe0c
config: i386-tinyconfig (attached as .config)
compiler: gcc-10 (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/d611eec3f37483e1acbcc299bf47e929766afc8d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matthew-Wilcox-Oracle/Folio-support-in-block-iomap-layers/20210720-152323
        git checkout d611eec3f37483e1acbcc299bf47e929766afc8d
        # save the attached .config to linux build tree
        make W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/linux/swap.h:9,
                    from include/linux/suspend.h:5,
                    from arch/x86/kernel/asm-offsets.c:13:
   include/linux/bio.h: In function 'bio_first_folio':
>> include/linux/bio.h:338:14: error: implicit declaration of function 'page_folio' [-Werror=implicit-function-declaration]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |              ^~~~~~~~~~
>> include/linux/bio.h:338:12: warning: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |            ^
>> include/linux/bio.h:340:43: error: invalid use of undefined type 'struct folio'
     340 |    PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
         |                                           ^~
   In file included from include/linux/kernel.h:16,
                    from include/linux/crypto.h:16,
                    from arch/x86/kernel/asm-offsets.c:9:
>> include/linux/bio.h:342:19: error: implicit declaration of function 'folio_size' [-Werror=implicit-function-declaration]
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |                   ^~~~~~~~~~
   include/linux/minmax.h:20:21: note: in definition of macro '__typecheck'
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                     ^
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:342:15: note: in expansion of macro 'min'
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |               ^~~
   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/linux/swap.h:9,
                    from include/linux/suspend.h:5,
                    from arch/x86/kernel/asm-offsets.c:13:
   include/linux/bio.h: In function 'bio_next_folio':
>> include/linux/bio.h:350:15: error: implicit declaration of function 'folio_next' [-Werror=implicit-function-declaration]
     350 |   fi->folio = folio_next(fi->folio);
         |               ^~~~~~~~~~
   include/linux/bio.h:350:13: warning: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     350 |   fi->folio = folio_next(fi->folio);
         |             ^
   In file included from include/linux/kernel.h:16,
                    from include/linux/crypto.h:16,
                    from arch/x86/kernel/asm-offsets.c:9:
   include/linux/minmax.h:20:28: warning: comparison of distinct pointer types lacks a cast
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                            ^~
   include/linux/minmax.h:26:4: note: in expansion of macro '__typecheck'
      26 |   (__typecheck(x, y) && __no_side_effects(x, y))
         |    ^~~~~~~~~~~
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:352:16: note: in expansion of macro 'min'
     352 |   fi->length = min(folio_size(fi->folio), fi->_seg_count);
         |                ^~~
   cc1: some warnings being treated as errors
--
   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/linux/swap.h:9,
                    from include/linux/suspend.h:5,
                    from arch/x86/kernel/asm-offsets.c:13:
   include/linux/bio.h: In function 'bio_first_folio':
>> include/linux/bio.h:338:14: error: implicit declaration of function 'page_folio' [-Werror=implicit-function-declaration]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |              ^~~~~~~~~~
>> include/linux/bio.h:338:12: warning: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     338 |  fi->folio = page_folio(bvec->bv_page);
         |            ^
>> include/linux/bio.h:340:43: error: invalid use of undefined type 'struct folio'
     340 |    PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
         |                                           ^~
   In file included from include/linux/kernel.h:16,
                    from include/linux/crypto.h:16,
                    from arch/x86/kernel/asm-offsets.c:9:
>> include/linux/bio.h:342:19: error: implicit declaration of function 'folio_size' [-Werror=implicit-function-declaration]
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |                   ^~~~~~~~~~
   include/linux/minmax.h:20:21: note: in definition of macro '__typecheck'
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                     ^
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:342:15: note: in expansion of macro 'min'
     342 |  fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
         |               ^~~
   In file included from include/linux/blkdev.h:18,
                    from include/linux/blk-cgroup.h:23,
                    from include/linux/writeback.h:14,
                    from include/linux/memcontrol.h:22,
                    from include/linux/swap.h:9,
                    from include/linux/suspend.h:5,
                    from arch/x86/kernel/asm-offsets.c:13:
   include/linux/bio.h: In function 'bio_next_folio':
>> include/linux/bio.h:350:15: error: implicit declaration of function 'folio_next' [-Werror=implicit-function-declaration]
     350 |   fi->folio = folio_next(fi->folio);
         |               ^~~~~~~~~~
   include/linux/bio.h:350:13: warning: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     350 |   fi->folio = folio_next(fi->folio);
         |             ^
   In file included from include/linux/kernel.h:16,
                    from include/linux/crypto.h:16,
                    from arch/x86/kernel/asm-offsets.c:9:
   include/linux/minmax.h:20:28: warning: comparison of distinct pointer types lacks a cast
      20 |  (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
         |                            ^~
   include/linux/minmax.h:26:4: note: in expansion of macro '__typecheck'
      26 |   (__typecheck(x, y) && __no_side_effects(x, y))
         |    ^~~~~~~~~~~
   include/linux/minmax.h:36:24: note: in expansion of macro '__safe_cmp'
      36 |  __builtin_choose_expr(__safe_cmp(x, y), \
         |                        ^~~~~~~~~~
   include/linux/minmax.h:45:19: note: in expansion of macro '__careful_cmp'
      45 | #define min(x, y) __careful_cmp(x, y, <)
         |                   ^~~~~~~~~~~~~
   include/linux/bio.h:352:16: note: in expansion of macro 'min'
     352 |   fi->length = min(folio_size(fi->folio), fi->_seg_count);
         |                ^~~
   cc1: some warnings being treated as errors
   make[2]: *** [scripts/Makefile.build:117: arch/x86/kernel/asm-offsets.s] Error 1
   make[2]: Target '__build' not remade because of errors.
   make[1]: *** [Makefile:1213: prepare0] Error 2
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [Makefile:220: __sub-make] Error 2
   make: Target 'prepare' not remade because of errors.


vim +/page_folio +338 include/linux/bio.h

   332	
   333	static inline
   334	void bio_first_folio(struct folio_iter *fi, struct bio *bio, int i)
   335	{
   336		struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
   337	
 > 338		fi->folio = page_folio(bvec->bv_page);
   339		fi->offset = bvec->bv_offset +
 > 340				PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
   341		fi->_seg_count = bvec->bv_len;
 > 342		fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
   343		fi->_i = i;
   344	}
   345	
   346	static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
   347	{
   348		fi->_seg_count -= fi->length;
   349		if (fi->_seg_count) {
 > 350			fi->folio = folio_next(fi->folio);
   351			fi->offset = 0;
   352			fi->length = min(folio_size(fi->folio), fi->_seg_count);
   353		} else if (fi->_i + 1 < bio->bi_vcnt) {
   354			bio_first_folio(fi, bio, fi->_i + 1);
   355		} else {
   356			fi->folio = NULL;
   357		}
   358	}
   359	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 7452 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios
  2021-07-19 18:40 ` [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios Matthew Wilcox (Oracle)
  2021-07-20  7:21   ` Christoph Hellwig
@ 2021-07-20 13:30   ` kernel test robot
  2021-07-21  0:02   ` Darrick J. Wong
  2 siblings, 0 replies; 62+ messages in thread
From: kernel test robot @ 2021-07-20 13:30 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle), linux-fsdevel
  Cc: kbuild-all, Matthew Wilcox (Oracle), linux-mm, linux-block

[-- Attachment #1: Type: text/plain, Size: 17027 bytes --]

Hi "Matthew,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.14-rc2 next-20210720]
[cannot apply to xfs-linux/for-next block/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Matthew-Wilcox-Oracle/Folio-support-in-block-iomap-layers/20210720-152323
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 2734d6c1b1a089fb593ef6a23d4b70903526fe0c
config: openrisc-randconfig-p002-20210720 (attached as .config)
compiler: or1k-linux-gcc (GCC) 10.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/c560a69342e882de7f1fd097fa2589e8d330eba0
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Matthew-Wilcox-Oracle/Folio-support-in-block-iomap-layers/20210720-152323
        git checkout c560a69342e882de7f1fd097fa2589e8d330eba0
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-10.3.0 make.cross ARCH=openrisc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

         |                                  ^
   include/asm-generic/bug.h:65:36: note: in expansion of macro 'unlikely'
      65 | #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
         |                                    ^~~~~~~~
   fs/iomap/buffered-io.c:207:2: note: in expansion of macro 'BUG_ON'
     207 |  BUG_ON(folio->index);
         |  ^~~~~~
   fs/iomap/buffered-io.c:207:14: error: invalid use of undefined type 'struct folio'
     207 |  BUG_ON(folio->index);
         |              ^~
   include/linux/compiler.h:35:19: note: in definition of macro '__branch_check__'
      35 |           expect, is_constant); \
         |                   ^~~~~~~~~~~
   include/asm-generic/bug.h:65:36: note: in expansion of macro 'unlikely'
      65 | #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
         |                                    ^~~~~~~~
   fs/iomap/buffered-io.c:207:2: note: in expansion of macro 'BUG_ON'
     207 |  BUG_ON(folio->index);
         |  ^~~~~~
   fs/iomap/buffered-io.c:208:9: error: implicit declaration of function 'folio_multi' [-Werror=implicit-function-declaration]
     208 |  BUG_ON(folio_multi(folio));
         |         ^~~~~~~~~~~
   include/linux/compiler.h:33:34: note: in definition of macro '__branch_check__'
      33 |    ______r = __builtin_expect(!!(x), expect); \
         |                                  ^
   include/asm-generic/bug.h:65:36: note: in expansion of macro 'unlikely'
      65 | #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
         |                                    ^~~~~~~~
   fs/iomap/buffered-io.c:208:2: note: in expansion of macro 'BUG_ON'
     208 |  BUG_ON(folio_multi(folio));
         |  ^~~~~~
   fs/iomap/buffered-io.c:211:9: error: implicit declaration of function 'kmap_local_folio'; did you mean 'kmap_local_fork'? [-Werror=implicit-function-declaration]
     211 |  addr = kmap_local_folio(folio, 0);
         |         ^~~~~~~~~~~~~~~~
         |         kmap_local_fork
   fs/iomap/buffered-io.c:211:7: warning: assignment to 'void *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     211 |  addr = kmap_local_folio(folio, 0);
         |       ^
   fs/iomap/buffered-io.c: In function 'iomap_readpage_actor':
   fs/iomap/buffered-io.c:251:19: error: invalid use of undefined type 'struct folio'
     251 |   zero_user(&folio->page, poff, plen);
         |                   ^~
   fs/iomap/buffered-io.c:263:44: error: invalid use of undefined type 'struct folio'
     263 |   if (__bio_try_merge_page(ctx->bio, &folio->page, plen, poff,
         |                                            ^~
   fs/iomap/buffered-io.c:270:43: error: invalid use of undefined type 'struct folio'
     270 |   gfp_t gfp = mapping_gfp_constraint(folio->mapping, GFP_KERNEL);
         |                                           ^~
   fs/iomap/buffered-io.c: In function 'iomap_readpage':
   fs/iomap/buffered-io.c:309:24: warning: initialization of 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     309 |  struct folio *folio = page_folio(page);
         |                        ^~~~~~~~~~
   fs/iomap/buffered-io.c:311:29: error: invalid use of undefined type 'struct folio'
     311 |  struct inode *inode = folio->mapping->host;
         |                             ^~
   fs/iomap/buffered-io.c:319:28: error: implicit declaration of function 'folio_pos' [-Werror=implicit-function-declaration]
     319 |   ret = iomap_apply(inode, folio_pos(folio) + poff, len - poff,
         |                            ^~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_readahead_actor':
   fs/iomap/buffered-io.c:360:21: error: implicit declaration of function 'readahead_folio'; did you mean 'readahead_count'? [-Werror=implicit-function-declaration]
     360 |    ctx->cur_folio = readahead_folio(ctx->rac);
         |                     ^~~~~~~~~~~~~~~
         |                     readahead_count
   fs/iomap/buffered-io.c:360:19: warning: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     360 |    ctx->cur_folio = readahead_folio(ctx->rac);
         |                   ^
   fs/iomap/buffered-io.c: In function 'iomap_is_partially_uptodate':
   fs/iomap/buffered-io.c:427:24: warning: initialization of 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     427 |  struct folio *folio = page_folio(page);
         |                        ^~~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_releasepage':
   fs/iomap/buffered-io.c:454:24: warning: initialization of 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     454 |  struct folio *folio = page_folio(page);
         |                        ^~~~~~~~~~
   fs/iomap/buffered-io.c:456:31: error: invalid use of undefined type 'struct folio'
     456 |  trace_iomap_releasepage(folio->mapping->host, folio_pos(folio),
         |                               ^~
   fs/iomap/buffered-io.c:464:6: error: implicit declaration of function 'folio_test_dirty' [-Werror=implicit-function-declaration]
     464 |  if (folio_test_dirty(folio) || folio_test_writeback(folio))
         |      ^~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c:464:33: error: implicit declaration of function 'folio_test_writeback' [-Werror=implicit-function-declaration]
     464 |  if (folio_test_dirty(folio) || folio_test_writeback(folio))
         |                                 ^~~~~~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_invalidatepage':
   fs/iomap/buffered-io.c:474:24: warning: initialization of 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     474 |  struct folio *folio = page_folio(page);
         |                        ^~~~~~~~~~
   fs/iomap/buffered-io.c:476:34: error: invalid use of undefined type 'struct folio'
     476 |  trace_iomap_invalidatepage(folio->mapping->host, offset, len);
         |                                  ^~
   fs/iomap/buffered-io.c:484:3: error: implicit declaration of function 'folio_cancel_dirty' [-Werror=implicit-function-declaration]
     484 |   folio_cancel_dirty(folio);
         |   ^~~~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_migrate_page':
   fs/iomap/buffered-io.c:495:24: warning: initialization of 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     495 |  struct folio *folio = page_folio(page);
         |                        ^~~~~~~~~~
   fs/iomap/buffered-io.c:496:27: warning: initialization of 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     496 |  struct folio *newfolio = page_folio(newpage);
         |                           ^~~~~~~~~~
>> fs/iomap/buffered-io.c:499:8: error: implicit declaration of function 'folio_migrate_mapping' [-Werror=implicit-function-declaration]
     499 |  ret = folio_migrate_mapping(mapping, newfolio, folio, 0);
         |        ^~~~~~~~~~~~~~~~~~~~~
>> fs/iomap/buffered-io.c:507:3: error: implicit declaration of function 'folio_migrate_copy' [-Werror=implicit-function-declaration]
     507 |   folio_migrate_copy(newfolio, folio);
         |   ^~~~~~~~~~~~~~~~~~
>> fs/iomap/buffered-io.c:509:3: error: implicit declaration of function 'folio_migrate_flags'; did you mean 'do_migrate_pages'? [-Werror=implicit-function-declaration]
     509 |   folio_migrate_flags(newfolio, folio);
         |   ^~~~~~~~~~~~~~~~~~~
         |   do_migrate_pages
   fs/iomap/buffered-io.c: In function '__iomap_write_begin':
   fs/iomap/buffered-io.c:559:2: error: implicit declaration of function 'folio_clear_error' [-Werror=implicit-function-declaration]
     559 |  folio_clear_error(folio);
         |  ^~~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c:575:29: error: invalid use of undefined type 'struct folio'
     575 |    zero_user_segments(&folio->page, poff, from, to,
         |                             ^~
   fs/iomap/buffered-io.c: In function 'iomap_write_begin':
   fs/iomap/buffered-io.c:596:52: error: 'FGP_STABLE' undeclared (first use in this function)
     596 |  unsigned fgp = FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE | FGP_NOFS;
         |                                                    ^~~~~~~~~~
   fs/iomap/buffered-io.c:596:52: note: each undeclared identifier is reported only once for each function it appears in
   fs/iomap/buffered-io.c:612:10: error: implicit declaration of function '__filemap_get_folio' [-Werror=implicit-function-declaration]
     612 |  folio = __filemap_get_folio(inode->i_mapping, pos >> PAGE_SHIFT, fgp,
         |          ^~~~~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c:612:8: warning: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     612 |  folio = __filemap_get_folio(inode->i_mapping, pos >> PAGE_SHIFT, fgp,
         |        ^
   fs/iomap/buffered-io.c:619:9: error: implicit declaration of function 'folio_file_page' [-Werror=implicit-function-declaration]
     619 |  page = folio_file_page(folio, pos >> PAGE_SHIFT);
         |         ^~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c:619:7: warning: assignment to 'struct page *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     619 |  page = folio_file_page(folio, pos >> PAGE_SHIFT);
         |       ^
   fs/iomap/buffered-io.c:636:2: error: implicit declaration of function 'folio_put'; did you mean 'bio_put'? [-Werror=implicit-function-declaration]
     636 |  folio_put(folio);
         |  ^~~~~~~~~
         |  bio_put
   fs/iomap/buffered-io.c: In function '__iomap_write_end':
   fs/iomap/buffered-io.c:649:2: error: implicit declaration of function 'flush_dcache_folio'; did you mean 'flush_cache_all'? [-Werror=implicit-function-declaration]
     649 |  flush_dcache_folio(folio);
         |  ^~~~~~~~~~~~~~~~~~
         |  flush_cache_all
   fs/iomap/buffered-io.c:665:2: error: implicit declaration of function 'filemap_dirty_folio' [-Werror=implicit-function-declaration]
     665 |  filemap_dirty_folio(inode->i_mapping, folio);
         |  ^~~~~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_write_end_inline':
   fs/iomap/buffered-io.c:678:7: warning: assignment to 'void *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     678 |  addr = kmap_local_folio(folio, 0);
         |       ^
   fs/iomap/buffered-io.c: In function 'iomap_write_end':
   fs/iomap/buffered-io.c:691:22: warning: initialization of 'struct page *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     691 |  struct page *page = folio_file_page(folio, pos >> PAGE_SHIFT);
         |                      ^~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_write_actor':
   fs/iomap/buffered-io.c:765:8: warning: assignment to 'struct page *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     765 |   page = folio_file_page(folio, pos >> PAGE_SHIFT);
         |        ^
   fs/iomap/buffered-io.c: In function 'iomap_zero':
   fs/iomap/buffered-io.c:891:12: warning: passing argument 1 of 'zero_user' makes pointer from integer without a cast [-Wint-conversion]
     891 |  zero_user(folio_file_page(folio, pos >> PAGE_SHIFT), offset, bytes);
         |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |            |
         |            int
   In file included from include/linux/bio.h:8,
                    from include/linux/blkdev.h:18,
                    from include/linux/iomap.h:11,
                    from fs/iomap/buffered-io.c:9:
   include/linux/highmem.h:231:43: note: expected 'struct page *' but argument is of type 'int'
     231 | static inline void zero_user(struct page *page,
         |                              ~~~~~~~~~~~~~^~~~
   fs/iomap/buffered-io.c:892:2: error: implicit declaration of function 'folio_mark_accessed' [-Werror=implicit-function-declaration]
     892 |  folio_mark_accessed(folio);
         |  ^~~~~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_folio_mkwrite_actor':
   fs/iomap/buffered-io.c:970:39: error: invalid use of undefined type 'struct folio'
     970 |   ret = __block_write_begin_int(&folio->page, pos, length, NULL,
         |                                       ^~
   fs/iomap/buffered-io.c:974:28: error: invalid use of undefined type 'struct folio'
     974 |   block_commit_write(&folio->page, 0, length);
         |                            ^~
   fs/iomap/buffered-io.c:977:3: error: implicit declaration of function 'folio_mark_dirty' [-Werror=implicit-function-declaration]
     977 |   folio_mark_dirty(folio);
         |   ^~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_page_mkwrite':
   fs/iomap/buffered-io.c:985:24: warning: initialization of 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     985 |  struct folio *folio = page_folio(vmf->page);
         |                        ^~~~~~~~~~
   fs/iomap/buffered-io.c:991:2: error: implicit declaration of function 'folio_lock'; did you mean 'osq_lock'? [-Werror=implicit-function-declaration]
     991 |  folio_lock(folio);
         |  ^~~~~~~~~~
         |  osq_lock
   fs/iomap/buffered-io.c:992:8: error: implicit declaration of function 'folio_mkwrite_check_truncate'; did you mean 'page_mkwrite_check_truncate'? [-Werror=implicit-function-declaration]
     992 |  ret = folio_mkwrite_check_truncate(folio, inode);
         |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |        page_mkwrite_check_truncate
   fs/iomap/buffered-io.c:1008:2: error: implicit declaration of function 'folio_wait_stable' [-Werror=implicit-function-declaration]
    1008 |  folio_wait_stable(folio);
         |  ^~~~~~~~~~~~~~~~~
   fs/iomap/buffered-io.c: In function 'iomap_finish_folio_write':
   fs/iomap/buffered-io.c:1030:3: error: implicit declaration of function 'folio_end_writeback'; did you mean 'file_end_write'? [-Werror=implicit-function-declaration]
    1030 |   folio_end_writeback(folio);
         |   ^~~~~~~~~~~~~~~~~~~
         |   file_end_write
   fs/iomap/buffered-io.c: In function 'iomap_add_to_ioend':
   fs/iomap/buffered-io.c:1280:38: error: invalid use of undefined type 'struct folio'
    1280 |  wbc_account_cgroup_owner(wbc, &folio->page, len);


vim +/folio_migrate_mapping +499 fs/iomap/buffered-io.c

   489	
   490	#ifdef CONFIG_MIGRATION
   491	int
   492	iomap_migrate_page(struct address_space *mapping, struct page *newpage,
   493			struct page *page, enum migrate_mode mode)
   494	{
   495		struct folio *folio = page_folio(page);
   496		struct folio *newfolio = page_folio(newpage);
   497		int ret;
   498	
 > 499		ret = folio_migrate_mapping(mapping, newfolio, folio, 0);
   500		if (ret != MIGRATEPAGE_SUCCESS)
   501			return ret;
   502	
   503		if (folio_test_private(folio))
   504			folio_attach_private(newfolio, folio_detach_private(folio));
   505	
   506		if (mode != MIGRATE_SYNC_NO_COPY)
 > 507			folio_migrate_copy(newfolio, folio);
   508		else
 > 509			folio_migrate_flags(newfolio, folio);
   510		return MIGRATEPAGE_SUCCESS;
   511	}
   512	EXPORT_SYMBOL_GPL(iomap_migrate_page);
   513	#endif /* CONFIG_MIGRATION */
   514	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 22003 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 06/17] iomap: Convert iomap_releasepage to use a folio
  2021-07-19 18:39 ` [PATCH v15 06/17] iomap: Convert iomap_releasepage to use " Matthew Wilcox (Oracle)
  2021-07-20  6:54   ` Christoph Hellwig
@ 2021-07-20 23:56   ` Darrick J. Wong
  1 sibling, 0 replies; 62+ messages in thread
From: Darrick J. Wong @ 2021-07-20 23:56 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:50PM +0100, Matthew Wilcox (Oracle) wrote:
> This is an address_space operation, so its argument must remain as a
> struct page, but we can use a folio internally.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

<rant>
/me curses at vger and fsdevel for not delivering this; if I have to
scrape lore to have reliable email, why don't we just use a webpage for
this? <grumble>
</rant>

The patch itself looks good though.
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  fs/iomap/buffered-io.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index 83eb5fdcbe05..715b25a1c1e6 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -460,15 +460,15 @@ iomap_releasepage(struct page *page, gfp_t gfp_mask)
>  {
>  	struct folio *folio = page_folio(page);
>  
> -	trace_iomap_releasepage(page->mapping->host, page_offset(page),
> -			PAGE_SIZE);
> +	trace_iomap_releasepage(folio->mapping->host, folio_pos(folio),
> +			folio_size(folio));
>  
>  	/*
>  	 * mm accommodates an old ext3 case where clean pages might not have had
>  	 * the dirty bit cleared. Thus, it can send actual dirty pages to
>  	 * ->releasepage() via shrink_active_list(), skip those here.
>  	 */
> -	if (PageDirty(page) || PageWriteback(page))
> +	if (folio_test_dirty(folio) || folio_test_writeback(folio))
>  		return 0;
>  	iomap_page_release(folio);
>  	return 1;
> -- 
> 2.30.2
> 


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 07/17] iomap: Convert iomap_invalidatepage to use a folio
  2021-07-19 18:39 ` [PATCH v15 07/17] iomap: Convert iomap_invalidatepage " Matthew Wilcox (Oracle)
  2021-07-20  6:55   ` Christoph Hellwig
@ 2021-07-20 23:57   ` Darrick J. Wong
  1 sibling, 0 replies; 62+ messages in thread
From: Darrick J. Wong @ 2021-07-20 23:57 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:51PM +0100, Matthew Wilcox (Oracle) wrote:
> This is an address_space operation, so its argument must remain as a
> struct page, but we can use a folio internally.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Looks good!
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  fs/iomap/buffered-io.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index 715b25a1c1e6..0d7b6ef4c5cc 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -480,15 +480,15 @@ iomap_invalidatepage(struct page *page, unsigned int offset, unsigned int len)
>  {
>  	struct folio *folio = page_folio(page);
>  
> -	trace_iomap_invalidatepage(page->mapping->host, offset, len);
> +	trace_iomap_invalidatepage(folio->mapping->host, offset, len);
>  
>  	/*
>  	 * If we are invalidating the entire page, clear the dirty state from it
>  	 * and release it to avoid unnecessary buildup of the LRU.
>  	 */
> -	if (offset == 0 && len == PAGE_SIZE) {
> -		WARN_ON_ONCE(PageWriteback(page));
> -		cancel_dirty_page(page);
> +	if (offset == 0 && len == folio_size(folio)) {
> +		WARN_ON_ONCE(folio_test_writeback(folio));
> +		folio_cancel_dirty(folio);
>  		iomap_page_release(folio);
>  	}
>  }
> -- 
> 2.30.2
> 


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 13/17] iomap: Convert iomap_write_begin and iomap_write_end to folios
  2021-07-19 18:39 ` [PATCH v15 13/17] iomap: Convert iomap_write_begin and iomap_write_end to folios Matthew Wilcox (Oracle)
  2021-07-20  7:15   ` Christoph Hellwig
@ 2021-07-20 23:59   ` Darrick J. Wong
  1 sibling, 0 replies; 62+ messages in thread
From: Darrick J. Wong @ 2021-07-20 23:59 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:57PM +0100, Matthew Wilcox (Oracle) wrote:
> These functions still only work in PAGE_SIZE chunks, but there are
> fewer conversions from head to tail pages as a result of this patch.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Woo, this looks like a straightforward conversion.
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  fs/iomap/buffered-io.c | 68 ++++++++++++++++++++++--------------------
>  1 file changed, 36 insertions(+), 32 deletions(-)
> 
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index dd05db36e135..4b02337009bc 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -543,9 +543,8 @@ static int iomap_read_folio_sync(loff_t block_start, struct folio *folio,
>  
>  static int
>  __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
> -		struct page *page, struct iomap *srcmap)
> +		struct folio *folio, struct iomap *srcmap)
>  {
> -	struct folio *folio = page_folio(page);
>  	struct iomap_page *iop = iomap_page_create(inode, folio);
>  	loff_t block_size = i_blocksize(inode);
>  	loff_t block_start = round_down(pos, block_size);
> @@ -585,12 +584,14 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
>  	return 0;
>  }
>  
> -static int
> -iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
> -		struct page **pagep, struct iomap *iomap, struct iomap *srcmap)
> +static int iomap_write_begin(struct inode *inode, loff_t pos, size_t len,
> +		unsigned flags, struct folio **foliop, struct iomap *iomap,
> +		struct iomap *srcmap)
>  {
>  	const struct iomap_page_ops *page_ops = iomap->page_ops;
> +	struct folio *folio;
>  	struct page *page;
> +	unsigned fgp = FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_STABLE | FGP_NOFS;
>  	int status = 0;
>  
>  	BUG_ON(pos + len > iomap->offset + iomap->length);
> @@ -606,30 +607,31 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
>  			return status;
>  	}
>  
> -	page = grab_cache_page_write_begin(inode->i_mapping, pos >> PAGE_SHIFT,
> -			AOP_FLAG_NOFS);
> -	if (!page) {
> +	folio = __filemap_get_folio(inode->i_mapping, pos >> PAGE_SHIFT, fgp,
> +			mapping_gfp_mask(inode->i_mapping));
> +	if (!folio) {
>  		status = -ENOMEM;
>  		goto out_no_page;
>  	}
>  
> +	page = folio_file_page(folio, pos >> PAGE_SHIFT);
>  	if (srcmap->type == IOMAP_INLINE)
>  		iomap_read_inline_data(inode, page, srcmap);
>  	else if (iomap->flags & IOMAP_F_BUFFER_HEAD)
>  		status = __block_write_begin_int(page, pos, len, NULL, srcmap);
>  	else
> -		status = __iomap_write_begin(inode, pos, len, flags, page,
> +		status = __iomap_write_begin(inode, pos, len, flags, folio,
>  				srcmap);
>  
>  	if (unlikely(status))
>  		goto out_unlock;
>  
> -	*pagep = page;
> +	*foliop = folio;
>  	return 0;
>  
>  out_unlock:
> -	unlock_page(page);
> -	put_page(page);
> +	folio_unlock(folio);
> +	folio_put(folio);
>  	iomap_write_failed(inode, pos, len);
>  
>  out_no_page:
> @@ -639,11 +641,10 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
>  }
>  
>  static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
> -		size_t copied, struct page *page)
> +		size_t copied, struct folio *folio)
>  {
> -	struct folio *folio = page_folio(page);
>  	struct iomap_page *iop = to_iomap_page(folio);
> -	flush_dcache_page(page);
> +	flush_dcache_folio(folio);
>  
>  	/*
>  	 * The blocks that were entirely written will now be uptodate, so we
> @@ -656,10 +657,10 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
>  	 * uptodate page as a zero-length write, and force the caller to redo
>  	 * the whole thing.
>  	 */
> -	if (unlikely(copied < len && !PageUptodate(page)))
> +	if (unlikely(copied < len && !folio_test_uptodate(folio)))
>  		return 0;
>  	iomap_set_range_uptodate(folio, iop, offset_in_folio(folio, pos), len);
> -	__set_page_dirty_nobuffers(page);
> +	filemap_dirty_folio(inode->i_mapping, folio);
>  	return copied;
>  }
>  
> @@ -682,9 +683,10 @@ static size_t iomap_write_end_inline(struct inode *inode, struct page *page,
>  
>  /* Returns the number of bytes copied.  May be 0.  Cannot be an errno. */
>  static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len,
> -		size_t copied, struct page *page, struct iomap *iomap,
> +		size_t copied, struct folio *folio, struct iomap *iomap,
>  		struct iomap *srcmap)
>  {
> +	struct page *page = folio_file_page(folio, pos >> PAGE_SHIFT);
>  	const struct iomap_page_ops *page_ops = iomap->page_ops;
>  	loff_t old_size = inode->i_size;
>  	size_t ret;
> @@ -695,7 +697,7 @@ static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len,
>  		ret = block_write_end(NULL, inode->i_mapping, pos, len, copied,
>  				page, NULL);
>  	} else {
> -		ret = __iomap_write_end(inode, pos, len, copied, page);
> +		ret = __iomap_write_end(inode, pos, len, copied, folio);
>  	}
>  
>  	/*
> @@ -707,13 +709,13 @@ static size_t iomap_write_end(struct inode *inode, loff_t pos, size_t len,
>  		i_size_write(inode, pos + ret);
>  		iomap->flags |= IOMAP_F_SIZE_CHANGED;
>  	}
> -	unlock_page(page);
> +	folio_unlock(folio);
>  
>  	if (old_size < pos)
>  		pagecache_isize_extended(inode, old_size, pos);
>  	if (page_ops && page_ops->page_done)
>  		page_ops->page_done(inode, pos, ret, page, iomap);
> -	put_page(page);
> +	folio_put(folio);
>  
>  	if (ret < len)
>  		iomap_write_failed(inode, pos, len);
> @@ -729,6 +731,7 @@ iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
>  	ssize_t written = 0;
>  
>  	do {
> +		struct folio *folio;
>  		struct page *page;
>  		unsigned long offset;	/* Offset into pagecache page */
>  		unsigned long bytes;	/* Bytes to write to page */
> @@ -752,18 +755,19 @@ iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
>  			break;
>  		}
>  
> -		status = iomap_write_begin(inode, pos, bytes, 0, &page, iomap,
> +		status = iomap_write_begin(inode, pos, bytes, 0, &folio, iomap,
>  				srcmap);
>  		if (unlikely(status))
>  			break;
>  
> +		page = folio_file_page(folio, pos >> PAGE_SHIFT);
>  		if (mapping_writably_mapped(inode->i_mapping))
>  			flush_dcache_page(page);
>  
>  		copied = copy_page_from_iter_atomic(page, offset, bytes, i);
>  
> -		status = iomap_write_end(inode, pos, bytes, copied, page, iomap,
> -				srcmap);
> +		status = iomap_write_end(inode, pos, bytes, copied, folio,
> +				iomap, srcmap);
>  
>  		if (unlikely(copied != status))
>  			iov_iter_revert(i, copied - status);
> @@ -827,14 +831,14 @@ iomap_unshare_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
>  	do {
>  		unsigned long offset = offset_in_page(pos);
>  		unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length);
> -		struct page *page;
> +		struct folio *folio;
>  
>  		status = iomap_write_begin(inode, pos, bytes,
> -				IOMAP_WRITE_F_UNSHARE, &page, iomap, srcmap);
> +				IOMAP_WRITE_F_UNSHARE, &folio, iomap, srcmap);
>  		if (unlikely(status))
>  			return status;
>  
> -		status = iomap_write_end(inode, pos, bytes, bytes, page, iomap,
> +		status = iomap_write_end(inode, pos, bytes, bytes, folio, iomap,
>  				srcmap);
>  		if (WARN_ON_ONCE(status == 0))
>  			return -EIO;
> @@ -873,19 +877,19 @@ EXPORT_SYMBOL_GPL(iomap_file_unshare);
>  static s64 iomap_zero(struct inode *inode, loff_t pos, u64 length,
>  		struct iomap *iomap, struct iomap *srcmap)
>  {
> -	struct page *page;
> +	struct folio *folio;
>  	int status;
>  	unsigned offset = offset_in_page(pos);
>  	unsigned bytes = min_t(u64, PAGE_SIZE - offset, length);
>  
> -	status = iomap_write_begin(inode, pos, bytes, 0, &page, iomap, srcmap);
> +	status = iomap_write_begin(inode, pos, bytes, 0, &folio, iomap, srcmap);
>  	if (status)
>  		return status;
>  
> -	zero_user(page, offset, bytes);
> -	mark_page_accessed(page);
> +	zero_user(folio_file_page(folio, pos >> PAGE_SHIFT), offset, bytes);
> +	folio_mark_accessed(folio);
>  
> -	return iomap_write_end(inode, pos, bytes, bytes, page, iomap, srcmap);
> +	return iomap_write_end(inode, pos, bytes, bytes, folio, iomap, srcmap);
>  }
>  
>  static loff_t iomap_zero_range_actor(struct inode *inode, loff_t pos,
> -- 
> 2.30.2
> 


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios
  2021-07-19 18:40 ` [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios Matthew Wilcox (Oracle)
  2021-07-20  7:21   ` Christoph Hellwig
  2021-07-20 13:30   ` kernel test robot
@ 2021-07-21  0:02   ` Darrick J. Wong
  2 siblings, 0 replies; 62+ messages in thread
From: Darrick J. Wong @ 2021-07-21  0:02 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:40:01PM +0100, Matthew Wilcox (Oracle) wrote:
> The arguments are still pages for now, but we can use folios internally
> and cut out a lot of calls to compound_head().
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Didn't I RVb this last time? ;)
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  fs/iomap/buffered-io.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index 60d3b7af61d1..cf56b19fb101 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -492,19 +492,21 @@ int
>  iomap_migrate_page(struct address_space *mapping, struct page *newpage,
>  		struct page *page, enum migrate_mode mode)
>  {
> +	struct folio *folio = page_folio(page);
> +	struct folio *newfolio = page_folio(newpage);
>  	int ret;
>  
> -	ret = migrate_page_move_mapping(mapping, newpage, page, 0);
> +	ret = folio_migrate_mapping(mapping, newfolio, folio, 0);
>  	if (ret != MIGRATEPAGE_SUCCESS)
>  		return ret;
>  
> -	if (page_has_private(page))
> -		attach_page_private(newpage, detach_page_private(page));
> +	if (folio_test_private(folio))
> +		folio_attach_private(newfolio, folio_detach_private(folio));
>  
>  	if (mode != MIGRATE_SYNC_NO_COPY)
> -		migrate_page_copy(newpage, page);
> +		folio_migrate_copy(newfolio, folio);
>  	else
> -		migrate_page_states(newpage, page);
> +		folio_migrate_flags(newfolio, folio);
>  	return MIGRATEPAGE_SUCCESS;
>  }
>  EXPORT_SYMBOL_GPL(iomap_migrate_page);
> -- 
> 2.30.2
> 


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend to take a folio
  2021-07-19 18:40 ` [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend " Matthew Wilcox (Oracle)
  2021-07-20  7:20   ` Christoph Hellwig
@ 2021-07-21  0:12   ` Darrick J. Wong
  2021-07-21  4:27     ` Christoph Hellwig
  1 sibling, 1 reply; 62+ messages in thread
From: Darrick J. Wong @ 2021-07-21  0:12 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle), Christoph Hellwig
  Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:40:00PM +0100, Matthew Wilcox (Oracle) wrote:
> We still iterate one block at a time, but now we call compound_head()
> less often.  Rename file_offset to pos to fit the rest of the file.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Everything in this patch looks ok to me, though I gather there will be
further changes to bio_add_folio, so I'll leave this off for now.

I /am/ beginning to wonder, though -- seeing as Christoph and Matthew
both have very large patchsets changing things in fs/iomap/, how would
you like those landed?  Christoph's iterator refactoring looks like it
could be ready to go for 5.15.  Matthew's folio series looks like a
mostly straightforward conversion for iomap, except that it has 91
patches as a hard dependency.

Since most of the iomap changes for 5.15 aren't directly related to
folios, I think I prefer iomap-for-next to be based directly off -rcX
like usual, though I don't know where that leaves the iomap folio
conversion.  I suppose one could add them to a branch that itself is a
result of the folio and iomap branches, or leave them off for 5.16?

Other ideas?

--D


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend to take a folio
  2021-07-21  0:12   ` Darrick J. Wong
@ 2021-07-21  4:27     ` Christoph Hellwig
  2021-07-21  4:31       ` Matthew Wilcox
  0 siblings, 1 reply; 62+ messages in thread
From: Christoph Hellwig @ 2021-07-21  4:27 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: Matthew Wilcox (Oracle),
	Christoph Hellwig, linux-fsdevel, linux-mm, linux-block

On Tue, Jul 20, 2021 at 05:12:19PM -0700, Darrick J. Wong wrote:
> I /am/ beginning to wonder, though -- seeing as Christoph and Matthew
> both have very large patchsets changing things in fs/iomap/, how would
> you like those landed?  Christoph's iterator refactoring looks like it
> could be ready to go for 5.15.  Matthew's folio series looks like a
> mostly straightforward conversion for iomap, except that it has 91
> patches as a hard dependency.
> 
> Since most of the iomap changes for 5.15 aren't directly related to
> folios, I think I prefer iomap-for-next to be based directly off -rcX
> like usual, though I don't know where that leaves the iomap folio
> conversion.  I suppose one could add them to a branch that itself is a
> result of the folio and iomap branches, or leave them off for 5.16?

Maybe willy has a different opinion, but I thought the plan was to have
the based folio enablement in 5.15, and then do things like the iomap
conversion in the the next merge window.  If we have everything ready
this window we could still add a branch that builds on top of both
the iomap and folio trees, though.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend to take a folio
  2021-07-21  4:27     ` Christoph Hellwig
@ 2021-07-21  4:31       ` Matthew Wilcox
  2021-07-21 15:28         ` Darrick J. Wong
  0 siblings, 1 reply; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-21  4:31 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Darrick J. Wong, linux-fsdevel, linux-mm, linux-block

On Wed, Jul 21, 2021 at 05:27:49AM +0100, Christoph Hellwig wrote:
> On Tue, Jul 20, 2021 at 05:12:19PM -0700, Darrick J. Wong wrote:
> > I /am/ beginning to wonder, though -- seeing as Christoph and Matthew
> > both have very large patchsets changing things in fs/iomap/, how would
> > you like those landed?  Christoph's iterator refactoring looks like it
> > could be ready to go for 5.15.  Matthew's folio series looks like a
> > mostly straightforward conversion for iomap, except that it has 91
> > patches as a hard dependency.
> > 
> > Since most of the iomap changes for 5.15 aren't directly related to
> > folios, I think I prefer iomap-for-next to be based directly off -rcX
> > like usual, though I don't know where that leaves the iomap folio
> > conversion.  I suppose one could add them to a branch that itself is a
> > result of the folio and iomap branches, or leave them off for 5.16?
> 
> Maybe willy has a different opinion, but I thought the plan was to have
> the based folio enablement in 5.15, and then do things like the iomap
> conversion in the the next merge window.  If we have everything ready
> this window we could still add a branch that builds on top of both
> the iomap and folio trees, though.

Yes, my plan was to have the iomap conversion and the second half of the
page cache work hit 5.16.  If we're ready earlier, that's great!  Both
you and I want to see both the folio work and the iomap_iter work
get merged, so I don't anticipate any lack of will to get the work done.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend to take a folio
  2021-07-21  4:31       ` Matthew Wilcox
@ 2021-07-21 15:28         ` Darrick J. Wong
  0 siblings, 0 replies; 62+ messages in thread
From: Darrick J. Wong @ 2021-07-21 15:28 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Christoph Hellwig, linux-fsdevel, linux-mm, linux-block

On Wed, Jul 21, 2021 at 05:31:16AM +0100, Matthew Wilcox wrote:
> On Wed, Jul 21, 2021 at 05:27:49AM +0100, Christoph Hellwig wrote:
> > On Tue, Jul 20, 2021 at 05:12:19PM -0700, Darrick J. Wong wrote:
> > > I /am/ beginning to wonder, though -- seeing as Christoph and Matthew
> > > both have very large patchsets changing things in fs/iomap/, how would
> > > you like those landed?  Christoph's iterator refactoring looks like it
> > > could be ready to go for 5.15.  Matthew's folio series looks like a
> > > mostly straightforward conversion for iomap, except that it has 91
> > > patches as a hard dependency.
> > > 
> > > Since most of the iomap changes for 5.15 aren't directly related to
> > > folios, I think I prefer iomap-for-next to be based directly off -rcX
> > > like usual, though I don't know where that leaves the iomap folio
> > > conversion.  I suppose one could add them to a branch that itself is a
> > > result of the folio and iomap branches, or leave them off for 5.16?
> > 
> > Maybe willy has a different opinion, but I thought the plan was to have
> > the based folio enablement in 5.15, and then do things like the iomap
> > conversion in the the next merge window.  If we have everything ready
> > this window we could still add a branch that builds on top of both
> > the iomap and folio trees, though.
> 
> Yes, my plan was to have the iomap conversion and the second half of the
> page cache work hit 5.16.  If we're ready earlier, that's great!  Both
> you and I want to see both the folio work and the iomap_iter work
> get merged, so I don't anticipate any lack of will to get the work done.

Ok, good.  I'll await a non-RFC version of the iterator rework for 5.15,
and folio conversions for 5.16.

--D


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 01/17] block: Add bio_add_folio()
  2021-07-20  6:42   ` Christoph Hellwig
  2021-07-20 11:16     ` Matthew Wilcox
@ 2021-07-22 16:27     ` Matthew Wilcox
  1 sibling, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-22 16:27 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-fsdevel, linux-mm, linux-block

On Tue, Jul 20, 2021 at 07:42:00AM +0100, Christoph Hellwig wrote:
> On Mon, Jul 19, 2021 at 07:39:45PM +0100, Matthew Wilcox (Oracle) wrote:
> > +/**
> > + * bio_add_folio - Attempt to add part of a folio to a bio.
> > + * @bio: Bio to add to.
> > + * @folio: Folio to add.
> > + * @len: How many bytes from the folio to add.
> > + * @off: First byte in this folio to add.
> > + *
> > + * Always uses the head page of the folio in the bio.  If a submitter only
> > + * uses bio_add_folio(), it can count on never seeing tail pages in the
> > + * completion routine.  BIOs do not support folios that are 4GiB or larger.
> > + *
> > + * Return: The number of bytes from this folio added to the bio.
> > + */
> > +size_t bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
> > +		size_t off)
> > +{
> > +	if (len > UINT_MAX || off > UINT_MAX)
> > +		return 0;
> > +	return bio_add_page(bio, &folio->page, len, off);
> > +}
> 
> I'd use the opportunity to switch to a true/false return instead of
> the length.  This has been on my todo list for bio_add_page for a while,
> so it might make sense to start out the new API the right way.

Looking at it with fresh eyes, I decided to rewrite the docs too.
ie this:

 /**
  * bio_add_folio - Attempt to add part of a folio to a bio.
- * @bio: Bio to add to.
+ * @bio: BIO to add to.
  * @folio: Folio to add.
  * @len: How many bytes from the folio to add.
  * @off: First byte in this folio to add.
  *
- * Always uses the head page of the folio in the bio.  If a submitter only
- * uses bio_add_folio(), it can count on never seeing tail pages in the
- * completion routine.  BIOs do not support folios that are 4GiB or larger.
+ * Filesystems that use folios can call this function instead of calling
+ * bio_add_page() for each page in the folio.  If @off is bigger than
+ * PAGE_SIZE, this function can create a bio_vec that starts in a page
+ * after the bv_page.  BIOs do not support folios that are 4GiB or larger.
  *
- * Return: The number of bytes from this folio added to the bio.
+ * Return: Whether the addition was successful.
  */
-size_t bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
+bool bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
                size_t off)
 {
        if (len > UINT_MAX || off > UINT_MAX)
                return 0;
-       return bio_add_page(bio, &folio->page, len, off);
+       return bio_add_page(bio, &folio->page, len, off) > 0;
 }

(i decided to go with > 0 so it's impervious to when you change
bio_add_page())


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 02/17] block: Add bio_for_each_folio_all()
  2021-07-20  6:48   ` Christoph Hellwig
@ 2021-07-23  2:40     ` Matthew Wilcox
  0 siblings, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-23  2:40 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-fsdevel, linux-mm, linux-block

On Tue, Jul 20, 2021 at 08:48:07AM +0200, Christoph Hellwig wrote:
> On Mon, Jul 19, 2021 at 07:39:46PM +0100, Matthew Wilcox (Oracle) wrote:
> >  #define bio_for_each_bvec_all(bvl, bio, i)		\
> >  	for (i = 0, bvl = bio_first_bvec_all(bio);	\
> > -	     i < (bio)->bi_vcnt; i++, bvl++)		\
> > +	     i < (bio)->bi_vcnt; i++, bvl++)
> 
> Pleae split out this unrelated fixup.
> 
> > +static inline
> > +void bio_first_folio(struct folio_iter *fi, struct bio *bio, int i)
> 
> Please fix the strange formatting.

static inline void bio_first_folio(struct folio_iter *fi, struct bio *bio,
		int i)

> > +{
> > +	struct bio_vec *bvec = bio_first_bvec_all(bio) + i;
> > +
> > +	fi->folio = page_folio(bvec->bv_page);
> > +	fi->offset = bvec->bv_offset +
> > +			PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
> 
> Can we have a little helper for the offset in folio calculation, like:
> 
> static inline size_t offset_of_page_in_folio(struct page *page)
> {
> 	return (bvec->bv_page - &page_folio(page)->page) * PAGE;
> }
> 
> as that makes the callers a lot easier to read.

I've spent most of today thinking about this one.  I actually don't
want to make this easy to read.  This is code that, in an ideal world,
would not exist.  A bio_vec should not contain a struct page; it should
probably be:

struct bio_vec {
	phys_addr_t bv_start;
	unsigned int bv_len;
};

and then the helper to get from a bio_vec to a folio_iter looks like:

	fi->folio = pfn_folio(bvec->bv_start >> PAGE_SHIFT);
	fi->offset = offset_in_folio(fi->folio, bvec->bv_start);

If instead we decide to keep bvecs the way they are, we can at
least turn the bv_page into bv_folio, and then we won't need this
code either.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 01/17] block: Add bio_add_folio()
  2021-07-19 18:39 ` [PATCH v15 01/17] block: Add bio_add_folio() Matthew Wilcox (Oracle)
  2021-07-20  1:28   ` Darrick J. Wong
  2021-07-20  6:42   ` Christoph Hellwig
@ 2021-07-30  8:25   ` Ming Lei
  2021-07-30 11:30     ` Matthew Wilcox
  2 siblings, 1 reply; 62+ messages in thread
From: Ming Lei @ 2021-07-30  8:25 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel, linux-mm, linux-block

On Mon, Jul 19, 2021 at 07:39:45PM +0100, Matthew Wilcox (Oracle) wrote:
> This is a thin wrapper around bio_add_page().  The main advantage here
> is the documentation that the submitter can expect to see folios in the
> completion handler, and that stupidly large folios are not supported.
> It's not currently possible to allocate stupidly large folios, but if
> it ever becomes possible, this function will fail gracefully instead of
> doing I/O to the wrong bytes.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> ---
>  block/bio.c         | 21 +++++++++++++++++++++
>  include/linux/bio.h |  3 ++-
>  2 files changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/block/bio.c b/block/bio.c
> index 1fab762e079b..c64e35548fb2 100644
> --- a/block/bio.c
> +++ b/block/bio.c
> @@ -933,6 +933,27 @@ int bio_add_page(struct bio *bio, struct page *page,
>  }
>  EXPORT_SYMBOL(bio_add_page);
>  
> +/**
> + * bio_add_folio - Attempt to add part of a folio to a bio.
> + * @bio: Bio to add to.
> + * @folio: Folio to add.
> + * @len: How many bytes from the folio to add.
> + * @off: First byte in this folio to add.
> + *
> + * Always uses the head page of the folio in the bio.  If a submitter only
> + * uses bio_add_folio(), it can count on never seeing tail pages in the
> + * completion routine.  BIOs do not support folios that are 4GiB or larger.
> + *
> + * Return: The number of bytes from this folio added to the bio.
> + */
> +size_t bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
> +		size_t off)
> +{
> +	if (len > UINT_MAX || off > UINT_MAX)
> +		return 0;

The added page shouldn't cross 4G boundary, so just wondering why not
check 'if (len > UINT_MAX - off)'?


Thanks, 
Ming



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v15 01/17] block: Add bio_add_folio()
  2021-07-30  8:25   ` Ming Lei
@ 2021-07-30 11:30     ` Matthew Wilcox
  0 siblings, 0 replies; 62+ messages in thread
From: Matthew Wilcox @ 2021-07-30 11:30 UTC (permalink / raw)
  To: Ming Lei; +Cc: linux-fsdevel, linux-mm, linux-block

On Fri, Jul 30, 2021 at 04:25:17PM +0800, Ming Lei wrote:
> > +size_t bio_add_folio(struct bio *bio, struct folio *folio, size_t len,
> > +		size_t off)
> > +{
> > +	if (len > UINT_MAX || off > UINT_MAX)
> > +		return 0;
> 
> The added page shouldn't cross 4G boundary, so just wondering why not
> check 'if (len > UINT_MAX - off)'?

That check is going to be vulnerable to wrapping, eg
	off = 2^32, len = 512

It would be less vulnerable to wrapping if we cast both sides to
signed long.  But at that point, we're firmly into obscuring the
intent of the check.


^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2021-07-30 11:32 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-19 18:39 [PATCH v15 00/17] Folio support in block + iomap layers Matthew Wilcox (Oracle)
2021-07-19 18:39 ` [PATCH v15 01/17] block: Add bio_add_folio() Matthew Wilcox (Oracle)
2021-07-20  1:28   ` Darrick J. Wong
2021-07-20  6:42   ` Christoph Hellwig
2021-07-20 11:16     ` Matthew Wilcox
2021-07-22 16:27     ` Matthew Wilcox
2021-07-30  8:25   ` Ming Lei
2021-07-30 11:30     ` Matthew Wilcox
2021-07-19 18:39 ` [PATCH v15 02/17] block: Add bio_for_each_folio_all() Matthew Wilcox (Oracle)
2021-07-20  1:29   ` Darrick J. Wong
2021-07-20  1:59     ` Matthew Wilcox
2021-07-20  6:48   ` Christoph Hellwig
2021-07-23  2:40     ` Matthew Wilcox
2021-07-20 12:05   ` kernel test robot
2021-07-20 12:05   ` kernel test robot
2021-07-20 12:26   ` kernel test robot
2021-07-19 18:39 ` [PATCH v15 03/17] iomap: Convert to_iomap_page to take a folio Matthew Wilcox (Oracle)
2021-07-20  6:49   ` Christoph Hellwig
2021-07-19 18:39 ` [PATCH v15 04/17] iomap: Convert iomap_page_create " Matthew Wilcox (Oracle)
2021-07-20  6:50   ` Christoph Hellwig
2021-07-19 18:39 ` [PATCH v15 05/17] iomap: Convert iomap_page_release " Matthew Wilcox (Oracle)
2021-07-20  6:52   ` Christoph Hellwig
2021-07-20 11:29     ` Matthew Wilcox
2021-07-20 11:40       ` Christoph Hellwig
2021-07-19 18:39 ` [PATCH v15 06/17] iomap: Convert iomap_releasepage to use " Matthew Wilcox (Oracle)
2021-07-20  6:54   ` Christoph Hellwig
2021-07-20 23:56   ` Darrick J. Wong
2021-07-19 18:39 ` [PATCH v15 07/17] iomap: Convert iomap_invalidatepage " Matthew Wilcox (Oracle)
2021-07-20  6:55   ` Christoph Hellwig
2021-07-20 23:57   ` Darrick J. Wong
2021-07-19 18:39 ` [PATCH v15 08/17] iomap: Pass the iomap_page into iomap_set_range_uptodate Matthew Wilcox (Oracle)
2021-07-20  6:57   ` Christoph Hellwig
2021-07-20 11:36     ` Matthew Wilcox
2021-07-19 18:39 ` [PATCH v15 09/17] iomap: Use folio offsets instead of page offsets Matthew Wilcox (Oracle)
2021-07-20  6:59   ` Christoph Hellwig
2021-07-20 11:42     ` Matthew Wilcox
2021-07-19 18:39 ` [PATCH v15 10/17] iomap: Convert bio completions to use folios Matthew Wilcox (Oracle)
2021-07-20  7:08   ` Christoph Hellwig
2021-07-19 18:39 ` [PATCH v15 11/17] iomap: Convert readahead and readpage to use a folio Matthew Wilcox (Oracle)
2021-07-20  7:09   ` Christoph Hellwig
2021-07-19 18:39 ` [PATCH v15 12/17] iomap: Convert iomap_page_mkwrite " Matthew Wilcox (Oracle)
2021-07-20  7:13   ` Christoph Hellwig
2021-07-19 18:39 ` [PATCH v15 13/17] iomap: Convert iomap_write_begin and iomap_write_end to folios Matthew Wilcox (Oracle)
2021-07-20  7:15   ` Christoph Hellwig
2021-07-20 23:59   ` Darrick J. Wong
2021-07-19 18:39 ` [PATCH v15 14/17] iomap: Convert iomap_read_inline_data to take a folio Matthew Wilcox (Oracle)
2021-07-20  7:16   ` Christoph Hellwig
2021-07-19 18:39 ` [PATCH v15 15/17] iomap: Convert iomap_write_end_inline " Matthew Wilcox (Oracle)
2021-07-20  7:17   ` Christoph Hellwig
2021-07-19 18:40 ` [PATCH v15 16/17] iomap: Convert iomap_add_to_ioend " Matthew Wilcox (Oracle)
2021-07-20  7:20   ` Christoph Hellwig
2021-07-20 11:45     ` Matthew Wilcox
2021-07-21  0:12   ` Darrick J. Wong
2021-07-21  4:27     ` Christoph Hellwig
2021-07-21  4:31       ` Matthew Wilcox
2021-07-21 15:28         ` Darrick J. Wong
2021-07-19 18:40 ` [PATCH v15 17/17] iomap: Convert iomap_migrate_page to use folios Matthew Wilcox (Oracle)
2021-07-20  7:21   ` Christoph Hellwig
2021-07-20 13:30   ` kernel test robot
2021-07-21  0:02   ` Darrick J. Wong
2021-07-20  8:44 ` [PATCH v15 00/17] Folio support in block + iomap layers Christoph Hellwig
2021-07-20 11:08   ` Matthew Wilcox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).