Commit 4268b480 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle)
Browse files

mm/filemap: Add folio_end_writeback()



Add an end_page_writeback() wrapper function for users that are not yet
converted to folios.

folio_end_writeback() is less than half the size of end_page_writeback()
at just 105 bytes compared to 228 bytes, due to removing all the
compound_head() calls.  The 30 byte wrapper function makes this a net
saving of 93 bytes.

Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarJeff Layton <jlayton@kernel.org>
Acked-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Reviewed-by: default avatarWilliam Kucharski <william.kucharski@oracle.com>
Reviewed-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarMike Rapoport <rppt@linux.ibm.com>
parent 575ced1c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -767,7 +767,8 @@ static inline int wait_on_page_locked_killable(struct page *page)
int put_and_wait_on_page_locked(struct page *page, int state);
void wait_on_page_writeback(struct page *page);
int wait_on_page_writeback_killable(struct page *page);
extern void end_page_writeback(struct page *page);
void end_page_writeback(struct page *page);
void folio_end_writeback(struct folio *folio);
void wait_for_stable_page(struct page *page);

void __set_page_dirty(struct page *, struct address_space *, int warn);
+21 −22
Original line number Diff line number Diff line
@@ -1230,11 +1230,11 @@ static void wake_up_page_bit(struct page *page, int bit_nr)
	spin_unlock_irqrestore(&q->lock, flags);
}

static void wake_up_page(struct page *page, int bit)
static void folio_wake(struct folio *folio, int bit)
{
	if (!PageWaiters(page))
	if (!folio_test_waiters(folio))
		return;
	wake_up_page_bit(page, bit);
	wake_up_page_bit(&folio->page, bit);
}

/*
@@ -1571,39 +1571,38 @@ int wait_on_page_private_2_killable(struct page *page)
EXPORT_SYMBOL(wait_on_page_private_2_killable);

/**
 * end_page_writeback - end writeback against a page
 * @page: the page
 * folio_end_writeback - End writeback against a folio.
 * @folio: The folio.
 */
void end_page_writeback(struct page *page)
void folio_end_writeback(struct folio *folio)
{
	/*
	 * TestClearPageReclaim could be used here but it is an atomic
	 * operation and overkill in this particular case. Failing to
	 * shuffle a page marked for immediate reclaim is too mild to
	 * justify taking an atomic operation penalty at the end of
	 * ever page writeback.
	 * folio_test_clear_reclaim() could be used here but it is an
	 * atomic operation and overkill in this particular case. Failing
	 * to shuffle a folio marked for immediate reclaim is too mild
	 * a gain to justify taking an atomic operation penalty at the
	 * end of every folio writeback.
	 */
	if (PageReclaim(page)) {
		struct folio *folio = page_folio(page);
		ClearPageReclaim(page);
	if (folio_test_reclaim(folio)) {
		folio_clear_reclaim(folio);
		folio_rotate_reclaimable(folio);
	}

	/*
	 * Writeback does not hold a page reference of its own, relying
	 * Writeback does not hold a folio reference of its own, relying
	 * on truncation to wait for the clearing of PG_writeback.
	 * But here we must make sure that the page is not freed and
	 * reused before the wake_up_page().
	 * But here we must make sure that the folio is not freed and
	 * reused before the folio_wake().
	 */
	get_page(page);
	if (!test_clear_page_writeback(page))
	folio_get(folio);
	if (!test_clear_page_writeback(&folio->page))
		BUG();

	smp_mb__after_atomic();
	wake_up_page(page, PG_writeback);
	put_page(page);
	folio_wake(folio, PG_writeback);
	folio_put(folio);
}
EXPORT_SYMBOL(end_page_writeback);
EXPORT_SYMBOL(folio_end_writeback);

/*
 * After completing I/O on a page, call this routine to update the page
+6 −0
Original line number Diff line number Diff line
@@ -17,3 +17,9 @@ void unlock_page(struct page *page)
	return folio_unlock(page_folio(page));
}
EXPORT_SYMBOL(unlock_page);

void end_page_writeback(struct page *page)
{
	return folio_end_writeback(page_folio(page));
}
EXPORT_SYMBOL(end_page_writeback);