[PATCH 2/2] mm/page_alloc: use a single function to free page

From: Aaron Lu
Date: Mon Nov 05 2018 - 03:58:32 EST


We have multiple places of freeing a page, most of them doing similar
things and a common function can be used to reduce code duplicate.

It also avoids bug fixed in one function and left in another.

Signed-off-by: Aaron Lu <aaron.lu@xxxxxxxxx>
---
mm/page_alloc.c | 37 +++++++++++++++++--------------------
1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 91a9a6af41a2..2b330296e92a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4425,9 +4425,17 @@ unsigned long get_zeroed_page(gfp_t gfp_mask)
}
EXPORT_SYMBOL(get_zeroed_page);

-void __free_pages(struct page *page, unsigned int order)
+/*
+ * Free a page by reducing its ref count by @nr.
+ * If its refcount reaches 0, then according to its order:
+ * order0: send to PCP;
+ * high order: directly send to Buddy.
+ */
+static inline void free_the_page(struct page *page, unsigned int order, int nr)
{
- if (put_page_testzero(page)) {
+ VM_BUG_ON_PAGE(page_ref_count(page) == 0, page);
+
+ if (page_ref_sub_and_test(page, nr)) {
if (order == 0)
free_unref_page(page);
else
@@ -4435,6 +4443,11 @@ void __free_pages(struct page *page, unsigned int order)
}
}

+void __free_pages(struct page *page, unsigned int order)
+{
+ free_the_page(page, order, 1);
+}
+
EXPORT_SYMBOL(__free_pages);

void free_pages(unsigned long addr, unsigned int order)
@@ -4481,16 +4494,7 @@ static struct page *__page_frag_cache_refill(struct page_frag_cache *nc,

void __page_frag_cache_drain(struct page *page, unsigned int count)
{
- VM_BUG_ON_PAGE(page_ref_count(page) == 0, page);
-
- if (page_ref_sub_and_test(page, count)) {
- unsigned int order = compound_order(page);
-
- if (order == 0)
- free_unref_page(page);
- else
- __free_pages_ok(page, order);
- }
+ free_the_page(page, compound_order(page), count);
}
EXPORT_SYMBOL(__page_frag_cache_drain);

@@ -4555,14 +4559,7 @@ void page_frag_free(void *addr)
{
struct page *page = virt_to_head_page(addr);

- if (unlikely(put_page_testzero(page))) {
- unsigned int order = compound_order(page);
-
- if (order == 0)
- free_unref_page(page);
- else
- __free_pages_ok(page, order);
- }
+ free_the_page(page, compound_order(page), 1);
}
EXPORT_SYMBOL(page_frag_free);

--
2.17.2