radix-tree: Fix private list warnings
PATCH 1/1 radix-tree: Fix private list warnings
From: Matthew Wilcox <[email protected]>
The newly introduced warning in radix_tree_free_nodes() was testing the wrong variable; it should have been 'old' instead of 'node'. Rather than replace that one instance, I noticed that we can simply put the WARN_ON_ONCE in radix_tree_node_free() and it will be just as effective.
--- lib/radix-tree.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
lib/radix-tree.c +1 -3
@@ -449,6 +449,7 @@ static void radix_tree_node_rcu_free(struct rcu_head *head)static inline void radix_tree_node_free (struct radix_tree_node *node) { +WARN_ON_ONCE (!list_empty (&node->private_list));call_rcu (&node->rcu_head, radix_tree_node_rcu_free); }
@@ -734,7 +735,6 @@ static inline void radix_tree_shrink(struct radix_tree_root *root,update_node (node, private); } -WARN_ON_ONCE (!list_empty (&node->private_list));radix_tree_node_free (node); } }
@@ -766,7 +766,6 @@ static void delete_node(struct radix_tree_root *root, root->rnode =NULL ; } -WARN_ON_ONCE (!list_empty (&node->private_list));radix_tree_node_free (node); node = parent;
@@ -868,7 +867,6 @@ static void radix_tree_free_nodes(struct radix_tree_node *node)struct radix_tree_node *old = child; offset = child->offset +1 ; child = child->parent; -WARN_ON_ONCE (!list_empty (&node->private_list));radix_tree_node_free (old);if (old ==entry_to_node (node))return ;
Signature · 1 line
2.11.0.296.g5800ad326.dirty
Quoted 9 lines · Matthew Wilcox
From: Matthew Wilcox <[email protected]>
The newly introduced warning in
radix_tree_free_nodes()was testing the wrong variable; it should have been 'old' instead of 'node'. Rather than replace that one instance, I noticed that we can simply put theWARN_ON_ONCEinradix_tree_node_free()and it will be just as effective.Fixes ea07b862ac8e ("mm: workingset: fix use-after-free in shadow node shrinker")Signed-off-by Matthew Wilcox <[email protected]>
Thanks for the fix in radix_tree_free_nodes(). But I intentionally spread out the warnings to retain the line numbers. The inlining in that code will obscure which tree operation ends up triggering.
From: Johannes Weiner [mailto:[email protected]]
Quoted 6 lines · Matthew Wilcox
Quoted 5 lines
The newly introduced warning in
radix_tree_free_nodes()was testing the wrong variable; it should have been 'old' instead of 'node'. Rather than replace that one instance, I noticed that we can simply put theWARN_ON_ONCEinradix_tree_node_free()and it will be just as effective.
Quoted 7 lines
Quoted 1 line
Fixes ea07b862ac8e ("mm: workingset: fix use-after-free in shadow nodeshrinker")
Quoted 1 line
Signed-off-by Matthew Wilcox <[email protected]>Thanks for the fix in
radix_tree_free_nodes(). But I intentionally spread out the warnings to retain the line numbers. The inlining in that code will obscure which tree operation ends up triggering.
The backtrace should make that fairly obvious though; even if radix_tree_node_free() gets inlined, the caller of radix_tree_free_nodes() probably doesn't also call radix_tree_shrink() or delete_node(). You're really looking for the caller in the backtrace that's outside of radix-tree.c.
By the way, if you'd run the radix tree test-suite, the WARN_ON_ONCE would have triggered (that's how I spotted the bug). The test-suite is getting pretty useful these days; would you mind running it in future?
Quoted 15 lines · Matthew Wilcox
From: Johannes Weiner [mailto:[email protected]]
Quoted 6 lines · Matthew Wilcox
Quoted 5 lines
The newly introduced warning in
radix_tree_free_nodes()was testing the wrong variable; it should have been 'old' instead of 'node'. Rather than replace that one instance, I noticed that we can simply put theWARN_ON_ONCEinradix_tree_node_free()and it will be just as effective.Quoted 7 lines
Quoted 1 line
Fixes ea07b862ac8e ("mm: workingset: fix use-after-free in shadow nodeshrinker")
Quoted 1 line
Signed-off-by Matthew Wilcox <[email protected]>Thanks for the fix in
radix_tree_free_nodes(). But I intentionally spread out the warnings to retain the line numbers. The inlining in that code will obscure which tree operation ends up triggering.
Quoted 5 lines
The backtrace should make that fairly obvious though; even if
radix_tree_node_free()gets inlined, the caller ofradix_tree_free_nodes()probably doesn't also callradix_tree_shrink()ordelete_node(). You're really looking for the caller in the backtrace that's outside ofradix-tree.c.
Distinguishing between the radix_tree_shrink() and the delete_node() sites was essential to find the bug whose fix added these warnings. The former gets inlined into the latter. Not impossible to figure out which one triggered from a full dump, but certainly less robust.
Quoted 4 lines
By the way, if you'd run the radix tree test-suite, the
WARN_ON_ONCEwould have triggered (that's how I spotted the bug). The test-suite is getting pretty useful these days; would you mind running it in future?
Thanks, I'll keep that in mind for future radix tree changes.
Quoted 22 lines · Johannes Weiner
Quoted 15 lines · Matthew Wilcox
From: Johannes Weiner [mailto:[email protected]]
Quoted 6 lines · Matthew Wilcox
Quoted 5 lines
The newly introduced warning in
radix_tree_free_nodes()was testing the wrong variable; it should have been 'old' instead of 'node'. Rather than replace that one instance, I noticed that we can simply put theWARN_ON_ONCEinradix_tree_node_free()and it will be just as effective.Quoted 7 lines
Quoted 1 line
Fixes ea07b862ac8e ("mm: workingset: fix use-after-free in shadow nodeshrinker")
Quoted 1 line
Signed-off-by Matthew Wilcox <[email protected]>Thanks for the fix in
radix_tree_free_nodes(). But I intentionally spread out the warnings to retain the line numbers. The inlining in that code will obscure which tree operation ends up triggering.Quoted 5 lines
The backtrace should make that fairly obvious though; even if
radix_tree_node_free()gets inlined, the caller ofradix_tree_free_nodes()probably doesn't also callradix_tree_shrink()ordelete_node(). You're really looking for the caller in the backtrace that's outside ofradix-tree.c.
Quoted 4 lines
Distinguishing between the
radix_tree_shrink()and thedelete_node()sites was essential to find the bug whose fix added these warnings. The former gets inlined into the latter. Not impossible to figure out which one triggered from a full dump, but certainly less robust.
This?
Quoted 1 line
From
669b5ed6e32386d634023fee29b0b8562951e734Mon Sep 17 00:00:00 2001
From: Matthew Wilcox <[email protected]>
Date: Thu, 12 Jan 2017 17:28:23 -0800
Subject: [PATCH] radix-tree: Fix private list warnings
The newly introduced warning in radix_tree_free_nodes() was testing the wrong variable; it should have been 'old' instead of 'node'.
--- lib/radix-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/radix-tree.c +1 -1
@@ -769,7 +769,7 @@ static void radix_tree_free_nodes(struct radix_tree_node *node)struct radix_tree_node *old = child; offset = child->offset +1 ; child = child->parent; -WARN_ON_ONCE (!list_empty (&node->private_list)); +WARN_ON_ONCE (!list_empty (&old->private_list));radix_tree_node_free (old);if (old ==entry_to_node (node))return ;
Signature · 1 line
2.11.0