From mboxrd@z Thu Jan 1 00:00:00 1970 From: Benjamin Marzinski Date: Tue, 13 Oct 2009 09:49:02 -0500 Subject: [Cluster-devel] [PATCH] GFS2: Improve statfs and quota usability Message-ID: <20091013144902.GE3555@ether.msp.redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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 --- 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_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_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_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_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_spin); *field = x; spin_unlock(>->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,