aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mm.h18
-rw-r--r--mm/hugetlb.c2
-rw-r--r--mm/page_alloc.c2
-rw-r--r--mm/swap.c4
4 files changed, 22 insertions, 4 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0e266fe1b4c4..a17b147c61e7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -296,6 +296,24 @@ void put_pages_list(struct list_head *pages);
296void split_page(struct page *page, unsigned int order); 296void split_page(struct page *page, unsigned int order);
297 297
298/* 298/*
299 * Compound pages have a destructor function. Provide a
300 * prototype for that function and accessor functions.
301 * These are _only_ valid on the head of a PG_compound page.
302 */
303typedef void compound_page_dtor(struct page *);
304
305static inline void set_compound_page_dtor(struct page *page,
306 compound_page_dtor *dtor)
307{
308 page[1].lru.next = (void *)dtor;
309}
310
311static inline compound_page_dtor *get_compound_page_dtor(struct page *page)
312{
313 return (compound_page_dtor *)page[1].lru.next;
314}
315
316/*
299 * Multiple processes may "see" the same page. E.g. for untouched 317 * Multiple processes may "see" the same page. E.g. for untouched
300 * mappings of /dev/null, all processes see the same page full of 318 * mappings of /dev/null, all processes see the same page full of
301 * zeroes, and text pages of executables and shared libraries have 319 * zeroes, and text pages of executables and shared libraries have
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 2911a364481e..0ccc7f230252 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -109,7 +109,7 @@ static int alloc_fresh_huge_page(void)
109 if (nid == MAX_NUMNODES) 109 if (nid == MAX_NUMNODES)
110 nid = first_node(node_online_map); 110 nid = first_node(node_online_map);
111 if (page) { 111 if (page) {
112 page[1].lru.next = (void *)free_huge_page; /* dtor */ 112 set_compound_page_dtor(page, free_huge_page);
113 spin_lock(&hugetlb_lock); 113 spin_lock(&hugetlb_lock);
114 nr_huge_pages++; 114 nr_huge_pages++;
115 nr_huge_pages_node[page_to_nid(page)]++; 115 nr_huge_pages_node[page_to_nid(page)]++;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index dc8753bdd47e..d539f83c62b6 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -230,7 +230,7 @@ static void prep_compound_page(struct page *page, unsigned long order)
230 int i; 230 int i;
231 int nr_pages = 1 << order; 231 int nr_pages = 1 << order;
232 232
233 page[1].lru.next = (void *)free_compound_page; /* set dtor */ 233 set_compound_page_dtor(page, free_compound_page);
234 page[1].lru.prev = (void *)order; 234 page[1].lru.prev = (void *)order;
235 for (i = 0; i < nr_pages; i++) { 235 for (i = 0; i < nr_pages; i++) {
236 struct page *p = page + i; 236 struct page *p = page + i;
diff --git a/mm/swap.c b/mm/swap.c
index d9a3770d8f3c..017e72ca9bbb 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -57,9 +57,9 @@ static void put_compound_page(struct page *page)
57{ 57{
58 page = (struct page *)page_private(page); 58 page = (struct page *)page_private(page);
59 if (put_page_testzero(page)) { 59 if (put_page_testzero(page)) {
60 void (*dtor)(struct page *page); 60 compound_page_dtor *dtor;
61 61
62 dtor = (void (*)(struct page *))page[1].lru.next; 62 dtor = get_compound_page_dtor(page);
63 (*dtor)(page); 63 (*dtor)(page);
64 } 64 }
65} 65}