aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSonny Rao <sonny@burdell.org>2006-06-25 08:49:34 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 13:01:26 -0400
commit1eec00565d849ceda67f425e089c3233e3ef2ca2 (patch)
tree83f5bb133755ddde28772e64b99ff0cfd701f0d7
parenta45219483e2894af3c07f959cbd4edb4575b4f8c (diff)
[PATCH] fix race in idr code
I ran into a bug where the kernel died in the idr code: cpu 0x1d: Vector: 300 (Data Access) at [c000000b7096f710] pc: c0000000001f8984: .idr_get_new_above_int+0x140/0x330 lr: c0000000001f89b4: .idr_get_new_above_int+0x170/0x330 sp: c000000b7096f990 msr: 800000000000b032 dar: 0 dsisr: 40010000 current = 0xc000000b70d43830 paca = 0xc000000000556900 pid = 2022, comm = hwup 1d:mon> t [c000000b7096f990] c0000000000d2ad8 .expand_files+0x2e8/0x364 (unreliable) [c000000b7096faa0] c0000000001f8bf8 .idr_get_new_above+0x18/0x68 [c000000b7096fb20] c00000000002a054 .init_new_context+0x5c/0xf0 [c000000b7096fbc0] c000000000049dc8 .copy_process+0x91c/0x1404 [c000000b7096fcd0] c00000000004a988 .do_fork+0xd8/0x224 [c000000b7096fdc0] c00000000000ebdc .sys_clone+0x5c/0x74 [c000000b7096fe30] c000000000008950 .ppc_clone+0x8/0xc
-rw-r--r--lib/idr.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/lib/idr.c b/lib/idr.c
index d226259c3c28..de19030a999b 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -48,15 +48,21 @@ static struct idr_layer *alloc_layer(struct idr *idp)
48 return(p); 48 return(p);
49} 49}
50 50
51/* only called when idp->lock is held */
52static void __free_layer(struct idr *idp, struct idr_layer *p)
53{
54 p->ary[0] = idp->id_free;
55 idp->id_free = p;
56 idp->id_free_cnt++;
57}
58
51static void free_layer(struct idr *idp, struct idr_layer *p) 59static void free_layer(struct idr *idp, struct idr_layer *p)
52{ 60{
53 /* 61 /*
54 * Depends on the return element being zeroed. 62 * Depends on the return element being zeroed.
55 */ 63 */
56 spin_lock(&idp->lock); 64 spin_lock(&idp->lock);
57 p->ary[0] = idp->id_free; 65 __free_layer(idp, p);
58 idp->id_free = p;
59 idp->id_free_cnt++;
60 spin_unlock(&idp->lock); 66 spin_unlock(&idp->lock);
61} 67}
62 68
@@ -184,12 +190,14 @@ build_up:
184 * The allocation failed. If we built part of 190 * The allocation failed. If we built part of
185 * the structure tear it down. 191 * the structure tear it down.
186 */ 192 */
193 spin_lock(&idp->lock);
187 for (new = p; p && p != idp->top; new = p) { 194 for (new = p; p && p != idp->top; new = p) {
188 p = p->ary[0]; 195 p = p->ary[0];
189 new->ary[0] = NULL; 196 new->ary[0] = NULL;
190 new->bitmap = new->count = 0; 197 new->bitmap = new->count = 0;
191 free_layer(idp, new); 198 __free_layer(idp, new);
192 } 199 }
200 spin_unlock(&idp->lock);
193 return -1; 201 return -1;
194 } 202 }
195 new->ary[0] = p; 203 new->ary[0] = p;