diff options
author | Matthew Wilcox <willy@linux.intel.com> | 2016-12-14 18:08:37 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 19:04:10 -0500 |
commit | 9498d2bb34b0866829c313569df35e77a83f12eb (patch) | |
tree | db19aaa39dc04f8ad77335a06623a2443717a872 /lib | |
parent | 91d9c05ac6c788531136888d31ef18c6a0ec160f (diff) |
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')
-rw-r--r-- | lib/radix-tree.c | 41 |
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, | |||
991 | root_tag_clear(root, tag); | 991 | root_tag_clear(root, tag); |
992 | } | 992 | } |
993 | 993 | ||
994 | static void node_tag_set(struct radix_tree_root *root, | ||
995 | struct radix_tree_node *node, | ||
996 | unsigned int tag, unsigned int offset) | ||
997 | { | ||
998 | while (node) { | ||
999 | if (tag_get(node, tag, offset)) | ||
1000 | return; | ||
1001 | tag_set(node, tag, offset); | ||
1002 | offset = node->offset; | ||
1003 | node = node->parent; | ||
1004 | } | ||
1005 | |||
1006 | if (!root_tag_get(root, tag)) | ||
1007 | root_tag_set(root, tag); | ||
1008 | } | ||
1009 | |||
994 | /** | 1010 | /** |
995 | * radix_tree_tag_clear - clear a tag on a radix tree node | 1011 | * radix_tree_tag_clear - clear a tag on a radix tree node |
996 | * @root: radix tree root | 1012 | * @root: radix tree root |
@@ -1229,7 +1245,7 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, | |||
1229 | unsigned long nr_to_tag, | 1245 | unsigned long nr_to_tag, |
1230 | unsigned int iftag, unsigned int settag) | 1246 | unsigned int iftag, unsigned int settag) |
1231 | { | 1247 | { |
1232 | struct radix_tree_node *parent, *node, *child; | 1248 | struct radix_tree_node *node, *child; |
1233 | unsigned long maxindex; | 1249 | unsigned long maxindex; |
1234 | unsigned long tagged = 0; | 1250 | unsigned long tagged = 0; |
1235 | unsigned long index = *first_indexp; | 1251 | unsigned long index = *first_indexp; |
@@ -1264,22 +1280,8 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, | |||
1264 | continue; | 1280 | continue; |
1265 | } | 1281 | } |
1266 | 1282 | ||
1267 | /* tag the leaf */ | ||
1268 | tagged++; | 1283 | tagged++; |
1269 | tag_set(node, settag, offset); | 1284 | node_tag_set(root, node, settag, offset); |
1270 | |||
1271 | /* walk back up the path tagging interior nodes */ | ||
1272 | parent = node; | ||
1273 | for (;;) { | ||
1274 | offset = parent->offset; | ||
1275 | parent = parent->parent; | ||
1276 | if (!parent) | ||
1277 | break; | ||
1278 | /* stop if we find a node with the tag already set */ | ||
1279 | if (tag_get(parent, settag, offset)) | ||
1280 | break; | ||
1281 | tag_set(parent, settag, offset); | ||
1282 | } | ||
1283 | next: | 1285 | next: |
1284 | /* Go to next entry in node */ | 1286 | /* Go to next entry in node */ |
1285 | index = ((index >> node->shift) + 1) << node->shift; | 1287 | index = ((index >> node->shift) + 1) << node->shift; |
@@ -1301,12 +1303,7 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, | |||
1301 | if (tagged >= nr_to_tag) | 1303 | if (tagged >= nr_to_tag) |
1302 | break; | 1304 | break; |
1303 | } | 1305 | } |
1304 | /* | 1306 | |
1305 | * We need not to tag the root tag if there is no tag which is set with | ||
1306 | * settag within the range from *first_indexp to last_index. | ||
1307 | */ | ||
1308 | if (tagged > 0) | ||
1309 | root_tag_set(root, settag); | ||
1310 | *first_indexp = index; | 1307 | *first_indexp = index; |
1311 | 1308 | ||
1312 | return tagged; | 1309 | return tagged; |