diff options
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 1907688b75ee..b85919243399 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -493,36 +493,45 @@ next: | |||
493 | info = list_entry(pos, struct shmem_inode_info, shrinklist); | 493 | info = list_entry(pos, struct shmem_inode_info, shrinklist); |
494 | inode = &info->vfs_inode; | 494 | inode = &info->vfs_inode; |
495 | 495 | ||
496 | if (nr_to_split && split >= nr_to_split) { | 496 | if (nr_to_split && split >= nr_to_split) |
497 | iput(inode); | 497 | goto leave; |
498 | continue; | ||
499 | } | ||
500 | 498 | ||
501 | page = find_lock_page(inode->i_mapping, | 499 | page = find_get_page(inode->i_mapping, |
502 | (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT); | 500 | (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT); |
503 | if (!page) | 501 | if (!page) |
504 | goto drop; | 502 | goto drop; |
505 | 503 | ||
504 | /* No huge page at the end of the file: nothing to split */ | ||
506 | if (!PageTransHuge(page)) { | 505 | if (!PageTransHuge(page)) { |
507 | unlock_page(page); | ||
508 | put_page(page); | 506 | put_page(page); |
509 | goto drop; | 507 | goto drop; |
510 | } | 508 | } |
511 | 509 | ||
510 | /* | ||
511 | * Leave the inode on the list if we failed to lock | ||
512 | * the page at this time. | ||
513 | * | ||
514 | * Waiting for the lock may lead to deadlock in the | ||
515 | * reclaim path. | ||
516 | */ | ||
517 | if (!trylock_page(page)) { | ||
518 | put_page(page); | ||
519 | goto leave; | ||
520 | } | ||
521 | |||
512 | ret = split_huge_page(page); | 522 | ret = split_huge_page(page); |
513 | unlock_page(page); | 523 | unlock_page(page); |
514 | put_page(page); | 524 | put_page(page); |
515 | 525 | ||
516 | if (ret) { | 526 | /* If split failed leave the inode on the list */ |
517 | /* split failed: leave it on the list */ | 527 | if (ret) |
518 | iput(inode); | 528 | goto leave; |
519 | continue; | ||
520 | } | ||
521 | 529 | ||
522 | split++; | 530 | split++; |
523 | drop: | 531 | drop: |
524 | list_del_init(&info->shrinklist); | 532 | list_del_init(&info->shrinklist); |
525 | removed++; | 533 | removed++; |
534 | leave: | ||
526 | iput(inode); | 535 | iput(inode); |
527 | } | 536 | } |
528 | 537 | ||