[Cluster-devel] [PATCH] GFS2: Improve statfs and quota usability

Benjamin Marzinski bmarzins at redhat.com
Tue Oct 13 14:49:02 UTC 2009


GFS2 now has three new mount options, statfs_quantum, quota_quantum and
statfs_percent.  statfs_quantum and quota_quantum simply allow you to set the
tunables of the same name.  Setting setting statfs_quantum to 0 will
also turn on the statfs_slow tunable.  statfs_percent is both a mount option
and a tunable.  It accepts an integer between 0 and 100.  Numbers between 1 and 
100 will cause GFS2 to do any early sync when the local number of blocks free
changes by at least statfs_percent from the totoal number of blocks free.
Setting statfs_percent to 0 disables this.

Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
---
 fs/gfs2/incore.h     |    5 ++++
 fs/gfs2/ops_fstype.c |   15 ++++++++++---
 fs/gfs2/quota.c      |   21 ++++++++++++++++---
 fs/gfs2/quota.h      |    2 +
 fs/gfs2/super.c      |   56 +++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/gfs2/sys.c        |   33 +++++++++++++++++-------------
 6 files changed, 112 insertions(+), 20 deletions(-)

Index: gfs2-2.6-nmw/fs/gfs2/incore.h
===================================================================
--- gfs2-2.6-nmw.orig/fs/gfs2/incore.h
+++ gfs2-2.6-nmw/fs/gfs2/incore.h
@@ -430,6 +430,9 @@ struct gfs2_args {
 	unsigned int ar_discard:1;		/* discard requests */
 	unsigned int ar_errors:2;               /* errors=withdraw | panic */
 	int ar_commit;				/* Commit interval */
+	int ar_statfs_quantum;			/* The fast statfs interval */
+	int ar_quota_quantum;			/* The quota interval */
+	int ar_statfs_percent;			/* The % change to force sync */
 };
 
 struct gfs2_tune {
@@ -451,6 +454,7 @@ struct gfs2_tune {
 	unsigned int gt_complain_secs;
 	unsigned int gt_statfs_quantum;
 	unsigned int gt_statfs_slow;
+	unsigned int gt_statfs_percent;
 };
 
 enum {
@@ -558,6 +562,7 @@ struct gfs2_sbd {
 	spinlock_t sd_statfs_spin;
 	struct gfs2_statfs_change_host sd_statfs_master;
 	struct gfs2_statfs_change_host sd_statfs_local;
+	int sd_statfs_force_sync;
 
 	/* Resource group stuff */
 
Index: gfs2-2.6-nmw/fs/gfs2/ops_fstype.c
===================================================================
--- gfs2-2.6-nmw.orig/fs/gfs2/ops_fstype.c
+++ gfs2-2.6-nmw/fs/gfs2/ops_fstype.c
@@ -63,13 +63,10 @@ static void gfs2_tune_init(struct gfs2_t
 	gt->gt_quota_warn_period = 10;
 	gt->gt_quota_scale_num = 1;
 	gt->gt_quota_scale_den = 1;
-	gt->gt_quota_quantum = 60;
 	gt->gt_new_files_jdata = 0;
 	gt->gt_max_readahead = 1 << 18;
 	gt->gt_stall_secs = 600;
 	gt->gt_complain_secs = 10;
-	gt->gt_statfs_quantum = 30;
-	gt->gt_statfs_slow = 0;
 }
 
 static struct gfs2_sbd *init_sbd(struct super_block *sb)
@@ -1153,6 +1150,16 @@ static int fill_super(struct super_block
 	sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
 
 	sdp->sd_tune.gt_log_flush_secs = sdp->sd_args.ar_commit;
+	sdp->sd_tune.gt_quota_quantum = sdp->sd_args.ar_quota_quantum;
+	if (sdp->sd_args.ar_statfs_quantum) {
+		sdp->sd_tune.gt_statfs_slow = 0;
+		sdp->sd_tune.gt_statfs_quantum = sdp->sd_args.ar_statfs_quantum;
+	}
+	else {
+		sdp->sd_tune.gt_statfs_slow = 1;
+		sdp->sd_tune.gt_statfs_quantum = 30;
+	}
+	sdp->sd_tune.gt_statfs_percent = sdp->sd_args.ar_statfs_percent;
 
 	error = init_names(sdp, silent);
 	if (error)
@@ -1308,6 +1315,8 @@ static int gfs2_get_sb(struct file_syste
 	args.ar_quota = GFS2_QUOTA_DEFAULT;
 	args.ar_data = GFS2_DATA_DEFAULT;
 	args.ar_commit = 60;
+	args.ar_statfs_quantum = 30;
+	args.ar_quota_quantum = 60;
 	args.ar_errors = GFS2_ERRORS_DEFAULT;
 
 	error = gfs2_mount_args(&args, data);
Index: gfs2-2.6-nmw/fs/gfs2/super.c
===================================================================
--- gfs2-2.6-nmw.orig/fs/gfs2/super.c
+++ gfs2-2.6-nmw/fs/gfs2/super.c
@@ -70,6 +70,9 @@ enum {
 	Opt_commit,
 	Opt_err_withdraw,
 	Opt_err_panic,
+	Opt_statfs_quantum,
+	Opt_statfs_percent,
+	Opt_quota_quantum,
 	Opt_error,
 };
 
@@ -101,6 +104,9 @@ static const match_table_t tokens = {
 	{Opt_commit, "commit=%d"},
 	{Opt_err_withdraw, "errors=withdraw"},
 	{Opt_err_panic, "errors=panic"},
+	{Opt_statfs_quantum, "statfs_quantum=%d"},
+	{Opt_statfs_percent, "statfs_percent=%d"},
+	{Opt_quota_quantum, "quota_quantum=%d"},
 	{Opt_error, NULL}
 };
 
@@ -214,6 +220,28 @@ int gfs2_mount_args(struct gfs2_args *ar
 				return rv ? rv : -EINVAL;
 			}
 			break;
+		case Opt_statfs_quantum:
+			rv = match_int(&tmp[0], &args->ar_statfs_quantum);
+			if (rv || args->ar_statfs_quantum < 0) {
+				printk(KERN_WARNING "GFS2: statfs_quantum mount option requires a non-negative numeric argument\n");
+				return rv ? rv : -EINVAL;
+			}
+			break;
+		case Opt_quota_quantum:
+			rv = match_int(&tmp[0], &args->ar_quota_quantum);
+			if (rv || args->ar_quota_quantum <= 0) {
+				printk(KERN_WARNING "GFS2: quota_quantum mount option requires a positive numeric argument\n");
+				return rv ? rv : -EINVAL;
+			}
+			break;
+		case Opt_statfs_percent:
+			rv = match_int(&tmp[0], &args->ar_statfs_percent);
+			if (rv || args->ar_statfs_percent < 0 ||
+			    args->ar_statfs_percent > 100) {
+				printk(KERN_WARNING "statfs_percent mount option requires a numeric argument between 0 and 100\n");
+				return rv ? rv : -EINVAL;
+			}
+			break;
 		case Opt_err_withdraw:
 			args->ar_errors = GFS2_ERRORS_WITHDRAW;
 			break;
@@ -442,7 +470,9 @@ void gfs2_statfs_change(struct gfs2_sbd 
 {
 	struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
 	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+	struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
 	struct buffer_head *l_bh;
+	int percent, sync_percent;
 	int error;
 
 	error = gfs2_meta_inode_buffer(l_ip, &l_bh);
@@ -456,9 +486,17 @@ void gfs2_statfs_change(struct gfs2_sbd 
 	l_sc->sc_free += free;
 	l_sc->sc_dinodes += dinodes;
 	gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode));
+	if (m_sc->sc_free)
+		percent = (100 * l_sc->sc_free) / m_sc->sc_free;
+	else
+		percent = 100;
 	spin_unlock(&sdp->sd_statfs_spin);
 
 	brelse(l_bh);
+	sync_percent = gfs2_tune_get(sdp, gt_statfs_percent);
+	if (sync_percent && (percent >= sync_percent ||
+			     percent <= -sync_percent))
+		gfs2_wake_up_statfs(sdp);
 }
 
 void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
@@ -522,6 +560,7 @@ int gfs2_statfs_sync(struct super_block 
 		goto out_bh2;
 
 	update_statfs(sdp, m_bh, l_bh);
+	sdp->sd_statfs_force_sync = 0;
 
 	gfs2_trans_end(sdp);
 
@@ -1062,6 +1101,12 @@ static int gfs2_remount_fs(struct super_
 
 	spin_lock(&gt->gt_spin);
 	args.ar_commit = gt->gt_log_flush_secs;
+	args.ar_quota_quantum = gt->gt_quota_quantum;
+	if (gt->gt_statfs_slow)
+		args.ar_statfs_quantum = 0;
+	else
+		args.ar_statfs_quantum = gt->gt_statfs_quantum;
+	args.ar_statfs_percent = gt->gt_statfs_percent;
 	spin_unlock(&gt->gt_spin);
 	error = gfs2_mount_args(&args, data);
 	if (error)
@@ -1100,6 +1145,17 @@ static int gfs2_remount_fs(struct super_
 		sb->s_flags &= ~MS_POSIXACL;
 	spin_lock(&gt->gt_spin);
 	gt->gt_log_flush_secs = args.ar_commit;
+	gt->gt_statfs_quantum = args.ar_statfs_quantum;
+	gt->gt_quota_quantum = args.ar_quota_quantum;
+	if (args.ar_statfs_quantum) {
+		gt->gt_statfs_slow = 0;
+		gt->gt_statfs_quantum = args.ar_statfs_quantum;
+	}
+	else {
+		gt->gt_statfs_slow = 1;
+		gt->gt_statfs_quantum = 30;
+	}
+	gt->gt_statfs_percent = args.ar_statfs_percent;
 	spin_unlock(&gt->gt_spin);
 
 	gfs2_online_uevent(sdp);
Index: gfs2-2.6-nmw/fs/gfs2/quota.c
===================================================================
--- gfs2-2.6-nmw.orig/fs/gfs2/quota.c
+++ gfs2-2.6-nmw/fs/gfs2/quota.c
@@ -1336,6 +1336,14 @@ static void quotad_check_trunc_list(stru
 	}
 }
 
+void gfs2_wake_up_statfs(struct gfs2_sbd *sdp) {
+	if (!sdp->sd_statfs_force_sync) {
+		sdp->sd_statfs_force_sync = 1;
+		wake_up(&sdp->sd_quota_wait);
+	}
+}
+
+
 /**
  * gfs2_quotad - Write cached quota changes into the quota file
  * @sdp: Pointer to GFS2 superblock
@@ -1355,8 +1363,15 @@ int gfs2_quotad(void *data)
 	while (!kthread_should_stop()) {
 
 		/* Update the master statfs file */
-		quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t,
-				   &statfs_timeo, &tune->gt_statfs_quantum);
+		if (sdp->sd_statfs_force_sync) {
+			int error = gfs2_statfs_sync(sdp->sd_vfs, 0);
+			quotad_error(sdp, "statfs", error);
+			statfs_timeo = gfs2_tune_get(sdp, gt_statfs_quantum) * HZ;
+		}
+		else
+			quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t,
+				   	   &statfs_timeo,
+					   &tune->gt_statfs_quantum);
 
 		/* Update quota file */
 		quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t,
@@ -1373,7 +1388,7 @@ int gfs2_quotad(void *data)
 		spin_lock(&sdp->sd_trunc_lock);
 		empty = list_empty(&sdp->sd_trunc_list);
 		spin_unlock(&sdp->sd_trunc_lock);
-		if (empty)
+		if (empty && !sdp->sd_statfs_force_sync)
 			t -= schedule_timeout(t);
 		else
 			t = 0;
Index: gfs2-2.6-nmw/fs/gfs2/quota.h
===================================================================
--- gfs2-2.6-nmw.orig/fs/gfs2/quota.h
+++ gfs2-2.6-nmw/fs/gfs2/quota.h
@@ -32,6 +32,8 @@ extern int gfs2_quota_init(struct gfs2_s
 extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
 extern int gfs2_quotad(void *data);
 
+extern void gfs2_wake_up_statfs(struct gfs2_sbd *sdp);
+
 static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
Index: gfs2-2.6-nmw/fs/gfs2/sys.c
===================================================================
--- gfs2-2.6-nmw.orig/fs/gfs2/sys.c
+++ gfs2-2.6-nmw/fs/gfs2/sys.c
@@ -437,7 +437,7 @@ static ssize_t quota_scale_store(struct 
 }
 
 static ssize_t tune_set(struct gfs2_sbd *sdp, unsigned int *field,
-			int check_zero, const char *buf, size_t len)
+			int check_zero, int max, const char *buf, size_t len)
 {
 	struct gfs2_tune *gt = &sdp->sd_tune;
 	unsigned int x;
@@ -450,6 +450,9 @@ static ssize_t tune_set(struct gfs2_sbd 
 	if (check_zero && !x)
 		return -EINVAL;
 
+	if (max && x > max)
+		return -EINVAL;
+
 	spin_lock(&gt->gt_spin);
 	*field = x;
 	spin_unlock(&gt->gt_spin);
@@ -466,24 +469,25 @@ static ssize_t name##_show(struct gfs2_s
 }                                                                             \
 TUNE_ATTR_3(name, name##_show, store)
 
-#define TUNE_ATTR(name, check_zero)                                           \
+#define TUNE_ATTR(name, chk_zero, max)                                        \
 static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
 {                                                                             \
-	return tune_set(sdp, &sdp->sd_tune.gt_##name, check_zero, buf, len);  \
+	return tune_set(sdp, &sdp->sd_tune.gt_##name, chk_zero, max, buf, len);\
 }                                                                             \
 TUNE_ATTR_2(name, name##_store)
 
-TUNE_ATTR(incore_log_blocks, 0);
-TUNE_ATTR(log_flush_secs, 0);
-TUNE_ATTR(quota_warn_period, 0);
-TUNE_ATTR(quota_quantum, 0);
-TUNE_ATTR(max_readahead, 0);
-TUNE_ATTR(complain_secs, 0);
-TUNE_ATTR(statfs_slow, 0);
-TUNE_ATTR(new_files_jdata, 0);
-TUNE_ATTR(quota_simul_sync, 1);
-TUNE_ATTR(stall_secs, 1);
-TUNE_ATTR(statfs_quantum, 1);
+TUNE_ATTR(incore_log_blocks, 0, 0);
+TUNE_ATTR(log_flush_secs, 0, 0);
+TUNE_ATTR(quota_warn_period, 0, 0);
+TUNE_ATTR(quota_quantum, 0, 0);
+TUNE_ATTR(max_readahead, 0, 0);
+TUNE_ATTR(complain_secs, 0, 0);
+TUNE_ATTR(statfs_slow, 0, 0);
+TUNE_ATTR(new_files_jdata, 0, 0);
+TUNE_ATTR(quota_simul_sync, 1, 0);
+TUNE_ATTR(stall_secs, 1, 0);
+TUNE_ATTR(statfs_quantum, 1, 0);
+TUNE_ATTR(statfs_percent, 0, 100);
 TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
 
 static struct attribute *tune_attrs[] = {
@@ -497,6 +501,7 @@ static struct attribute *tune_attrs[] = 
 	&tune_attr_quota_simul_sync.attr,
 	&tune_attr_stall_secs.attr,
 	&tune_attr_statfs_quantum.attr,
+	&tune_attr_statfs_percent.attr,
 	&tune_attr_quota_scale.attr,
 	&tune_attr_new_files_jdata.attr,
 	NULL,




More information about the Cluster-devel mailing list