[Devel] [PATCH RHEL7 COMMIT] mm/tcache: invalidate existing page during cleancache_put_page()

Konstantin Khorenko khorenko at virtuozzo.com
Wed Jan 31 15:54:26 MSK 2018


The commit is pushed to "branch-rh7-3.10.0-693.11.6.vz7.42.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.11.6.vz7.42.3
------>
commit 463faaa4964e0029667a929c5aadc0b2f3cdef9a
Author: Andrey Ryabinin <aryabinin at virtuozzo.com>
Date:   Wed Jan 31 15:54:26 2018 +0300

    mm/tcache: invalidate existing page during cleancache_put_page()
    
    We ->put_page() into tcache twice w/o ->get_page() in between, resulting in:
    
    WARNING: CPU: 1 PID: 1936 at mm/tcache.c:752 tcache_attach_page+0x218/0x240
    
    Call Trace:
     dump_stack+0x19/0x1b
     add_taint+0x32/0x70
     __warn+0xaa/0x100
     warn_slowpath_null+0x1d/0x20
     tcache_attach_page+0x218/0x240
     tcache_cleancache_put_page+0xdc/0x150
     __cleancache_put_page+0xa2/0xf0
     __delete_from_page_cache+0x309/0x370
     __remove_mapping+0x91/0x180
     shrink_page_list+0x5a8/0xa80
     shrink_inactive_list+0x1da/0x710
     shrink_lruvec+0x3a1/0x760
     shrink_zone+0x15b/0x310
     do_try_to_free_pages+0x1a0/0x610
     try_to_free_mem_cgroup_pages+0xeb/0x190
     mem_cgroup_reclaim+0x63/0x140
     try_charge+0x287/0x560
     mem_cgroup_try_charge+0x7a/0x130
     __add_to_page_cache_locked+0x97/0x2f0
     add_to_page_cache_lru+0x37/0xb0
     mpage_readpages+0xb5/0x150
     ext4_readpages+0x3c/0x40 [ext4]
     __do_page_cache_readahead+0x1cd/0x250
     ondemand_readahead+0x116/0x230
     page_cache_async_readahead+0xa8/0xc0
    
    It's because we put all clean pages into cleancache, but in some cases
    we may never read those pages from cleancache. E.g. see do_mpage_readpage(),
    there are many case when cleancache_get_page() is not called.
    
    Fix this by invalidating such existing page during ->put_page().
    
    https://jira.sw.ru/browse/PSBM-80712
    Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
    Reviewed-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 mm/tcache.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/mm/tcache.c b/mm/tcache.c
index 1457664459bb..271d00187a50 100644
--- a/mm/tcache.c
+++ b/mm/tcache.c
@@ -751,7 +751,6 @@ static int tcache_page_tree_insert(struct tcache_node *node, pgoff_t index,
 	}
 
 	err = radix_tree_insert(&node->page_tree, index, page);
-	WARN_ON(err == -EEXIST);
 	if (!err) {
 		if (!node->nr_pages++)
 			tcache_hold_node(node);
@@ -1272,9 +1271,18 @@ static int tcache_cleancache_put_page(int pool_id,
 		cache_page = tcache_alloc_page(node->pool);
 		if (cache_page) {
 			copy_highpage(cache_page, page);
-			if (tcache_attach_page(node, index, cache_page)) {
+			ret = tcache_attach_page(node, index, cache_page);
+			if (ret) {
+				if (ret == -EEXIST) {
+					struct page *page;
+
+					page = tcache_detach_page(node, index, false);
+					if (page)
+						tcache_put_page(page);
+				}
 				if (put_page_testzero(cache_page))
 					tcache_put_page(cache_page);
+				ret = 0;
 			} else
 				ret = 1;
 		}


More information about the Devel mailing list