Commit 4e136428 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle)
Browse files

mm/filemap: Add folio_unlock()



Convert unlock_page() to call folio_unlock().  By using a folio we
avoid a call to compound_head().  This shortens the function from 39
bytes to 25 and removes 4 instructions on x86-64.  Because we still
have unlock_page(), it's a net increase of 16 bytes of text for the
kernel as a whole, but any path that uses folio_unlock() will execute
4 fewer instructions.

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>
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>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
parent 2f52578f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -657,7 +657,8 @@ extern int __lock_page_killable(struct page *page);
extern int __lock_page_async(struct page *page, struct wait_page_queue *wait);
extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
				unsigned int flags);
extern void unlock_page(struct page *page);
void unlock_page(struct page *page);
void folio_unlock(struct folio *folio);

/*
 * Return true if the page was successfully locked
+12 −17
Original line number Diff line number Diff line
@@ -1490,29 +1490,24 @@ static inline bool clear_bit_unlock_is_negative_byte(long nr, volatile void *mem
#endif

/**
 * unlock_page - unlock a locked page
 * @page: the page
 * folio_unlock - Unlock a locked folio.
 * @folio: The folio.
 *
 * Unlocks the page and wakes up sleepers in wait_on_page_locked().
 * Also wakes sleepers in wait_on_page_writeback() because the wakeup
 * mechanism between PageLocked pages and PageWriteback pages is shared.
 * But that's OK - sleepers in wait_on_page_writeback() just go back to sleep.
 * Unlocks the folio and wakes up any thread sleeping on the page lock.
 *
 * Note that this depends on PG_waiters being the sign bit in the byte
 * that contains PG_locked - thus the BUILD_BUG_ON(). That allows us to
 * clear the PG_locked bit and test PG_waiters at the same time fairly
 * portably (architectures that do LL/SC can test any bit, while x86 can
 * test the sign bit).
 * Context: May be called from interrupt or process context.  May not be
 * called from NMI context.
 */
void unlock_page(struct page *page)
void folio_unlock(struct folio *folio)
{
	/* Bit 7 allows x86 to check the byte's sign bit */
	BUILD_BUG_ON(PG_waiters != 7);
	page = compound_head(page);
	VM_BUG_ON_PAGE(!PageLocked(page), page);
	if (clear_bit_unlock_is_negative_byte(PG_locked, &page->flags))
		wake_up_page_bit(page, PG_locked);
	BUILD_BUG_ON(PG_locked > 7);
	VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
	if (clear_bit_unlock_is_negative_byte(PG_locked, folio_flags(folio, 0)))
		wake_up_page_bit(&folio->page, PG_locked);
}
EXPORT_SYMBOL(unlock_page);
EXPORT_SYMBOL(folio_unlock);

/**
 * end_page_private_2 - Clear PG_private_2 and release any waiters
+6 −0
Original line number Diff line number Diff line
@@ -11,3 +11,9 @@ struct address_space *page_mapping(struct page *page)
	return folio_mapping(page_folio(page));
}
EXPORT_SYMBOL(page_mapping);

void unlock_page(struct page *page)
{
	return folio_unlock(page_folio(page));
}
EXPORT_SYMBOL(unlock_page);