diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/ksm.c | 15 |
1 files changed, 3 insertions, 12 deletions
@@ -415,20 +415,11 @@ out: | |||
415 | static struct page *page_trans_compound_anon(struct page *page) | 415 | static struct page *page_trans_compound_anon(struct page *page) |
416 | { | 416 | { |
417 | if (PageTransCompound(page)) { | 417 | if (PageTransCompound(page)) { |
418 | struct page *head; | 418 | struct page *head = compound_trans_head(page); |
419 | head = compound_head(page); | ||
420 | /* | 419 | /* |
421 | * head may be a dangling pointer. | 420 | * head may actually be splitted and freed from under |
422 | * __split_huge_page_refcount clears PageTail | 421 | * us but it's ok here. |
423 | * before overwriting first_page, so if | ||
424 | * PageTail is still there it means the head | ||
425 | * pointer isn't dangling. | ||
426 | */ | 422 | */ |
427 | if (head != page) { | ||
428 | smp_rmb(); | ||
429 | if (!PageTransCompound(page)) | ||
430 | return NULL; | ||
431 | } | ||
432 | if (PageAnon(head)) | 423 | if (PageAnon(head)) |
433 | return head; | 424 | return head; |
434 | } | 425 | } |