login
Header Space

 
 

[patch 10/21] buffer heads: Support slab defrag

Score:
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: <akpm@...>
Cc: <linux-kernel@...>, <linux-fsdevel@...>, Mel Gorman <mel@...>, <andi@...>, Rik van Riel <riel@...>, Pekka Enberg <penberg@...>, <mpm@...>
Date: Friday, May 9, 2008 - 11:08 pm

Defragmentation support for buffer heads. We convert the references to
buffers to struct page references and try to remove the buffers from
those pages. If the pages are dirty then trigger writeout so that the
buffer heads can be removed later.

Reviewed-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Christoph Lameter <clameter@sgi.com>
---
 fs/buffer.c |   99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

Index: linux-2.6/fs/buffer.c
===================================================================
--- linux-2.6.orig/fs/buffer.c	2008-05-07 20:27:15.182659486 -0700
+++ linux-2.6/fs/buffer.c	2008-05-07 20:29:13.052102980 -0700
@@ -3255,6 +3255,104 @@ int bh_submit_read(struct buffer_head *b
 }
 EXPORT_SYMBOL(bh_submit_read);
 
+/*
+ * Writeback a page to clean the dirty state
+ */
+static void trigger_write(struct page *page)
+{
+	struct address_space *mapping = page_mapping(page);
+	int rc;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_NONE,
+		.nr_to_write = 1,
+		.range_start = 0,
+		.range_end = LLONG_MAX,
+		.nonblocking = 1,
+		.for_reclaim = 0
+	};
+
+	if (!mapping->a_ops->writepage)
+		/* No write method for the address space */
+		return;
+
+	if (!clear_page_dirty_for_io(page))
+		/* Someone else already triggered a write */
+		return;
+
+	rc = mapping->a_ops->writepage(page, &wbc);
+	if (rc < 0)
+		/* I/O Error writing */
+		return;
+
+	if (rc == AOP_WRITEPAGE_ACTIVATE)
+		unlock_page(page);
+}
+
+/*
+ * 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.
+ */
+static void *get_buffers(struct kmem_cache *s, int nr, void **v)
+{
+	struct page *page;
+	struct buffer_head *bh;
+	int i, j;
+	int n = 0;
+
+	for (i = 0; i < nr; i++) {
+		bh = v[i];
+		v[i] = NULL;
+
+		page = bh->b_page;
+
+		if (page && PagePrivate(page)) {
+			for (j = 0; j < n; j++)
+				if (page == v[j])
+					continue;
+		}
+
+		if (get_page_unless_zero(page))
+			v[n++] = page;
+	}
+	return NULL;
+}
+
+/*
+ * Despite its name: kick_buffers operates on a list of pointers to
+ * page structs that was set up 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 || PageWriteback(page))
+			continue;
+
+		if (!TestSetPageLocked(page)) {
+			if (PageDirty(page))
+				trigger_write(page);
+			else {
+				if (PagePrivate(page))
+					try_to_free_buffers(page);
+				unlock_page(page);
+			}
+		}
+		put_page(page);
+	}
+}
+
 static void
 init_buffer_head(struct kmem_cache *cachep, void *data)
 {
@@ -3273,6 +3371,7 @@ void __init buffer_init(void)
 				(SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
 				SLAB_MEM_SPREAD),
 				init_buffer_head);
+	kmem_cache_setup_defrag(bh_cachep, get_buffers, kick_buffers);
 
 	/*
 	 * Limit the bh occupancy to 10% of ZONE_NORMAL

-- 
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[patch 10/21] buffer heads: Support slab defrag, Christoph Lameter, (Fri May 9, 11:08 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, David Chinner, (Sun May 11, 8:24 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Christoph Lameter, (Thu May 15, 1:42 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, David Chinner, (Thu May 15, 7:10 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Christoph Lameter, (Fri May 16, 1:01 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, David Chinner, (Mon May 19, 1:45 am)
Re: [patch 10/21] buffer heads: Support slab defrag, Jamie Lokier, (Tue May 20, 6:53 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Christoph Lameter, (Mon May 19, 12:44 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, David Chinner, (Mon May 19, 8:25 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Evgeniy Polyakov, (Tue May 20, 2:56 am)
Re: [patch 10/21] buffer heads: Support slab defrag, David Chinner, (Tue May 20, 5:46 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Evgeniy Polyakov, (Tue May 20, 6:25 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Evgeniy Polyakov, (Tue May 20, 7:22 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Christoph Lameter, (Tue May 20, 9:56 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, David Chinner, (Tue May 20, 7:30 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Evgeniy Polyakov, (Wed May 21, 2:20 am)
Re: [patch 10/21] buffer heads: Support slab defrag, David Chinner, (Tue May 20, 7:19 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Andrew Morton, (Tue May 20, 7:28 pm)
Re: [patch 10/21] buffer heads: Support slab defrag, Evgeniy Polyakov, (Wed May 21, 2:15 am)
Re: [patch 10/21] buffer heads: Support slab defrag, Andrew Morton, (Wed May 21, 2:24 am)
iput() in reclaim context, Hugh Dickins, (Wed May 21, 1:52 pm)
Re: iput() in reclaim context, Andrew Morton, (Wed May 21, 2:12 pm)
Re: iput() in reclaim context, Evgeniy Polyakov, (Wed May 21, 1:58 pm)
speck-geostationary