From 471727092cd12464209b53d624430a557d402ec1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Apr 2010 22:36:20 +0100 Subject: [PATCH] --- yaml --- r: 189672 b: refs/heads/master c: ce82653d6cfcc95ba88c25908664878459fb1b8d h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/radix-tree.h | 7 +++++++ trunk/lib/radix-tree.c | 12 ++++++------ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index ab337d7ca479..c084e10af1bb 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d3e06e2b15590b70ea73733fc4612e4741ff46e0 +refs/heads/master: ce82653d6cfcc95ba88c25908664878459fb1b8d diff --git a/trunk/include/linux/radix-tree.h b/trunk/include/linux/radix-tree.h index c5da74918096..55ca73cf25e5 100644 --- a/trunk/include/linux/radix-tree.h +++ b/trunk/include/linux/radix-tree.h @@ -121,6 +121,13 @@ do { \ * (Note, rcu_assign_pointer and rcu_dereference are not needed to control * access to data items when inserting into or looking up from the radix tree) * + * Note that the value returned by radix_tree_tag_get() may not be relied upon + * if only the RCU read lock is held. Functions to set/clear tags and to + * delete nodes running concurrently with it may affect its result such that + * two consecutive reads in the same locked section may return different + * values. If reliability is required, modification functions must also be + * excluded from concurrency. + * * radix_tree_tagged is able to be called without locking or RCU. */ diff --git a/trunk/lib/radix-tree.c b/trunk/lib/radix-tree.c index 0871582aa29d..2a087e0f9863 100644 --- a/trunk/lib/radix-tree.c +++ b/trunk/lib/radix-tree.c @@ -555,6 +555,10 @@ EXPORT_SYMBOL(radix_tree_tag_clear); * * 0: tag not present or not set * 1: tag set + * + * Note that the return value of this function may not be relied on, even if + * the RCU lock is held, unless tag modification and node deletion are excluded + * from concurrency. */ int radix_tree_tag_get(struct radix_tree_root *root, unsigned long index, unsigned int tag) @@ -595,12 +599,8 @@ int radix_tree_tag_get(struct radix_tree_root *root, */ if (!tag_get(node, tag, offset)) saw_unset_tag = 1; - if (height == 1) { - int ret = tag_get(node, tag, offset); - - BUG_ON(ret && saw_unset_tag); - return !!ret; - } + if (height == 1) + return !!tag_get(node, tag, offset); node = rcu_dereference_raw(node->slots[offset]); shift -= RADIX_TREE_MAP_SHIFT; height--;