aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2009-10-20 03:39:44 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2009-12-03 06:55:17 -0500
commit3d3c10f2ce80d2a19e5e02023c2b7ab7086c36d5 (patch)
tree56b62b064457596caf66700323ff5aac2320ae93
parent2ec4650526c5a94d96bb760001fe0685b15988de (diff)
GFS2: Improve statfs and quota usability
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 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@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/incore.h4
-rw-r--r--fs/gfs2/ops_fstype.c14
-rw-r--r--fs/gfs2/quota.c21
-rw-r--r--fs/gfs2/quota.h2
-rw-r--r--fs/gfs2/super.c69
5 files changed, 100 insertions, 10 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 6edb423f90b3..c239b0f969c8 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -430,6 +430,9 @@ struct gfs2_args {
430 unsigned int ar_discard:1; /* discard requests */ 430 unsigned int ar_discard:1; /* discard requests */
431 unsigned int ar_errors:2; /* errors=withdraw | panic */ 431 unsigned int ar_errors:2; /* errors=withdraw | panic */
432 int ar_commit; /* Commit interval */ 432 int ar_commit; /* Commit interval */
433 int ar_statfs_quantum; /* The fast statfs interval */
434 int ar_quota_quantum; /* The quota interval */
435 int ar_statfs_percent; /* The % change to force sync */
433}; 436};
434 437
435struct gfs2_tune { 438struct gfs2_tune {
@@ -558,6 +561,7 @@ struct gfs2_sbd {
558 spinlock_t sd_statfs_spin; 561 spinlock_t sd_statfs_spin;
559 struct gfs2_statfs_change_host sd_statfs_master; 562 struct gfs2_statfs_change_host sd_statfs_master;
560 struct gfs2_statfs_change_host sd_statfs_local; 563 struct gfs2_statfs_change_host sd_statfs_local;
564 int sd_statfs_force_sync;
561 565
562 /* Resource group stuff */ 566 /* Resource group stuff */
563 567
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 36b11cba57e3..9744ee920473 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -63,13 +63,10 @@ static void gfs2_tune_init(struct gfs2_tune *gt)
63 gt->gt_quota_warn_period = 10; 63 gt->gt_quota_warn_period = 10;
64 gt->gt_quota_scale_num = 1; 64 gt->gt_quota_scale_num = 1;
65 gt->gt_quota_scale_den = 1; 65 gt->gt_quota_scale_den = 1;
66 gt->gt_quota_quantum = 60;
67 gt->gt_new_files_jdata = 0; 66 gt->gt_new_files_jdata = 0;
68 gt->gt_max_readahead = 1 << 18; 67 gt->gt_max_readahead = 1 << 18;
69 gt->gt_stall_secs = 600; 68 gt->gt_stall_secs = 600;
70 gt->gt_complain_secs = 10; 69 gt->gt_complain_secs = 10;
71 gt->gt_statfs_quantum = 30;
72 gt->gt_statfs_slow = 0;
73} 70}
74 71
75static struct gfs2_sbd *init_sbd(struct super_block *sb) 72static struct gfs2_sbd *init_sbd(struct super_block *sb)
@@ -1153,6 +1150,15 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
1153 sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; 1150 sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
1154 1151
1155 sdp->sd_tune.gt_log_flush_secs = sdp->sd_args.ar_commit; 1152 sdp->sd_tune.gt_log_flush_secs = sdp->sd_args.ar_commit;
1153 sdp->sd_tune.gt_quota_quantum = sdp->sd_args.ar_quota_quantum;
1154 if (sdp->sd_args.ar_statfs_quantum) {
1155 sdp->sd_tune.gt_statfs_slow = 0;
1156 sdp->sd_tune.gt_statfs_quantum = sdp->sd_args.ar_statfs_quantum;
1157 }
1158 else {
1159 sdp->sd_tune.gt_statfs_slow = 1;
1160 sdp->sd_tune.gt_statfs_quantum = 30;
1161 }
1156 1162
1157 error = init_names(sdp, silent); 1163 error = init_names(sdp, silent);
1158 if (error) 1164 if (error)
@@ -1308,6 +1314,8 @@ static int gfs2_get_sb(struct file_system_type *fs_type, int flags,
1308 args.ar_quota = GFS2_QUOTA_DEFAULT; 1314 args.ar_quota = GFS2_QUOTA_DEFAULT;
1309 args.ar_data = GFS2_DATA_DEFAULT; 1315 args.ar_data = GFS2_DATA_DEFAULT;
1310 args.ar_commit = 60; 1316 args.ar_commit = 60;
1317 args.ar_statfs_quantum = 30;
1318 args.ar_quota_quantum = 60;
1311 args.ar_errors = GFS2_ERRORS_DEFAULT; 1319 args.ar_errors = GFS2_ERRORS_DEFAULT;
1312 1320
1313 error = gfs2_mount_args(&args, data); 1321 error = gfs2_mount_args(&args, data);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 1d4fc0413a3f..e3bf6eab8750 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1344,6 +1344,14 @@ static void quotad_check_trunc_list(struct gfs2_sbd *sdp)
1344 } 1344 }
1345} 1345}
1346 1346
1347void gfs2_wake_up_statfs(struct gfs2_sbd *sdp) {
1348 if (!sdp->sd_statfs_force_sync) {
1349 sdp->sd_statfs_force_sync = 1;
1350 wake_up(&sdp->sd_quota_wait);
1351 }
1352}
1353
1354
1347/** 1355/**
1348 * gfs2_quotad - Write cached quota changes into the quota file 1356 * gfs2_quotad - Write cached quota changes into the quota file
1349 * @sdp: Pointer to GFS2 superblock 1357 * @sdp: Pointer to GFS2 superblock
@@ -1363,8 +1371,15 @@ int gfs2_quotad(void *data)
1363 while (!kthread_should_stop()) { 1371 while (!kthread_should_stop()) {
1364 1372
1365 /* Update the master statfs file */ 1373 /* Update the master statfs file */
1366 quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t, 1374 if (sdp->sd_statfs_force_sync) {
1367 &statfs_timeo, &tune->gt_statfs_quantum); 1375 int error = gfs2_statfs_sync(sdp->sd_vfs, 0);
1376 quotad_error(sdp, "statfs", error);
1377 statfs_timeo = gfs2_tune_get(sdp, gt_statfs_quantum) * HZ;
1378 }
1379 else
1380 quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t,
1381 &statfs_timeo,
1382 &tune->gt_statfs_quantum);
1368 1383
1369 /* Update quota file */ 1384 /* Update quota file */
1370 quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t, 1385 quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t,
@@ -1381,7 +1396,7 @@ int gfs2_quotad(void *data)
1381 spin_lock(&sdp->sd_trunc_lock); 1396 spin_lock(&sdp->sd_trunc_lock);
1382 empty = list_empty(&sdp->sd_trunc_list); 1397 empty = list_empty(&sdp->sd_trunc_list);
1383 spin_unlock(&sdp->sd_trunc_lock); 1398 spin_unlock(&sdp->sd_trunc_lock);
1384 if (empty) 1399 if (empty && !sdp->sd_statfs_force_sync)
1385 t -= schedule_timeout(t); 1400 t -= schedule_timeout(t);
1386 else 1401 else
1387 t = 0; 1402 t = 0;
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
index 025d15ba24c0..e271fa07ad02 100644
--- a/fs/gfs2/quota.h
+++ b/fs/gfs2/quota.h
@@ -32,6 +32,8 @@ extern int gfs2_quota_init(struct gfs2_sbd *sdp);
32extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp); 32extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
33extern int gfs2_quotad(void *data); 33extern int gfs2_quotad(void *data);
34 34
35extern void gfs2_wake_up_statfs(struct gfs2_sbd *sdp);
36
35static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) 37static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
36{ 38{
37 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 39 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index e7b24d59d4ff..3fee2fd3ae43 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -70,6 +70,9 @@ enum {
70 Opt_commit, 70 Opt_commit,
71 Opt_err_withdraw, 71 Opt_err_withdraw,
72 Opt_err_panic, 72 Opt_err_panic,
73 Opt_statfs_quantum,
74 Opt_statfs_percent,
75 Opt_quota_quantum,
73 Opt_error, 76 Opt_error,
74}; 77};
75 78
@@ -101,6 +104,9 @@ static const match_table_t tokens = {
101 {Opt_commit, "commit=%d"}, 104 {Opt_commit, "commit=%d"},
102 {Opt_err_withdraw, "errors=withdraw"}, 105 {Opt_err_withdraw, "errors=withdraw"},
103 {Opt_err_panic, "errors=panic"}, 106 {Opt_err_panic, "errors=panic"},
107 {Opt_statfs_quantum, "statfs_quantum=%d"},
108 {Opt_statfs_percent, "statfs_percent=%d"},
109 {Opt_quota_quantum, "quota_quantum=%d"},
104 {Opt_error, NULL} 110 {Opt_error, NULL}
105}; 111};
106 112
@@ -214,6 +220,28 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
214 return rv ? rv : -EINVAL; 220 return rv ? rv : -EINVAL;
215 } 221 }
216 break; 222 break;
223 case Opt_statfs_quantum:
224 rv = match_int(&tmp[0], &args->ar_statfs_quantum);
225 if (rv || args->ar_statfs_quantum < 0) {
226 printk(KERN_WARNING "GFS2: statfs_quantum mount option requires a non-negative numeric argument\n");
227 return rv ? rv : -EINVAL;
228 }
229 break;
230 case Opt_quota_quantum:
231 rv = match_int(&tmp[0], &args->ar_quota_quantum);
232 if (rv || args->ar_quota_quantum <= 0) {
233 printk(KERN_WARNING "GFS2: quota_quantum mount option requires a positive numeric argument\n");
234 return rv ? rv : -EINVAL;
235 }
236 break;
237 case Opt_statfs_percent:
238 rv = match_int(&tmp[0], &args->ar_statfs_percent);
239 if (rv || args->ar_statfs_percent < 0 ||
240 args->ar_statfs_percent > 100) {
241 printk(KERN_WARNING "statfs_percent mount option requires a numeric argument between 0 and 100\n");
242 return rv ? rv : -EINVAL;
243 }
244 break;
217 case Opt_err_withdraw: 245 case Opt_err_withdraw:
218 args->ar_errors = GFS2_ERRORS_WITHDRAW; 246 args->ar_errors = GFS2_ERRORS_WITHDRAW;
219 break; 247 break;
@@ -442,7 +470,9 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
442{ 470{
443 struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); 471 struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
444 struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; 472 struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
473 struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
445 struct buffer_head *l_bh; 474 struct buffer_head *l_bh;
475 int percent, sync_percent;
446 int error; 476 int error;
447 477
448 error = gfs2_meta_inode_buffer(l_ip, &l_bh); 478 error = gfs2_meta_inode_buffer(l_ip, &l_bh);
@@ -456,9 +486,17 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
456 l_sc->sc_free += free; 486 l_sc->sc_free += free;
457 l_sc->sc_dinodes += dinodes; 487 l_sc->sc_dinodes += dinodes;
458 gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode)); 488 gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode));
489 if (m_sc->sc_free)
490 percent = (100 * l_sc->sc_free) / m_sc->sc_free;
491 else
492 percent = 100;
459 spin_unlock(&sdp->sd_statfs_spin); 493 spin_unlock(&sdp->sd_statfs_spin);
460 494
461 brelse(l_bh); 495 brelse(l_bh);
496 sync_percent = sdp->sd_args.ar_statfs_percent;
497 if (sync_percent && (percent >= sync_percent ||
498 percent <= -sync_percent))
499 gfs2_wake_up_statfs(sdp);
462} 500}
463 501
464void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, 502void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
@@ -522,6 +560,7 @@ int gfs2_statfs_sync(struct super_block *sb, int type)
522 goto out_bh2; 560 goto out_bh2;
523 561
524 update_statfs(sdp, m_bh, l_bh); 562 update_statfs(sdp, m_bh, l_bh);
563 sdp->sd_statfs_force_sync = 0;
525 564
526 gfs2_trans_end(sdp); 565 gfs2_trans_end(sdp);
527 566
@@ -1062,6 +1101,11 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
1062 1101
1063 spin_lock(&gt->gt_spin); 1102 spin_lock(&gt->gt_spin);
1064 args.ar_commit = gt->gt_log_flush_secs; 1103 args.ar_commit = gt->gt_log_flush_secs;
1104 args.ar_quota_quantum = gt->gt_quota_quantum;
1105 if (gt->gt_statfs_slow)
1106 args.ar_statfs_quantum = 0;
1107 else
1108 args.ar_statfs_quantum = gt->gt_statfs_quantum;
1065 spin_unlock(&gt->gt_spin); 1109 spin_unlock(&gt->gt_spin);
1066 error = gfs2_mount_args(&args, data); 1110 error = gfs2_mount_args(&args, data);
1067 if (error) 1111 if (error)
@@ -1100,6 +1144,15 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
1100 sb->s_flags &= ~MS_POSIXACL; 1144 sb->s_flags &= ~MS_POSIXACL;
1101 spin_lock(&gt->gt_spin); 1145 spin_lock(&gt->gt_spin);
1102 gt->gt_log_flush_secs = args.ar_commit; 1146 gt->gt_log_flush_secs = args.ar_commit;
1147 gt->gt_quota_quantum = args.ar_quota_quantum;
1148 if (args.ar_statfs_quantum) {
1149 gt->gt_statfs_slow = 0;
1150 gt->gt_statfs_quantum = args.ar_statfs_quantum;
1151 }
1152 else {
1153 gt->gt_statfs_slow = 1;
1154 gt->gt_statfs_quantum = 30;
1155 }
1103 spin_unlock(&gt->gt_spin); 1156 spin_unlock(&gt->gt_spin);
1104 1157
1105 gfs2_online_uevent(sdp); 1158 gfs2_online_uevent(sdp);
@@ -1180,7 +1233,7 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
1180{ 1233{
1181 struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; 1234 struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info;
1182 struct gfs2_args *args = &sdp->sd_args; 1235 struct gfs2_args *args = &sdp->sd_args;
1183 int lfsecs; 1236 int val;
1184 1237
1185 if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir)) 1238 if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir))
1186 seq_printf(s, ",meta"); 1239 seq_printf(s, ",meta");
@@ -1241,9 +1294,17 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
1241 } 1294 }
1242 if (args->ar_discard) 1295 if (args->ar_discard)
1243 seq_printf(s, ",discard"); 1296 seq_printf(s, ",discard");
1244 lfsecs = sdp->sd_tune.gt_log_flush_secs; 1297 val = sdp->sd_tune.gt_log_flush_secs;
1245 if (lfsecs != 60) 1298 if (val != 60)
1246 seq_printf(s, ",commit=%d", lfsecs); 1299 seq_printf(s, ",commit=%d", val);
1300 val = sdp->sd_tune.gt_statfs_quantum;
1301 if (val != 30)
1302 seq_printf(s, ",statfs_quantum=%d", val);
1303 val = sdp->sd_tune.gt_quota_quantum;
1304 if (val != 60)
1305 seq_printf(s, ",quota_quantum=%d", val);
1306 if (args->ar_statfs_percent)
1307 seq_printf(s, ",statfs_percent=%d", args->ar_statfs_percent);
1247 if (args->ar_errors != GFS2_ERRORS_DEFAULT) { 1308 if (args->ar_errors != GFS2_ERRORS_DEFAULT) {
1248 const char *state; 1309 const char *state;
1249 1310