diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2013-11-19 22:02:36 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-11-19 22:02:36 -0500 |
commit | f294dc27a052f476d216c04ab386d84eb80f3c8c (patch) | |
tree | f000092a954a409b855d6b9c49435e07267904a8 /mm | |
parent | e4b4e0ed014258359aaf089824808333d768bc79 (diff) | |
parent | 14aa272fcd1cdbe7173073250c767bc7a37278ce (diff) |
Merge tag 'v3.4.69' into v3.4-rt
This is the 3.4.69 stable release
Conflicts:
mm/swap.c
Diffstat (limited to 'mm')
-rw-r--r-- | mm/swap.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/mm/swap.c b/mm/swap.c index 15c1c53bff89..bff7beaed861 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -30,6 +30,7 @@ #include <linux/backing-dev.h> #include <linux/memcontrol.h> #include <linux/gfp.h> +#include <linux/hugetlb.h> #include <linux/locallock.h> #include "internal.h" @@ -72,13 +73,26 @@ static void __put_compound_page(struct page *page) { compound_page_dtor *dtor; - __page_cache_release(page); + if (!PageHuge(page)) + __page_cache_release(page); dtor = get_compound_page_dtor(page); (*dtor)(page); } static void put_compound_page(struct page *page) { + /* + * hugetlbfs pages cannot be split from under us. If this is a + * hugetlbfs page, check refcount on head page and release the page if + * the refcount becomes zero. + */ + if (PageHuge(page)) { + page = compound_head(page); + if (put_page_testzero(page)) + __put_compound_page(page); + return; + } + if (unlikely(PageTail(page))) { /* __split_huge_page_refcount can run under us */ struct page *page_head = compound_trans_head(page); @@ -163,8 +177,20 @@ bool __get_page_tail(struct page *page) */ unsigned long flags; bool got = false; - struct page *page_head = compound_trans_head(page); + struct page *page_head; + + /* + * If this is a hugetlbfs page it cannot be split under us. Simply + * increment refcount for the head page. + */ + if (PageHuge(page)) { + page_head = compound_head(page); + atomic_inc(&page_head->_count); + got = true; + goto out; + } + page_head = compound_trans_head(page); if (likely(page != page_head && get_page_unless_zero(page_head))) { /* * page_head wasn't a dangling pointer but it @@ -182,6 +208,7 @@ bool __get_page_tail(struct page *page) if (unlikely(!got)) put_page(page_head); } +out: return got; } EXPORT_SYMBOL(__get_page_tail); |