diff options
author | Benjamin Marzinski <bmarzins@redhat.com> | 2009-10-20 03:39:44 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2009-12-03 06:55:17 -0500 |
commit | 3d3c10f2ce80d2a19e5e02023c2b7ab7086c36d5 (patch) | |
tree | 56b62b064457596caf66700323ff5aac2320ae93 | |
parent | 2ec4650526c5a94d96bb760001fe0685b15988de (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.h | 4 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 14 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 21 | ||||
-rw-r--r-- | fs/gfs2/quota.h | 2 | ||||
-rw-r--r-- | fs/gfs2/super.c | 69 |
5 files changed, 100 insertions, 10 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 6edb423f90b..c239b0f969c 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 | ||
435 | struct gfs2_tune { | 438 | struct 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 36b11cba57e..9744ee92047 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 | ||
75 | static struct gfs2_sbd *init_sbd(struct super_block *sb) | 72 | static 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 1d4fc0413a3..e3bf6eab875 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 | ||
1347 | void 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 025d15ba24c..e271fa07ad0 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h | |||
@@ -32,6 +32,8 @@ extern int gfs2_quota_init(struct gfs2_sbd *sdp); | |||
32 | extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp); | 32 | extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp); |
33 | extern int gfs2_quotad(void *data); | 33 | extern int gfs2_quotad(void *data); |
34 | 34 | ||
35 | extern void gfs2_wake_up_statfs(struct gfs2_sbd *sdp); | ||
36 | |||
35 | static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) | 37 | static 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 e7b24d59d4f..3fee2fd3ae4 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 | ||
464 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | 502 | void 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_spin); | 1102 | spin_lock(>->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_spin); | 1109 | spin_unlock(>->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_spin); | 1145 | spin_lock(>->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_spin); | 1156 | spin_unlock(>->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 | ||