aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorManfred Spraul <manfred@colorfullife.com>2008-12-01 13:14:02 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2008-12-05 10:55:13 -0800
commit228d6b8f4ca2c057e9c63559f72af111b4356bd3 (patch)
tree0f2ed69246fd5e46f1c465e76255cd967b58613a /include
parent605f2f6de6dee42c660d8965bf8b96052459afd2 (diff)
lib/idr.c: fix rcu related race with idr_find
commit 6ff2d39b91aec3dcae951afa982059e3dd9b49dc upstream. 2nd part of the fixes needed for http://bugzilla.kernel.org/show_bug.cgi?id=11796. When the idr tree is either grown or shrunk, then the update to the number of layers and the top pointer were not atomic. This race caused crashes. The attached patch fixes that by replicating the layers counter in each layer, thus idr_find doesn't need idp->layers anymore. Signed-off-by: Manfred Spraul <manfred@colorfullife.com> Cc: Clement Calmels <cboulte@gmail.com> Cc: Nadia Derbey <Nadia.Derbey@bull.net> Cc: Pierre Peiffer <peifferp@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'include')
-rw-r--r--include/linux/idr.h3
1 files changed, 2 insertions, 1 deletions
diff --git a/include/linux/idr.h b/include/linux/idr.h
index fa035f96f2a..dd846df8cd3 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -52,13 +52,14 @@ struct idr_layer {
unsigned long bitmap; /* A zero bit means "space here" */
struct idr_layer *ary[1<<IDR_BITS];
int count; /* When zero, we can release it */
+ int layer; /* distance from leaf */
struct rcu_head rcu_head;
};
struct idr {
struct idr_layer *top;
struct idr_layer *id_free;
- int layers;
+ int layers; /* only valid without concurrent changes */
int id_free_cnt;
spinlock_t lock;
};