[Devel] [PATCH rh7 v2] tcache: fix BUG at mm/tcache.c:421
Vladimir Davydov
vdavydov at parallels.com
Fri Jul 3 03:21:10 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>
---
Changes in v2:
- account for the fact that tcache_detach_page may return NULL
mm/tcache.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mm/tcache.c b/mm/tcache.c
index e83ad05da944..8de333905f81 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(cache_page && 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