diff options
author | Kirill A. Shutemov <kirill.shutemov@linux.intel.com> | 2019-10-18 23:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-10-19 06:32:33 -0400 |
commit | ef18a1ca847b01cb7296f11a728cb2f5ef671760 (patch) | |
tree | 1997ff661ec1c7d5d25bc59264d7520c845427c8 | |
parent | 906d278d75e364f2bb85dc1e1ff6265ea46e7e43 (diff) |
mm/thp: allow dropping THP from page cache
Once a THP is added to the page cache, it cannot be dropped via
/proc/sys/vm/drop_caches. Fix this issue with proper handling in
invalidate_mapping_pages().
Link: http://lkml.kernel.org/r/20191017164223.2762148-5-songliubraving@fb.com
Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Song Liu <songliubraving@fb.com>
Tested-by: Song Liu <songliubraving@fb.com>
Acked-by: Yang Shi <yang.shi@linux.alibaba.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: William Kucharski <william.kucharski@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/truncate.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/mm/truncate.c b/mm/truncate.c index 8563339041f6..dd9ebc1da356 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
@@ -592,6 +592,16 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, | |||
592 | unlock_page(page); | 592 | unlock_page(page); |
593 | continue; | 593 | continue; |
594 | } | 594 | } |
595 | |||
596 | /* Take a pin outside pagevec */ | ||
597 | get_page(page); | ||
598 | |||
599 | /* | ||
600 | * Drop extra pins before trying to invalidate | ||
601 | * the huge page. | ||
602 | */ | ||
603 | pagevec_remove_exceptionals(&pvec); | ||
604 | pagevec_release(&pvec); | ||
595 | } | 605 | } |
596 | 606 | ||
597 | ret = invalidate_inode_page(page); | 607 | ret = invalidate_inode_page(page); |
@@ -602,6 +612,8 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, | |||
602 | */ | 612 | */ |
603 | if (!ret) | 613 | if (!ret) |
604 | deactivate_file_page(page); | 614 | deactivate_file_page(page); |
615 | if (PageTransHuge(page)) | ||
616 | put_page(page); | ||
605 | count += ret; | 617 | count += ret; |
606 | } | 618 | } |
607 | pagevec_remove_exceptionals(&pvec); | 619 | pagevec_remove_exceptionals(&pvec); |