Skip to content

Commit 0410cd8

Browse files
Matthew Wilcox (Oracle)akpm00
authored andcommitted
mm: add folio_xor_flags_has_waiters()
Optimise folio_end_read() by setting the uptodate bit at the same time we clear the unlock bit. This saves at least one memory barrier and one write-after-write hazard. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Cc: Albert Ou <[email protected]> Cc: Alexander Gordeev <[email protected]> Cc: Andreas Dilger <[email protected]> Cc: Christian Borntraeger <[email protected]> Cc: Christophe Leroy <[email protected]> Cc: Geert Uytterhoeven <[email protected]> Cc: Heiko Carstens <[email protected]> Cc: Ivan Kokshaysky <[email protected]> Cc: Matt Turner <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Nicholas Piggin <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Richard Henderson <[email protected]> Cc: Sven Schnelle <[email protected]> Cc: "Theodore Ts'o" <[email protected]> Cc: Thomas Bogendoerfer <[email protected]> Cc: Vasily Gorbik <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent f12fb73 commit 0410cd8

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

include/linux/page-flags.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,25 @@ TESTPAGEFLAG_FALSE(Ksm, ksm)
692692

693693
u64 stable_page_flags(struct page *page);
694694

695+
/**
696+
* folio_xor_flags_has_waiters - Change some folio flags.
697+
* @folio: The folio.
698+
* @mask: Bits set in this word will be changed.
699+
*
700+
* This must only be used for flags which are changed with the folio
701+
* lock held. For example, it is unsafe to use for PG_dirty as that
702+
* can be set without the folio lock held. It can also only be used
703+
* on flags which are in the range 0-6 as some of the implementations
704+
* only affect those bits.
705+
*
706+
* Return: Whether there are tasks waiting on the folio.
707+
*/
708+
static inline bool folio_xor_flags_has_waiters(struct folio *folio,
709+
unsigned long mask)
710+
{
711+
return xor_unlock_is_negative_byte(mask, folio_flags(folio, 0));
712+
}
713+
695714
/**
696715
* folio_test_uptodate - Is this folio up to date?
697716
* @folio: The folio.

mm/filemap.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,7 @@ void folio_unlock(struct folio *folio)
14971497
BUILD_BUG_ON(PG_waiters != 7);
14981498
BUILD_BUG_ON(PG_locked > 7);
14991499
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
1500-
if (xor_unlock_is_negative_byte(1 << PG_locked, folio_flags(folio, 0)))
1500+
if (folio_xor_flags_has_waiters(folio, 1 << PG_locked))
15011501
folio_wake_bit(folio, PG_locked);
15021502
}
15031503
EXPORT_SYMBOL(folio_unlock);
@@ -1518,9 +1518,17 @@ EXPORT_SYMBOL(folio_unlock);
15181518
*/
15191519
void folio_end_read(struct folio *folio, bool success)
15201520
{
1521+
unsigned long mask = 1 << PG_locked;
1522+
1523+
/* Must be in bottom byte for x86 to work */
1524+
BUILD_BUG_ON(PG_uptodate > 7);
1525+
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
1526+
VM_BUG_ON_FOLIO(folio_test_uptodate(folio), folio);
1527+
15211528
if (likely(success))
1522-
folio_mark_uptodate(folio);
1523-
folio_unlock(folio);
1529+
mask |= 1 << PG_uptodate;
1530+
if (folio_xor_flags_has_waiters(folio, mask))
1531+
folio_wake_bit(folio, PG_locked);
15241532
}
15251533
EXPORT_SYMBOL(folio_end_read);
15261534

0 commit comments

Comments
 (0)