summaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorPekka Enberg2007-05-06 23:49:03 +0200
committerLinus Torvalds2007-05-07 21:12:51 +0200
commit714b8171af9c930a59a0da8f6fe50518e70ab035 (patch)
treeb63f21c4efd165637c938267d7e542df18d93c99 /mm
parentmm: remove gcc workaround (diff)
downloadkernel-qcow2-linux-714b8171af9c930a59a0da8f6fe50518e70ab035.tar.gz
kernel-qcow2-linux-714b8171af9c930a59a0da8f6fe50518e70ab035.tar.xz
kernel-qcow2-linux-714b8171af9c930a59a0da8f6fe50518e70ab035.zip
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.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/mm/slab.c b/mm/slab.c
index 8b71a9c3daa4..21b2aef25254 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2990,6 +2990,14 @@ retry:
slabp = list_entry(entry, struct slab, list);
check_slabp(cachep, slabp);
check_spinlock_acquired(cachep);
+
+ /*
+ * The slab was either on partial or free list so
+ * there must be at least one object available for
+ * allocation.
+ */
+ BUG_ON(slabp->inuse < 0 || slabp->inuse >= cachep->num);
+
while (slabp->inuse < cachep->num && batchcount--) {
STATS_INC_ALLOCED(cachep);
STATS_INC_ACTIVE(cachep);