summaryrefslogtreecommitdiffstats
path: root/lib/radix-tree.c
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@linux.intel.com>2016-12-15 00:08:37 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-15 01:04:10 +0100
commit9498d2bb34b0866829c313569df35e77a83f12eb (patch)
treedb19aaa39dc04f8ad77335a06623a2443717a872 /lib/radix-tree.c
parentradix-tree: move rcu_head into a union with private_list (diff)
downloadlinux-9498d2bb34b0866829c313569df35e77a83f12eb.tar.xz
linux-9498d2bb34b0866829c313569df35e77a83f12eb.zip
radix-tree: create node_tag_set()
Similar to node_tag_clear(), factor node_tag_set() out of radix_tree_range_tag_if_tagged(). Link: http://lkml.kernel.org/r/1480369871-5271-51-git-send-email-mawilcox@linuxonhyperv.com Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Konstantin Khlebnikov <koct9i@gmail.com> Cc: Ross Zwisler <ross.zwisler@linux.intel.com> Cc: Matthew Wilcox <mawilcox@microsoft.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/radix-tree.c')
-rw-r--r--lib/radix-tree.c41
1 files changed, 19 insertions, 22 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 8c5911eae5e2..a90a4371deb8 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -991,6 +991,22 @@ static void node_tag_clear(struct radix_tree_root *root,
root_tag_clear(root, tag);
}
+static void node_tag_set(struct radix_tree_root *root,
+ struct radix_tree_node *node,
+ unsigned int tag, unsigned int offset)
+{
+ while (node) {
+ if (tag_get(node, tag, offset))
+ return;
+ tag_set(node, tag, offset);
+ offset = node->offset;
+ node = node->parent;
+ }
+
+ if (!root_tag_get(root, tag))
+ root_tag_set(root, tag);
+}
+
/**
* radix_tree_tag_clear - clear a tag on a radix tree node
* @root: radix tree root
@@ -1229,7 +1245,7 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
unsigned long nr_to_tag,
unsigned int iftag, unsigned int settag)
{
- struct radix_tree_node *parent, *node, *child;
+ struct radix_tree_node *node, *child;
unsigned long maxindex;
unsigned long tagged = 0;
unsigned long index = *first_indexp;
@@ -1264,22 +1280,8 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
continue;
}
- /* tag the leaf */
tagged++;
- tag_set(node, settag, offset);
-
- /* walk back up the path tagging interior nodes */
- parent = node;
- for (;;) {
- offset = parent->offset;
- parent = parent->parent;
- if (!parent)
- break;
- /* stop if we find a node with the tag already set */
- if (tag_get(parent, settag, offset))
- break;
- tag_set(parent, settag, offset);
- }
+ node_tag_set(root, node, settag, offset);
next:
/* Go to next entry in node */
index = ((index >> node->shift) + 1) << node->shift;
@@ -1301,12 +1303,7 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
if (tagged >= nr_to_tag)
break;
}
- /*
- * We need not to tag the root tag if there is no tag which is set with
- * settag within the range from *first_indexp to last_index.
- */
- if (tagged > 0)
- root_tag_set(root, settag);
+
*first_indexp = index;
return tagged;