diff options
author | Pekka Enberg <penberg@cs.helsinki.fi> | 2007-05-06 17:49:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-07 15:12:51 -0400 |
commit | 714b8171af9c930a59a0da8f6fe50518e70ab035 (patch) | |
tree | b63f21c4efd165637c938267d7e542df18d93c99 /mm | |
parent | 5f22df00a009e3f86301366c0ecddb63ebd22af9 (diff) |
slab: ensure cache_alloc_refill terminates
If slab->inuse is corrupted, cache_alloc_refill can enter an infinite
loop as detailed by Michael Richardson in the following post:
<http://lkml.org/lkml/2007/2/16/292>. This adds a BUG_ON to catch
those cases.
Cc: Michael Richardson <mcr@sandelman.ca>
Acked-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/slab.c | 8 |
1 files changed, 8 insertions, 0 deletions
@@ -2990,6 +2990,14 @@ retry: | |||
2990 | slabp = list_entry(entry, struct slab, list); | 2990 | slabp = list_entry(entry, struct slab, list); |
2991 | check_slabp(cachep, slabp); | 2991 | check_slabp(cachep, slabp); |
2992 | check_spinlock_acquired(cachep); | 2992 | check_spinlock_acquired(cachep); |
2993 | |||
2994 | /* | ||
2995 | * The slab was either on partial or free list so | ||
2996 | * there must be at least one object available for | ||
2997 | * allocation. | ||
2998 | */ | ||
2999 | BUG_ON(slabp->inuse < 0 || slabp->inuse >= cachep->num); | ||
3000 | |||
2993 | while (slabp->inuse < cachep->num && batchcount--) { | 3001 | while (slabp->inuse < cachep->num && batchcount--) { |
2994 | STATS_INC_ALLOCED(cachep); | 3002 | STATS_INC_ALLOCED(cachep); |
2995 | STATS_INC_ACTIVE(cachep); | 3003 | STATS_INC_ACTIVE(cachep); |