diff options
Diffstat (limited to 'arch/powerpc/mm/hugetlbpage.c')
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 0b9a5c1901b9..da5eb3885702 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -390,7 +390,7 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add | |||
390 | { | 390 | { |
391 | unsigned long mask; | 391 | unsigned long mask; |
392 | unsigned long pte_end; | 392 | unsigned long pte_end; |
393 | struct page *head, *page; | 393 | struct page *head, *page, *tail; |
394 | pte_t pte; | 394 | pte_t pte; |
395 | int refs; | 395 | int refs; |
396 | 396 | ||
@@ -413,6 +413,7 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add | |||
413 | head = pte_page(pte); | 413 | head = pte_page(pte); |
414 | 414 | ||
415 | page = head + ((addr & (sz-1)) >> PAGE_SHIFT); | 415 | page = head + ((addr & (sz-1)) >> PAGE_SHIFT); |
416 | tail = page; | ||
416 | do { | 417 | do { |
417 | VM_BUG_ON(compound_head(page) != head); | 418 | VM_BUG_ON(compound_head(page) != head); |
418 | pages[*nr] = page; | 419 | pages[*nr] = page; |
@@ -428,10 +429,20 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add | |||
428 | 429 | ||
429 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { | 430 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { |
430 | /* Could be optimized better */ | 431 | /* Could be optimized better */ |
431 | while (*nr) { | 432 | *nr -= refs; |
432 | put_page(page); | 433 | while (refs--) |
433 | (*nr)--; | 434 | put_page(head); |
434 | } | 435 | return 0; |
436 | } | ||
437 | |||
438 | /* | ||
439 | * Any tail page need their mapcount reference taken before we | ||
440 | * return. | ||
441 | */ | ||
442 | while (refs--) { | ||
443 | if (PageTail(tail)) | ||
444 | get_huge_page_tail(tail); | ||
445 | tail++; | ||
435 | } | 446 | } |
436 | 447 | ||
437 | return 1; | 448 | return 1; |