From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756262AbXGHDL0 (ORCPT ); Sat, 7 Jul 2007 23:11:26 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756267AbXGHDJR (ORCPT ); Sat, 7 Jul 2007 23:09:17 -0400 Received: from netops-testserver-3-out.sgi.com ([192.48.171.28]:47697 "EHLO relay.sgi.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755158AbXGHDIq (ORCPT ); Sat, 7 Jul 2007 23:08:46 -0400 Message-Id: <20070708030845.032023558@sgi.com> References: <20070708030538.729027694@sgi.com> User-Agent: quilt/0.46-1 Date: Sat, 07 Jul 2007 20:05:45 -0700 From: Christoph Lameter To: akpm@linux-foundation.org Cc: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org Cc: dgc@sgi.com Subject: [patch 07/12] Slab defragmentation: Support for buffer_head defrag Content-Disposition: inline; filename=slub_defrag_buffer_heads Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Limited defragmentation support for buffer heads. Simply try to free the buffers in a sparsely populated slab page. Signed-off-by: Christoph Lameter --- fs/buffer.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) Index: linux-2.6.22-rc6-mm1/fs/buffer.c =================================================================== --- linux-2.6.22-rc6-mm1.orig/fs/buffer.c 2007-07-04 11:14:01.000000000 -0700 +++ linux-2.6.22-rc6-mm1/fs/buffer.c 2007-07-04 17:23:02.000000000 -0700 @@ -3078,12 +3078,75 @@ static int buffer_cpu_notify(struct noti return NOTIFY_OK; } +/* + * Get references on buffers. + * + * We obtain references on the page that uses the buffer. v[i] will point to + * the corresponding page after get_buffers() is through. + * + * We are safe from the underlying page being removed simply by doing + * a get_page_unless_zero. The buffer head removal may race at will. + * try_to_free_buffes will later take appropriate locks to remove the + * buffers if they are still there. + * + * TODO: Write out dirty buffers to increase the chance of kick_buffers + * to be successful. + */ +static void *get_buffers(struct kmem_cache *s, int nr, void **v) +{ + struct page *page; + struct buffer_head *bh; + int i; + + for (i = 0; i < nr; i++) { + bh = v[i]; + page = bh->b_page; + if (page && PagePrivate(page) && get_page_unless_zero(page)) + v[i] = page; + else + v[i] = NULL; + } + return NULL; +} + +/* + * Despite its name: kick_buffers operates on a list of pointers to + * page structs that was setup by get_buffer + */ +static void kick_buffers(struct kmem_cache *s, int nr, void **v, + void *private) +{ + struct page *page; + int i; + + for (i = 0; i < nr; i++) { + page = v[i]; + + if (!page) + continue; + + if (!TestSetPageLocked(page)) { + if (PagePrivate(page)) + try_to_free_buffers(page); + unlock_page(page); + } + put_page(page); + } +} + +static struct kmem_cache_ops buffer_head_kmem_cache_ops = { + .get = get_buffers, + .kick = kick_buffers, +}; + + void __init buffer_init(void) { int nrpages; - bh_cachep = KMEM_CACHE(buffer_head, - SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD); + bh_cachep = KMEM_CACHE_OPS(buffer_head, + SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD, + &buffer_head_kmem_cache_ops); /* * Limit the bh occupancy to 10% of ZONE_NORMAL --