diff mbox series

[24/26] jbd2: Convert release_buffer_page() to use a folio

Message ID 20220508203247.668791-25-willy@infradead.org (mailing list archive)
State New, archived
Headers show
Series Convert aops->releasepage to aops->release_folio | expand

Commit Message

Matthew Wilcox May 8, 2022, 8:32 p.m. UTC
Saves a few calls to compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/jbd2/commit.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

Comments

Theodore Ts'o May 9, 2022, 1:23 p.m. UTC | #1
On Sun, May 08, 2022 at 09:32:45PM +0100, Matthew Wilcox (Oracle) wrote:
> Saves a few calls to compound_head().
>
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Acked-by: Theodore Ts'o <tytso@mit.edu>

... although I have one question:

> -	get_page(page);
> +	folio_get(folio);
>  	__brelse(bh);
> -	try_to_free_buffers(page);
> -	unlock_page(page);
> -	put_page(page);
> +	try_to_free_buffers(&folio->page);

The patches in this series seem to assume that the folio contains only
a single page.  Or at least, a *lot* more detailed auditing to make
sure the right thing would happen if a page happens to be a member of
a folio with more than a single page.

Should we be adding some kind of WARN_ON to check this particular
assumption?

					- Ted
Matthew Wilcox May 9, 2022, 1:48 p.m. UTC | #2
On Mon, May 09, 2022 at 09:23:10AM -0400, Theodore Ts'o wrote:
> On Sun, May 08, 2022 at 09:32:45PM +0100, Matthew Wilcox (Oracle) wrote:
> > Saves a few calls to compound_head().
> >
> > Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> 
> Acked-by: Theodore Ts'o <tytso@mit.edu>
> 
> ... although I have one question:
> 
> > -	get_page(page);
> > +	folio_get(folio);
> >  	__brelse(bh);
> > -	try_to_free_buffers(page);
> > -	unlock_page(page);
> > -	put_page(page);
> > +	try_to_free_buffers(&folio->page);
> 
> The patches in this series seem to assume that the folio contains only
> a single page.  Or at least, a *lot* more detailed auditing to make
> sure the right thing would happen if a page happens to be a member of
> a folio with more than a single page.
> 
> Should we be adding some kind of WARN_ON to check this particular
> assumption?

You're right, a lot of places assume a single-page folio.  Since
filesystems need to explicitly enable large folios (by calling
mapping_set_large_folios()), I haven't been adding assertions to
aops entry points.  I have been adding them to some common utility
functions in fs/buffer.c eg block_read_full_folio has:
        VM_BUG_ON_FOLIO(folio_test_large(folio), folio);

Other functions in fs/buffer.c look like they should handle large folios
OK, eg buffer_check_dirty_writeback() and block_dirty_folio() and then
others have existing assertions which are going to trigger if you try
to use them with large folios, like __block_write_begin_int() has
        BUG_ON(from > PAGE_SIZE);
and I haven't bothered to add assertions to either of those classes of
function.

JBD2 somewhat straddles a line between being considered "generic utility
functions" and "part of a filesystem".  I could go either way on adding
assertions to document that this hasn't been audited for large folios.
Although seeing '&folio->page' is always a sign that you should probably
audit the function.

By the end of this series, it seems to me that jbd2's
release_buffer_page() is actually large-folio-safe.  There's nothing
in it that relies on the size of the folio, it calls functions that
are large-folio-safe and the only actual use of 'page' in it is to
get bh->b_page ... which should probably be in a union with a new
->b_folio so we don't need to muck around with calling page_folio().
diff mbox series

Patch

diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index ac7f067b7bdd..2f37108da0ec 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -62,6 +62,7 @@  static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
  */
 static void release_buffer_page(struct buffer_head *bh)
 {
+	struct folio *folio;
 	struct page *page;
 
 	if (buffer_dirty(bh))
@@ -71,18 +72,19 @@  static void release_buffer_page(struct buffer_head *bh)
 	page = bh->b_page;
 	if (!page)
 		goto nope;
-	if (page->mapping)
+	folio = page_folio(page);
+	if (folio->mapping)
 		goto nope;
 
 	/* OK, it's a truncated page */
-	if (!trylock_page(page))
+	if (!folio_trylock(folio))
 		goto nope;
 
-	get_page(page);
+	folio_get(folio);
 	__brelse(bh);
-	try_to_free_buffers(page);
-	unlock_page(page);
-	put_page(page);
+	try_to_free_buffers(&folio->page);
+	folio_unlock(folio);
+	folio_put(folio);
 	return;
 
 nope: