History

futex: Calculate the futex key based on a tail page for file-based futexes

Mike Galbraith reported that the LTP test case futex_wake04 was broken by commit 65d8fc777f6d ("futex: Remove requirement for lock_page() in get_futex_key()"). This test case uses futexes backed by hugetlbfs pages and so there is an associated inode with a futex stored on such pages. The problem is that the key is being calculated based on the head page index of the hugetlbfs page and not the tail page. Prior to the optimisation, the page lock was used to stabilise mappings and pin the inode is file-backed which is overkill. If the page was a compound page, the head page was automatically looked up as part of the page lock operation but the tail page index was used to calculate the futex key. After the optimisation, the compound head is looked up early and the page lock is only relied upon to identify truncated pages, special pages or a shmem page moving to swapcache. The head page is looked up because without the page lock, special care has to be taken to pin the inode correctly. However, the tail page is still required to calculate the futex key so this patch records the tail page. On vanilla 4.6, the output of the test case is; futex_wake04 0 TINFO : Hugepagesize 2097152 futex_wake04 1 TFAIL : futex_wake04.c:126: Bug: wait_thread2 did not wake after 30 secs. With the patch applied futex_wake04 0 TINFO : Hugepagesize 2097152 futex_wake04 1 TPASS : Hi hydra, thread2 awake!

Mel Gorman committed 10 years ago

Commit 077fa7a1 parent 2c610021 file · +11 −3Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/futex.c+11−3
@@ -469,7 +469,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) · 468 unmodified lines
469{469{
470 unsigned long address = (unsigned long)uaddr;470 unsigned long address = (unsigned long)uaddr;
471 struct mm_struct *mm = current->mm;471 struct mm_struct *mm = current->mm;
472 struct page *page;472 struct page *page, *tail;
473 struct address_space *mapping;473 struct address_space *mapping;
474 int err, ro = 0;474 int err, ro = 0;
475 475
@@ -530,7 +530,15 @@ again: · 54 unmodified lines
530 * considered here and page lock forces unnecessarily serialization530 * considered here and page lock forces unnecessarily serialization
531 * From this point on, mapping will be re-verified if necessary and531 * From this point on, mapping will be re-verified if necessary and
532 * page lock will be acquired only if it is unavoidable532 * page lock will be acquired only if it is unavoidable
533 */533 *
534 * Mapping checks require the head page for any compound page so the
535 * head page and mapping is looked up now. For anonymous pages, it
536 * does not matter if the page splits in the future as the key is
537 * based on the address. For filesystem-backed pages, the tail is
538 * required as the index of the page determines the key. For
539 * base pages, there is no tail page and tail == page.
540 */
541 tail = page;
534 page = compound_head(page);542 page = compound_head(page);
535 mapping = READ_ONCE(page->mapping);543 mapping = READ_ONCE(page->mapping);
536 544
@@ -654,7 +662,7 @@ again: · 117 unmodified lines
654 662
655 key->both.offset |= FUT_OFF_INODE; /* inode-based key */663 key->both.offset |= FUT_OFF_INODE; /* inode-based key */
656 key->shared.inode = inode;664 key->shared.inode = inode;
657 key->shared.pgoff = basepage_index(page);665 key->shared.pgoff = basepage_index(tail);
658 rcu_read_unlock();666 rcu_read_unlock();
659 }667 }
660 668

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t