summaryrefslogtreecommitdiffstats
path: root/fs/gfs2/main.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2012-03-08 13:10:23 +0100
committerSteven Whitehouse <swhiteho@redhat.com>2012-03-08 13:10:23 +0100
commit75ca61c101601a7071d93571920be9697b3fda9b (patch)
treeaaf42da2b6086a58d84efd4ef39a312f03cfbefb /fs/gfs2/main.c
parentGFS2: Flush pending glock work when evicting an inode (diff)
downloadlinux-75ca61c101601a7071d93571920be9697b3fda9b.tar.xz
linux-75ca61c101601a7071d93571920be9697b3fda9b.zip
GFS2: Remove a __GFP_NOFAIL allocation
In order to ensure that we've got enough buffer heads for flushing the journal, the orignal code used __GFP_NOFAIL when performing this allocation. Here we dispense with that in favour of using a mempool. This should improve efficiency in low memory conditions since flushing the journal is a good way to get memory back, we don't want to be spinning, waiting on memory allocations. The buffers which are allocated via this mempool are fairly short lived, so that we'll recycle them pretty quickly. Although there are other memory allocations which occur during the journal flush process, this is the one which can potentially require the most memory, so the most important one to fix. The amount of memory reserved is a fixed amount, and we should not need to scale it when there are a greater number of filesystems in use. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/main.c')
-rw-r--r--fs/gfs2/main.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index a8d9bcd0e19c..754426b1e52c 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -17,6 +17,7 @@
#include <linux/rcupdate.h>
#include <linux/rculist_bl.h>
#include <linux/atomic.h>
+#include <linux/mempool.h>
#include "gfs2.h"
#include "incore.h"
@@ -69,6 +70,16 @@ static void gfs2_init_gl_aspace_once(void *foo)
address_space_init_once(mapping);
}
+static void *gfs2_bh_alloc(gfp_t mask, void *data)
+{
+ return alloc_buffer_head(mask);
+}
+
+static void gfs2_bh_free(void *ptr, void *data)
+{
+ return free_buffer_head(ptr);
+}
+
/**
* init_gfs2_fs - Register GFS2 as a filesystem
*
@@ -151,6 +162,10 @@ static int __init init_gfs2_fs(void)
gfs2_control_wq = alloc_workqueue("gfs2_control",
WQ_NON_REENTRANT | WQ_UNBOUND | WQ_FREEZABLE, 0);
if (!gfs2_control_wq)
+ goto fail_recovery;
+
+ gfs2_bh_pool = mempool_create(1024, gfs2_bh_alloc, gfs2_bh_free, NULL);
+ if (!gfs2_bh_pool)
goto fail_control;
gfs2_register_debugfs();
@@ -160,6 +175,8 @@ static int __init init_gfs2_fs(void)
return 0;
fail_control:
+ destroy_workqueue(gfs2_control_wq);
+fail_recovery:
destroy_workqueue(gfs_recovery_wq);
fail_wq:
unregister_filesystem(&gfs2meta_fs_type);
@@ -208,6 +225,7 @@ static void __exit exit_gfs2_fs(void)
rcu_barrier();
+ mempool_destroy(gfs2_bh_pool);
kmem_cache_destroy(gfs2_quotad_cachep);
kmem_cache_destroy(gfs2_rgrpd_cachep);
kmem_cache_destroy(gfs2_bufdata_cachep);