[Devel] [PATCH RHEL7 COMMIT] tcache: store tcache_node in page->mapping instead of page->private

Konstantin Khorenko khorenko at virtuozzo.com
Fri Feb 19 02:15:41 PST 2016


The commit is pushed to "branch-rh7-3.10.0-327.4.5.vz7.11.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.4.5.vz7.11.4
------>
commit f1dae749e21fc715e6e7eebcaff4ae7082ef1a8d
Author: Vladimir Davydov <vdavydov at virtuozzo.com>
Date:   Fri Feb 19 14:15:41 2016 +0400

    tcache: store tcache_node in page->mapping instead of page->private
    
    I'll need to store extra information in page struct soon, page->private
    fits better for it, because this is going to be an integer. So let's
    store tcache_node in page->mapping instead of page->private. Note, in
    order to not trigger free_pages_check warning, we need to clear
    page->mapping once the last reference to a page has gone, so this patch
    encapsulates page refcount manipulation in dedicated functions.
    
    Related to https://jira.sw.ru/browse/PSBM-41239
    
    Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
---
 mm/tcache.c | 39 ++++++++++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/mm/tcache.c b/mm/tcache.c
index f4ea718..61c5283 100644
--- a/mm/tcache.c
+++ b/mm/tcache.c
@@ -537,16 +537,29 @@ tcache_invalidate_node_tree(struct tcache_node_tree *tree)
 
 static inline struct tcache_node *tcache_page_node(struct page *page)
 {
-	return (struct tcache_node *)page->private;
+	return (struct tcache_node *)page->mapping;
 }
 
 static inline void tcache_init_page(struct page *page,
 				    struct tcache_node *node, pgoff_t index)
 {
-	page->private = (unsigned long)node;
+	page->mapping = (struct address_space *)node;
 	page->index = index;
 }
 
+static inline void tcache_hold_page(struct page *page)
+{
+	get_page(page);
+}
+
+static inline void tcache_put_page(struct page *page)
+{
+	if (put_page_testzero(page)) {
+		page->mapping = NULL;	/* to make free_pages_check happy */
+		free_hot_cold_page(page, false);
+	}
+}
+
 static int tcache_page_tree_replace(struct tcache_node *node, pgoff_t index,
 				    struct page *page, struct page **old_page)
 {
@@ -630,9 +643,9 @@ tcache_attach_page(struct tcache_node *node, pgoff_t index, struct page *page)
 
 	if (old_page) {
 		tcache_lru_del(old_page);
-		put_page(old_page);
+		tcache_put_page(old_page);
 	}
-	get_page(page);
+	tcache_hold_page(page);
 	tcache_lru_add(page);
 out:
 	local_irq_restore(flags);
@@ -681,7 +694,7 @@ restart:
 		page = radix_tree_deref_slot_protected(slot, &node->tree_lock);
 		BUG_ON(!__tcache_page_tree_delete(node, page->index, page));
 		tcache_lru_del(page);
-		put_page(page);
+		tcache_put_page(page);
 
 		if (need_resched()) {
 			spin_unlock_irq(&node->tree_lock);
@@ -739,7 +752,7 @@ static struct page *tcache_lru_isolate(struct tcache_lru *lru,
 	}
 
 	tcache_hold_node(node);
-	get_page(page);
+	tcache_hold_page(page);
 
 	*pnode = node;
 out:
@@ -763,13 +776,13 @@ __tcache_try_to_reclaim_page(struct tcache_lru *lru)
 			 * corresponding reference. Note, we still hold the
 			 * page reference taken in tcache_lru_isolate.
 			 */
-			put_page(page);
+			tcache_put_page(page);
 		} else {
 			/*
 			 * The page was deleted by a concurrent thread - drop
 			 * the reference taken in tcache_lru_isolate and abort.
 			 */
-			put_page(page);
+			tcache_put_page(page);
 			page = NULL;
 		}
 		tcache_put_node_and_pool(node);
@@ -812,7 +825,7 @@ static unsigned long tcache_shrink_scan(struct shrinker *shrink,
 	while (lru->nr_items > 0 && sc->nr_to_scan > 0) {
 		page = __tcache_try_to_reclaim_page(lru);
 		if (page) {
-			put_page(page);
+			tcache_put_page(page);
 			nr_reclaimed++;
 		}
 		sc->nr_to_scan--;
@@ -866,7 +879,7 @@ static void tcache_cleancache_put_page(int pool_id,
 	}
 
 	if (cache_page)
-		put_page(cache_page);
+		tcache_put_page(cache_page);
 }
 
 static int tcache_cleancache_get_page(int pool_id,
@@ -880,7 +893,7 @@ static int tcache_cleancache_get_page(int pool_id,
 	if (node) {
 		cache_page = tcache_detach_page(node, index);
 		if (unlikely(cache_page && node->invalidated)) {
-			put_page(cache_page);
+			tcache_put_page(cache_page);
 			cache_page = NULL;
 		}
 		tcache_put_node_and_pool(node);
@@ -888,7 +901,7 @@ static int tcache_cleancache_get_page(int pool_id,
 
 	if (cache_page) {
 		copy_highpage(page, cache_page);
-		put_page(cache_page);
+		tcache_put_page(cache_page);
 		return 0;
 	}
 	return -1;
@@ -904,7 +917,7 @@ static void tcache_cleancache_invalidate_page(int pool_id,
 	if (node) {
 		page = tcache_detach_page(node, index);
 		if (page)
-			put_page(page);
+			tcache_put_page(page);
 		tcache_put_node_and_pool(node);
 	}
 }


More information about the Devel mailing list