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: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Acked-by: Jeff Layton <jlayton@kernel.org> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Reviewed-by: William Kucharski <william.kucharski@oracle.com> Reviewed-by: David Howells <dhowells@redhat.com> Acked-by: Mike Rapoport <rppt@linux.ibm.com> Acked-by: Vlastimil Babka <vbabka@suse.cz>
This commit is contained in:
parent
2f52578f9c
commit
4e1364286d
@ -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
|
||||
|
29
mm/filemap.c
29
mm/filemap.c
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user