[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] [GFS2] Reduce meta inodes to one per fs



>From f030a5ef7df90484a41fa68609f7f2ad1849a47b Mon Sep 17 00:00:00 2001
From: Steven Whitehouse <swhiteho redhat com>
Date: Wed, 12 Dec 2007 16:01:09 +0000
Subject: [PATCH] [GFS2] Reduce meta inodes to one per fs

Now that the previous patches have laid the groundwork, this
patch is the one which actually reduces the meta inodes to
a single one per filesystem.

As a result we save:
  - The space of one gfs2_inode per "real" inode (about 1800 bytes on x86_64,
    just over 1k on x86)
  - Whenever we have block size < page size and lots of metadata we save on
    wasted space in the page cache

Signed-off-by: Steven Whitehouse <swhiteho redhat com>

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 52c8a09..d18f00c 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -181,13 +181,9 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp,
 static void glock_free(struct gfs2_glock *gl)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
-	struct inode *aspace = gl->gl_aspace;
 
 	gfs2_lm_put_lock(sdp, gl->gl_lock);
 
-	if (aspace)
-		gfs2_aspace_put(aspace);
-
 	kmem_cache_free(gfs2_glock_cachep, gl);
 }
 
@@ -344,23 +340,12 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	gl->gl_tchange = jiffies;
 	gl->gl_object = NULL;
 	gl->gl_sbd = sdp;
-	gl->gl_aspace = NULL;
 	INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
 	gl->gl_start = gl->gl_end = number;
 
-	/* If this glock protects actual on-disk data or metadata blocks,
-	   create a VFS inode to manage the pages/buffers holding them. */
-	if (glops == &gfs2_inode_glops || glops == &gfs2_rgrp_glops) {
-		gl->gl_aspace = gfs2_aspace_get(sdp);
-		if (!gl->gl_aspace) {
-			error = -ENOMEM;
-			goto fail;
-		}
-	}
-
 	error = gfs2_lm_get_lock(sdp, &name, &gl->gl_lock);
 	if (error)
-		goto fail_aspace;
+		goto fail;
 
 	write_lock(gl_lock_addr(hash));
 	tmp = search_bucket(hash, sdp, &name);
@@ -377,9 +362,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 
 	return 0;
 
-fail_aspace:
-	if (gl->gl_aspace)
-		gfs2_aspace_put(gl->gl_aspace);
 fail:
 	kmem_cache_free(gfs2_glock_cachep, gl);
 	return error;
@@ -1894,11 +1876,6 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
 	print_dbg(gi, "  object = %s\n", (gl->gl_object) ? "yes" : "no");
 	print_dbg(gi, "  reclaim = %s\n",
 		   (list_empty(&gl->gl_reclaim)) ? "no" : "yes");
-	if (gl->gl_aspace)
-		print_dbg(gi, "  aspace = 0x%p nrpages = %lu\n", gl->gl_aspace,
-			   gl->gl_aspace->i_mapping->nrpages);
-	else
-		print_dbg(gi, "  aspace = no\n");
 	print_dbg(gi, "  ail = %d\n", atomic_read(&gl->gl_ail_count));
 	if (gl->gl_req_gh) {
 		error = dump_holder(gi, "Request", gl->gl_req_gh);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 26640c1..98abc83 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -91,8 +91,8 @@ static int gfs2_wait_on_meta_pages(struct buffer_head *bh)
 static void gfs2_foreach_page(struct gfs2_glock *gl,
 			      int (*fxn)(struct buffer_head *bh))
 {
-	struct address_space *mapping = gl->gl_aspace->i_mapping;
 	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct address_space *mapping = sdp->sd_meta->i_mapping;
 	unsigned shift = PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift;
 	pgoff_t start = (pgoff_t)(gl->gl_start >> shift);
 	pgoff_t end = (pgoff_t)(gl->gl_end >> shift);
@@ -157,8 +157,8 @@ do_writepage:
 
 static int gfs2_meta_sync(struct gfs2_glock *gl)
 {
-	struct address_space *mapping = gl->gl_aspace->i_mapping;
 	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct address_space *mapping = sdp->sd_meta->i_mapping;
 	struct writeback_control wbc = {
 		.sync_mode = WB_SYNC_ALL,
 		.nr_to_write = LONG_MAX,
@@ -183,8 +183,7 @@ static int gfs2_meta_sync(struct gfs2_glock *gl)
 static void meta_go_sync(struct gfs2_glock *gl)
 {
 	gfs2_log_flush(gl->gl_sbd, gl);
-	if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
-		gfs2_meta_sync(gl);
+	gfs2_meta_sync(gl);
 	gfs2_ail_empty_gl(gl);
 }
 
@@ -215,12 +214,8 @@ static void inode_go_sync(struct gfs2_glock *gl)
 	if (ip && S_ISREG(ip->i_inode.i_mode)) {
 		struct inode *inode = &ip->i_inode;
 		struct address_space *mapping = inode->i_mapping;
-		int mapped = mapping->i_mmap_writable;
 		unmap_shared_mapping_range(mapping, 0, 0);
-		if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags) || mapped) {
-			generic_osync_inode(inode, mapping,
-					    OSYNC_DATA|OSYNC_METADATA);
-		}
+		generic_osync_inode(inode, mapping, OSYNC_DATA|OSYNC_METADATA);
 	} else {
 		gfs2_meta_sync(gl);
 	}
@@ -281,7 +276,7 @@ static int inode_go_demote_ok(struct gfs2_glock *gl)
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	int demote = 0;
 
-	if (!gl->gl_object && !gl->gl_aspace->i_mapping->nrpages)
+	if (!gl->gl_object)
 		demote = 1;
 	else if (!sdp->sd_args.ar_localcaching &&
 		 time_after_eq(jiffies, gl->gl_stamp +
@@ -331,7 +326,13 @@ static int inode_go_lock(struct gfs2_holder *gh)
 
 static int rgrp_go_demote_ok(struct gfs2_glock *gl)
 {
-	return !gl->gl_aspace->i_mapping->nrpages;
+	struct gfs2_sbd *sdp = gl->gl_sbd;
+
+	if (!sdp->sd_args.ar_localcaching &&
+                 time_after_eq(jiffies, gl->gl_stamp +
+                               gfs2_tune_get(sdp, gt_demote_secs) * HZ))
+		return 1;
+	return 0;
 }
 
 /**
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index f478e8b..8ab0563 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -203,7 +203,6 @@ enum {
 	GLF_STICKY		= 2,
 	GLF_DEMOTE		= 3,
 	GLF_PENDING_DEMOTE	= 4,
-	GLF_DIRTY		= 5,
 	GLF_DEMOTE_IN_PROGRESS	= 6,
 	GLF_LFLUSH		= 7,
 };
@@ -245,7 +244,6 @@ struct gfs2_glock {
 
 	struct gfs2_sbd *gl_sbd;
 
-	struct inode *gl_aspace;
 	struct list_head gl_ail_list;
 	atomic_t gl_ail_count;
 	struct delayed_work gl_work;
@@ -557,6 +555,7 @@ struct gfs2_sbd {
 	struct inode *sd_qc_inode;
 	struct inode *sd_rindex;
 	struct inode *sd_quota_inode;
+	struct inode *sd_meta;
 
 	/* Inum stuff */
 
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 58e51ef..86118eb 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -147,7 +147,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
 	if (!list_empty(&le->le_list))
 		goto out;
 	set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
-	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
 	gfs2_meta_check(sdp, bd->bd_bh);
 	gfs2_pin(sdp, bd->bd_bh);
 	sdp->sd_log_num_buf++;
@@ -527,7 +526,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
 		goto out;
 
 	set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
-	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
 	if (gfs2_is_jdata(ip)) {
 		gfs2_pin(sdp, bd->bd_bh);
 		tr->tr_num_databuf_new++;
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 1cf711f..1451a4b 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -98,8 +98,8 @@ void gfs2_aspace_put(struct inode *aspace)
 
 static struct buffer_head *getbuf(struct gfs2_glock *gl, u64 blkno, int create)
 {
-	struct address_space *mapping = gl->gl_aspace->i_mapping;
 	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct address_space *mapping = sdp->sd_meta->i_mapping;
 	struct page *page;
 	struct buffer_head *bh;
 	unsigned int shift;
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 35ec630..5558fdf 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -37,6 +37,7 @@
 #include "sys.h"
 #include "util.h"
 #include "log.h"
+#include "meta_io.h"
 
 #define DO 0
 #define UNDO 1
@@ -247,6 +248,10 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
 			dput(sb->s_root);
 			sb->s_root = NULL;
 		}
+		if (sdp->sd_meta) {
+			iput(sdp->sd_meta);
+			sdp->sd_meta = NULL;
+		}
 		return 0;
 	}
 
@@ -280,6 +285,12 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
 	}
 	sb_set_blocksize(sb, sdp->sd_sb.sb_bsize);
 
+	sdp->sd_meta = gfs2_aspace_get(sdp);
+	if (sdp->sd_meta == NULL) {
+		error = -ENOMEM;
+		goto out;
+	}
+
 	/* Get the root inode */
 	no_addr = sdp->sd_sb.sb_root_dir.no_addr;
 	if (sb->s_type == &gfs2meta_fs_type)
@@ -288,6 +299,7 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
 	if (IS_ERR(inode)) {
 		error = PTR_ERR(inode);
 		fs_err(sdp, "can't read in root inode: %d\n", error);
+		iput(sdp->sd_meta);
 		goto out;
 	}
 
@@ -295,6 +307,7 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
 	if (!sb->s_root) {
 		fs_err(sdp, "can't get root dentry\n");
 		error = -ENOMEM;
+		iput(sdp->sd_meta);
 		iput(inode);
 	} else
 		sb->s_root->d_op = &gfs2_dops;
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 5e52421..ade8c2e 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -108,6 +108,7 @@ static void gfs2_put_super(struct super_block *sb)
 	iput(sdp->sd_statfs_inode);
 	iput(sdp->sd_rindex);
 	iput(sdp->sd_quota_inode);
+	iput(sdp->sd_meta);
 
 	gfs2_glock_put(sdp->sd_rename_gl);
 	gfs2_glock_put(sdp->sd_trans_gl);
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 2a4d414..b916679 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -147,7 +147,15 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)
 
 	bd = bh_to_bufdata(bh);
 	if (bd) {
-		BUG_ON(bd->bd_gl != gl);
+		if (unlikely(bd->bd_gl != gl)) {
+			BUG_ON(buffer_dirty(bh));
+			BUG_ON(!list_empty(&bd->bd_le.le_list));
+			gfs2_log_lock(sdp);
+			if (bd->bd_ail)
+				gfs2_remove_from_ail(bd);
+			bd->bd_gl = gl;
+			gfs2_log_unlock(sdp);
+		}
 		goto out;
 	}
 
-- 
1.5.1.2




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]