slab: Avoid fragmentation During free_block we unconditionally put a block at the end of the partial list. This was done to insure that there is maximum time for the other entries in the slab to be freed. If we would leave the slab at the beginning of the partial list if there are only a few free entries then the slab has more of a chance to get back onto the fully used list. The partial slabs already on the partial list have therefore more chances of getting all their objects freed. Signed-off-by: Christoph Lameter Index: linux-2.6.18-rc3/mm/slab.c =================================================================== --- linux-2.6.18-rc3.orig/mm/slab.c 2006-08-03 22:44:16.879298921 -0700 +++ linux-2.6.18-rc3/mm/slab.c 2006-08-03 22:51:02.708671592 -0700 @@ -3134,11 +3134,21 @@ static void free_block(struct kmem_cache list_add(&slabp->list, &l3->slabs_free); } } else { - /* Unconditionally move a slab to the end of the - * partial list on free - maximum time for the - * other objects to be freed, too. + /* + * Move slab to the end of the list if the number + * of allocated objects is low to increase the + * likelyhood of freeing the rest. + * + * If the number of allocated objects is high then + * we want this at the start of the list in order + * to fill the slab up again. + * + * This help to reduce fragmentation. */ - list_add_tail(&slabp->list, &l3->slabs_partial); + if (cachep->num - slabp->inuse <= cachep->num / 4) + list_add(&slabp->list, &l3->slabs_partial); + else + list_add_tail(&slabp->list, &l3->slabs_partial); } } }