[Devel] [PATCH rh7] tcache: fix BUG at mm/tcache.c:421

Vladimir Davydov vdavydov at parallels.com
Wed Jul 1 02:55:01 PDT 2015


The BUG is triggered if tcache_get_node is about to return an
invalidated node. This actually can happen if cleancache_get_page races
with cleancache_invalidate_inode as follows, e.g. while concurrent
direct reads/writes are performed:

CPU0                                    CPU1
----                                    ----
cleancache_get_page                     cleancache_invalidate_inode
 tcache_cleancache_get_page              tcache_cleancache_invalidate_inode
  tcache_get_node_and_pool                tcache_invalidate_node
   tcache_get_node
    spin_lock_irqsave(&tree->lock, flags)
    node = <lookup in the tree>
    spin_unlock_irqrestore(&tree->lock, flags)
                                          spin_lock_irq(&tree->lock)
                                          <remove node from the tree>
                                          spin_unlock_irq(&tree->lock)
                                          tcache_invalidate_node_pages
                                           spin_lock_irq(&node->tree_lock)
                                           node->invalidated = true
    BUG_ON(node->invalidated);

Instead of panicking we should drop the page further in
cleancache_get_page.

https://jira.sw.ru/browse/PSBM-34620

Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
---
 mm/tcache.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/mm/tcache.c b/mm/tcache.c
index e83ad05da944..b70fbaeab926 100644
--- a/mm/tcache.c
+++ b/mm/tcache.c
@@ -418,7 +418,6 @@ retry:
 
 	if (node) {
 		BUG_ON(node->pool != pool);
-		BUG_ON(node->invalidated);
 		if (node != new_node)
 			kfree(new_node);
 		return node;
@@ -866,6 +865,10 @@ static int tcache_cleancache_get_page(int pool_id,
 	node = tcache_get_node_and_pool(pool_id, &key, false);
 	if (node) {
 		cache_page = tcache_detach_page(node, index);
+		if (unlikely(node->invalidated)) {
+			put_page(cache_page);
+			cache_page = NULL;
+		}
 		tcache_put_node_and_pool(node);
 	}
 
-- 
2.1.4




More information about the Devel mailing list