|
@@ -469,7 +469,8 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
|
|
{
|
|
{
|
|
unsigned long address = (unsigned long)uaddr;
|
|
unsigned long address = (unsigned long)uaddr;
|
|
struct mm_struct *mm = current->mm;
|
|
struct mm_struct *mm = current->mm;
|
|
- struct page *page, *page_head;
|
|
|
|
|
|
+ struct page *page;
|
|
|
|
+ struct address_space *mapping;
|
|
int err, ro = 0;
|
|
int err, ro = 0;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -519,46 +520,9 @@ again:
|
|
else
|
|
else
|
|
err = 0;
|
|
err = 0;
|
|
|
|
|
|
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
|
|
- page_head = page;
|
|
|
|
- if (unlikely(PageTail(page))) {
|
|
|
|
- put_page(page);
|
|
|
|
- /* serialize against __split_huge_page_splitting() */
|
|
|
|
- local_irq_disable();
|
|
|
|
- if (likely(__get_user_pages_fast(address, 1, !ro, &page) == 1)) {
|
|
|
|
- page_head = compound_head(page);
|
|
|
|
- /*
|
|
|
|
- * page_head is valid pointer but we must pin
|
|
|
|
- * it before taking the PG_lock and/or
|
|
|
|
- * PG_compound_lock. The moment we re-enable
|
|
|
|
- * irqs __split_huge_page_splitting() can
|
|
|
|
- * return and the head page can be freed from
|
|
|
|
- * under us. We can't take the PG_lock and/or
|
|
|
|
- * PG_compound_lock on a page that could be
|
|
|
|
- * freed from under us.
|
|
|
|
- */
|
|
|
|
- if (page != page_head) {
|
|
|
|
- get_page(page_head);
|
|
|
|
- put_page(page);
|
|
|
|
- }
|
|
|
|
- local_irq_enable();
|
|
|
|
- } else {
|
|
|
|
- local_irq_enable();
|
|
|
|
- goto again;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-#else
|
|
|
|
- page_head = compound_head(page);
|
|
|
|
- if (page != page_head) {
|
|
|
|
- get_page(page_head);
|
|
|
|
- put_page(page);
|
|
|
|
- }
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- lock_page(page_head);
|
|
|
|
-
|
|
|
|
|
|
+ lock_page(page);
|
|
/*
|
|
/*
|
|
- * If page_head->mapping is NULL, then it cannot be a PageAnon
|
|
|
|
|
|
+ * If page->mapping is NULL, then it cannot be a PageAnon
|
|
* page; but it might be the ZERO_PAGE or in the gate area or
|
|
* page; but it might be the ZERO_PAGE or in the gate area or
|
|
* in a special mapping (all cases which we are happy to fail);
|
|
* in a special mapping (all cases which we are happy to fail);
|
|
* or it may have been a good file page when get_user_pages_fast
|
|
* or it may have been a good file page when get_user_pages_fast
|
|
@@ -570,12 +534,13 @@ again:
|
|
*
|
|
*
|
|
* The case we do have to guard against is when memory pressure made
|
|
* The case we do have to guard against is when memory pressure made
|
|
* shmem_writepage move it from filecache to swapcache beneath us:
|
|
* shmem_writepage move it from filecache to swapcache beneath us:
|
|
- * an unlikely race, but we do need to retry for page_head->mapping.
|
|
|
|
|
|
+ * an unlikely race, but we do need to retry for page->mapping.
|
|
*/
|
|
*/
|
|
- if (!page_head->mapping) {
|
|
|
|
- int shmem_swizzled = PageSwapCache(page_head);
|
|
|
|
- unlock_page(page_head);
|
|
|
|
- put_page(page_head);
|
|
|
|
|
|
+ mapping = compound_head(page)->mapping;
|
|
|
|
+ if (!mapping) {
|
|
|
|
+ int shmem_swizzled = PageSwapCache(page);
|
|
|
|
+ unlock_page(page);
|
|
|
|
+ put_page(page);
|
|
if (shmem_swizzled)
|
|
if (shmem_swizzled)
|
|
goto again;
|
|
goto again;
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
@@ -588,7 +553,7 @@ again:
|
|
* it's a read-only handle, it's expected that futexes attach to
|
|
* it's a read-only handle, it's expected that futexes attach to
|
|
* the object not the particular process.
|
|
* the object not the particular process.
|
|
*/
|
|
*/
|
|
- if (PageAnon(page_head)) {
|
|
|
|
|
|
+ if (PageAnon(page)) {
|
|
/*
|
|
/*
|
|
* A RO anonymous page will never change and thus doesn't make
|
|
* A RO anonymous page will never change and thus doesn't make
|
|
* sense for futex operations.
|
|
* sense for futex operations.
|
|
@@ -603,15 +568,15 @@ again:
|
|
key->private.address = address;
|
|
key->private.address = address;
|
|
} else {
|
|
} else {
|
|
key->both.offset |= FUT_OFF_INODE; /* inode-based key */
|
|
key->both.offset |= FUT_OFF_INODE; /* inode-based key */
|
|
- key->shared.inode = page_head->mapping->host;
|
|
|
|
|
|
+ key->shared.inode = mapping->host;
|
|
key->shared.pgoff = basepage_index(page);
|
|
key->shared.pgoff = basepage_index(page);
|
|
}
|
|
}
|
|
|
|
|
|
get_futex_key_refs(key); /* implies MB (B) */
|
|
get_futex_key_refs(key); /* implies MB (B) */
|
|
|
|
|
|
out:
|
|
out:
|
|
- unlock_page(page_head);
|
|
|
|
- put_page(page_head);
|
|
|
|
|
|
+ unlock_page(page);
|
|
|
|
+ put_page(page);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|