diff options
Diffstat (limited to 'fs/gfs2/super.c')
-rw-r--r-- | fs/gfs2/super.c | 143 |
1 files changed, 108 insertions, 35 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0ec3ec672de1..50aac606b990 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/gfs2_ondisk.h> | 21 | #include <linux/gfs2_ondisk.h> |
22 | #include <linux/crc32.h> | 22 | #include <linux/crc32.h> |
23 | #include <linux/time.h> | 23 | #include <linux/time.h> |
24 | #include <linux/wait.h> | ||
25 | #include <linux/writeback.h> | ||
24 | 26 | ||
25 | #include "gfs2.h" | 27 | #include "gfs2.h" |
26 | #include "incore.h" | 28 | #include "incore.h" |
@@ -70,6 +72,11 @@ enum { | |||
70 | Opt_commit, | 72 | Opt_commit, |
71 | Opt_err_withdraw, | 73 | Opt_err_withdraw, |
72 | Opt_err_panic, | 74 | Opt_err_panic, |
75 | Opt_statfs_quantum, | ||
76 | Opt_statfs_percent, | ||
77 | Opt_quota_quantum, | ||
78 | Opt_barrier, | ||
79 | Opt_nobarrier, | ||
73 | Opt_error, | 80 | Opt_error, |
74 | }; | 81 | }; |
75 | 82 | ||
@@ -101,18 +108,23 @@ static const match_table_t tokens = { | |||
101 | {Opt_commit, "commit=%d"}, | 108 | {Opt_commit, "commit=%d"}, |
102 | {Opt_err_withdraw, "errors=withdraw"}, | 109 | {Opt_err_withdraw, "errors=withdraw"}, |
103 | {Opt_err_panic, "errors=panic"}, | 110 | {Opt_err_panic, "errors=panic"}, |
111 | {Opt_statfs_quantum, "statfs_quantum=%d"}, | ||
112 | {Opt_statfs_percent, "statfs_percent=%d"}, | ||
113 | {Opt_quota_quantum, "quota_quantum=%d"}, | ||
114 | {Opt_barrier, "barrier"}, | ||
115 | {Opt_nobarrier, "nobarrier"}, | ||
104 | {Opt_error, NULL} | 116 | {Opt_error, NULL} |
105 | }; | 117 | }; |
106 | 118 | ||
107 | /** | 119 | /** |
108 | * gfs2_mount_args - Parse mount options | 120 | * gfs2_mount_args - Parse mount options |
109 | * @sdp: | 121 | * @args: The structure into which the parsed options will be written |
110 | * @data: | 122 | * @options: The options to parse |
111 | * | 123 | * |
112 | * Return: errno | 124 | * Return: errno |
113 | */ | 125 | */ |
114 | 126 | ||
115 | int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | 127 | int gfs2_mount_args(struct gfs2_args *args, char *options) |
116 | { | 128 | { |
117 | char *o; | 129 | char *o; |
118 | int token; | 130 | int token; |
@@ -157,7 +169,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
157 | break; | 169 | break; |
158 | case Opt_debug: | 170 | case Opt_debug: |
159 | if (args->ar_errors == GFS2_ERRORS_PANIC) { | 171 | if (args->ar_errors == GFS2_ERRORS_PANIC) { |
160 | fs_info(sdp, "-o debug and -o errors=panic " | 172 | printk(KERN_WARNING "GFS2: -o debug and -o errors=panic " |
161 | "are mutually exclusive.\n"); | 173 | "are mutually exclusive.\n"); |
162 | return -EINVAL; | 174 | return -EINVAL; |
163 | } | 175 | } |
@@ -210,7 +222,29 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
210 | case Opt_commit: | 222 | case Opt_commit: |
211 | rv = match_int(&tmp[0], &args->ar_commit); | 223 | rv = match_int(&tmp[0], &args->ar_commit); |
212 | if (rv || args->ar_commit <= 0) { | 224 | if (rv || args->ar_commit <= 0) { |
213 | fs_info(sdp, "commit mount option requires a positive numeric argument\n"); | 225 | printk(KERN_WARNING "GFS2: commit mount option requires a positive numeric argument\n"); |
226 | return rv ? rv : -EINVAL; | ||
227 | } | ||
228 | break; | ||
229 | case Opt_statfs_quantum: | ||
230 | rv = match_int(&tmp[0], &args->ar_statfs_quantum); | ||
231 | if (rv || args->ar_statfs_quantum < 0) { | ||
232 | printk(KERN_WARNING "GFS2: statfs_quantum mount option requires a non-negative numeric argument\n"); | ||
233 | return rv ? rv : -EINVAL; | ||
234 | } | ||
235 | break; | ||
236 | case Opt_quota_quantum: | ||
237 | rv = match_int(&tmp[0], &args->ar_quota_quantum); | ||
238 | if (rv || args->ar_quota_quantum <= 0) { | ||
239 | printk(KERN_WARNING "GFS2: quota_quantum mount option requires a positive numeric argument\n"); | ||
240 | return rv ? rv : -EINVAL; | ||
241 | } | ||
242 | break; | ||
243 | case Opt_statfs_percent: | ||
244 | rv = match_int(&tmp[0], &args->ar_statfs_percent); | ||
245 | if (rv || args->ar_statfs_percent < 0 || | ||
246 | args->ar_statfs_percent > 100) { | ||
247 | printk(KERN_WARNING "statfs_percent mount option requires a numeric argument between 0 and 100\n"); | ||
214 | return rv ? rv : -EINVAL; | 248 | return rv ? rv : -EINVAL; |
215 | } | 249 | } |
216 | break; | 250 | break; |
@@ -219,15 +253,21 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
219 | break; | 253 | break; |
220 | case Opt_err_panic: | 254 | case Opt_err_panic: |
221 | if (args->ar_debug) { | 255 | if (args->ar_debug) { |
222 | fs_info(sdp, "-o debug and -o errors=panic " | 256 | printk(KERN_WARNING "GFS2: -o debug and -o errors=panic " |
223 | "are mutually exclusive.\n"); | 257 | "are mutually exclusive.\n"); |
224 | return -EINVAL; | 258 | return -EINVAL; |
225 | } | 259 | } |
226 | args->ar_errors = GFS2_ERRORS_PANIC; | 260 | args->ar_errors = GFS2_ERRORS_PANIC; |
227 | break; | 261 | break; |
262 | case Opt_barrier: | ||
263 | args->ar_nobarrier = 0; | ||
264 | break; | ||
265 | case Opt_nobarrier: | ||
266 | args->ar_nobarrier = 1; | ||
267 | break; | ||
228 | case Opt_error: | 268 | case Opt_error: |
229 | default: | 269 | default: |
230 | fs_info(sdp, "invalid mount option: %s\n", o); | 270 | printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o); |
231 | return -EINVAL; | 271 | return -EINVAL; |
232 | } | 272 | } |
233 | } | 273 | } |
@@ -442,7 +482,10 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | |||
442 | { | 482 | { |
443 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | 483 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); |
444 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | 484 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; |
485 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
445 | struct buffer_head *l_bh; | 486 | struct buffer_head *l_bh; |
487 | s64 x, y; | ||
488 | int need_sync = 0; | ||
446 | int error; | 489 | int error; |
447 | 490 | ||
448 | error = gfs2_meta_inode_buffer(l_ip, &l_bh); | 491 | error = gfs2_meta_inode_buffer(l_ip, &l_bh); |
@@ -456,9 +499,17 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | |||
456 | l_sc->sc_free += free; | 499 | l_sc->sc_free += free; |
457 | l_sc->sc_dinodes += dinodes; | 500 | l_sc->sc_dinodes += dinodes; |
458 | gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode)); | 501 | gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode)); |
502 | if (sdp->sd_args.ar_statfs_percent) { | ||
503 | x = 100 * l_sc->sc_free; | ||
504 | y = m_sc->sc_free * sdp->sd_args.ar_statfs_percent; | ||
505 | if (x >= y || x <= -y) | ||
506 | need_sync = 1; | ||
507 | } | ||
459 | spin_unlock(&sdp->sd_statfs_spin); | 508 | spin_unlock(&sdp->sd_statfs_spin); |
460 | 509 | ||
461 | brelse(l_bh); | 510 | brelse(l_bh); |
511 | if (need_sync) | ||
512 | gfs2_wake_up_statfs(sdp); | ||
462 | } | 513 | } |
463 | 514 | ||
464 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | 515 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, |
@@ -484,8 +535,9 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | |||
484 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | 535 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); |
485 | } | 536 | } |
486 | 537 | ||
487 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) | 538 | int gfs2_statfs_sync(struct super_block *sb, int type) |
488 | { | 539 | { |
540 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
489 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | 541 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); |
490 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | 542 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); |
491 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | 543 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; |
@@ -521,6 +573,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp) | |||
521 | goto out_bh2; | 573 | goto out_bh2; |
522 | 574 | ||
523 | update_statfs(sdp, m_bh, l_bh); | 575 | update_statfs(sdp, m_bh, l_bh); |
576 | sdp->sd_statfs_force_sync = 0; | ||
524 | 577 | ||
525 | gfs2_trans_end(sdp); | 578 | gfs2_trans_end(sdp); |
526 | 579 | ||
@@ -659,7 +712,7 @@ void gfs2_unfreeze_fs(struct gfs2_sbd *sdp) | |||
659 | * Returns: errno | 712 | * Returns: errno |
660 | */ | 713 | */ |
661 | 714 | ||
662 | static int gfs2_write_inode(struct inode *inode, int sync) | 715 | static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) |
663 | { | 716 | { |
664 | struct gfs2_inode *ip = GFS2_I(inode); | 717 | struct gfs2_inode *ip = GFS2_I(inode); |
665 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 718 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
@@ -670,8 +723,7 @@ static int gfs2_write_inode(struct inode *inode, int sync) | |||
670 | int ret = 0; | 723 | int ret = 0; |
671 | 724 | ||
672 | /* Check this is a "normal" inode, etc */ | 725 | /* Check this is a "normal" inode, etc */ |
673 | if (!test_bit(GIF_USER, &ip->i_flags) || | 726 | if (current->flags & PF_MEMALLOC) |
674 | (current->flags & PF_MEMALLOC)) | ||
675 | return 0; | 727 | return 0; |
676 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 728 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
677 | if (ret) | 729 | if (ret) |
@@ -694,7 +746,7 @@ static int gfs2_write_inode(struct inode *inode, int sync) | |||
694 | do_unlock: | 746 | do_unlock: |
695 | gfs2_glock_dq_uninit(&gh); | 747 | gfs2_glock_dq_uninit(&gh); |
696 | do_flush: | 748 | do_flush: |
697 | if (sync != 0) | 749 | if (wbc->sync_mode == WB_SYNC_ALL) |
698 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | 750 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); |
699 | return ret; | 751 | return ret; |
700 | } | 752 | } |
@@ -712,8 +764,8 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
712 | int error; | 764 | int error; |
713 | 765 | ||
714 | flush_workqueue(gfs2_delete_workqueue); | 766 | flush_workqueue(gfs2_delete_workqueue); |
715 | gfs2_quota_sync(sdp); | 767 | gfs2_quota_sync(sdp->sd_vfs, 0, 1); |
716 | gfs2_statfs_sync(sdp); | 768 | gfs2_statfs_sync(sdp->sd_vfs, 0); |
717 | 769 | ||
718 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, | 770 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, |
719 | &t_gh); | 771 | &t_gh); |
@@ -808,6 +860,7 @@ restart: | |||
808 | gfs2_clear_rgrpd(sdp); | 860 | gfs2_clear_rgrpd(sdp); |
809 | gfs2_jindex_free(sdp); | 861 | gfs2_jindex_free(sdp); |
810 | /* Take apart glock structures and buffer lists */ | 862 | /* Take apart glock structures and buffer lists */ |
863 | invalidate_inodes(sdp->sd_vfs); | ||
811 | gfs2_gl_hash_clear(sdp); | 864 | gfs2_gl_hash_clear(sdp); |
812 | /* Unmount the locking protocol */ | 865 | /* Unmount the locking protocol */ |
813 | gfs2_lm_unmount(sdp); | 866 | gfs2_lm_unmount(sdp); |
@@ -1061,8 +1114,13 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | |||
1061 | 1114 | ||
1062 | spin_lock(>->gt_spin); | 1115 | spin_lock(>->gt_spin); |
1063 | args.ar_commit = gt->gt_log_flush_secs; | 1116 | args.ar_commit = gt->gt_log_flush_secs; |
1117 | args.ar_quota_quantum = gt->gt_quota_quantum; | ||
1118 | if (gt->gt_statfs_slow) | ||
1119 | args.ar_statfs_quantum = 0; | ||
1120 | else | ||
1121 | args.ar_statfs_quantum = gt->gt_statfs_quantum; | ||
1064 | spin_unlock(>->gt_spin); | 1122 | spin_unlock(>->gt_spin); |
1065 | error = gfs2_mount_args(sdp, &args, data); | 1123 | error = gfs2_mount_args(&args, data); |
1066 | if (error) | 1124 | if (error) |
1067 | return error; | 1125 | return error; |
1068 | 1126 | ||
@@ -1097,8 +1155,21 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | |||
1097 | sb->s_flags |= MS_POSIXACL; | 1155 | sb->s_flags |= MS_POSIXACL; |
1098 | else | 1156 | else |
1099 | sb->s_flags &= ~MS_POSIXACL; | 1157 | sb->s_flags &= ~MS_POSIXACL; |
1158 | if (sdp->sd_args.ar_nobarrier) | ||
1159 | set_bit(SDF_NOBARRIERS, &sdp->sd_flags); | ||
1160 | else | ||
1161 | clear_bit(SDF_NOBARRIERS, &sdp->sd_flags); | ||
1100 | spin_lock(>->gt_spin); | 1162 | spin_lock(>->gt_spin); |
1101 | gt->gt_log_flush_secs = args.ar_commit; | 1163 | gt->gt_log_flush_secs = args.ar_commit; |
1164 | gt->gt_quota_quantum = args.ar_quota_quantum; | ||
1165 | if (args.ar_statfs_quantum) { | ||
1166 | gt->gt_statfs_slow = 0; | ||
1167 | gt->gt_statfs_quantum = args.ar_statfs_quantum; | ||
1168 | } | ||
1169 | else { | ||
1170 | gt->gt_statfs_slow = 1; | ||
1171 | gt->gt_statfs_quantum = 30; | ||
1172 | } | ||
1102 | spin_unlock(>->gt_spin); | 1173 | spin_unlock(>->gt_spin); |
1103 | 1174 | ||
1104 | gfs2_online_uevent(sdp); | 1175 | gfs2_online_uevent(sdp); |
@@ -1124,7 +1195,7 @@ static void gfs2_drop_inode(struct inode *inode) | |||
1124 | { | 1195 | { |
1125 | struct gfs2_inode *ip = GFS2_I(inode); | 1196 | struct gfs2_inode *ip = GFS2_I(inode); |
1126 | 1197 | ||
1127 | if (test_bit(GIF_USER, &ip->i_flags) && inode->i_nlink) { | 1198 | if (inode->i_nlink) { |
1128 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; | 1199 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; |
1129 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1200 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) |
1130 | clear_nlink(inode); | 1201 | clear_nlink(inode); |
@@ -1142,18 +1213,12 @@ static void gfs2_clear_inode(struct inode *inode) | |||
1142 | { | 1213 | { |
1143 | struct gfs2_inode *ip = GFS2_I(inode); | 1214 | struct gfs2_inode *ip = GFS2_I(inode); |
1144 | 1215 | ||
1145 | /* This tells us its a "real" inode and not one which only | 1216 | ip->i_gl->gl_object = NULL; |
1146 | * serves to contain an address space (see rgrp.c, meta_io.c) | 1217 | gfs2_glock_put(ip->i_gl); |
1147 | * which therefore doesn't have its own glocks. | 1218 | ip->i_gl = NULL; |
1148 | */ | 1219 | if (ip->i_iopen_gh.gh_gl) { |
1149 | if (test_bit(GIF_USER, &ip->i_flags)) { | 1220 | ip->i_iopen_gh.gh_gl->gl_object = NULL; |
1150 | ip->i_gl->gl_object = NULL; | 1221 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
1151 | gfs2_glock_put(ip->i_gl); | ||
1152 | ip->i_gl = NULL; | ||
1153 | if (ip->i_iopen_gh.gh_gl) { | ||
1154 | ip->i_iopen_gh.gh_gl->gl_object = NULL; | ||
1155 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | ||
1156 | } | ||
1157 | } | 1222 | } |
1158 | } | 1223 | } |
1159 | 1224 | ||
@@ -1179,7 +1244,7 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1179 | { | 1244 | { |
1180 | struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; | 1245 | struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; |
1181 | struct gfs2_args *args = &sdp->sd_args; | 1246 | struct gfs2_args *args = &sdp->sd_args; |
1182 | int lfsecs; | 1247 | int val; |
1183 | 1248 | ||
1184 | if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir)) | 1249 | if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir)) |
1185 | seq_printf(s, ",meta"); | 1250 | seq_printf(s, ",meta"); |
@@ -1240,9 +1305,17 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1240 | } | 1305 | } |
1241 | if (args->ar_discard) | 1306 | if (args->ar_discard) |
1242 | seq_printf(s, ",discard"); | 1307 | seq_printf(s, ",discard"); |
1243 | lfsecs = sdp->sd_tune.gt_log_flush_secs; | 1308 | val = sdp->sd_tune.gt_log_flush_secs; |
1244 | if (lfsecs != 60) | 1309 | if (val != 60) |
1245 | seq_printf(s, ",commit=%d", lfsecs); | 1310 | seq_printf(s, ",commit=%d", val); |
1311 | val = sdp->sd_tune.gt_statfs_quantum; | ||
1312 | if (val != 30) | ||
1313 | seq_printf(s, ",statfs_quantum=%d", val); | ||
1314 | val = sdp->sd_tune.gt_quota_quantum; | ||
1315 | if (val != 60) | ||
1316 | seq_printf(s, ",quota_quantum=%d", val); | ||
1317 | if (args->ar_statfs_percent) | ||
1318 | seq_printf(s, ",statfs_percent=%d", args->ar_statfs_percent); | ||
1246 | if (args->ar_errors != GFS2_ERRORS_DEFAULT) { | 1319 | if (args->ar_errors != GFS2_ERRORS_DEFAULT) { |
1247 | const char *state; | 1320 | const char *state; |
1248 | 1321 | ||
@@ -1259,6 +1332,9 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1259 | } | 1332 | } |
1260 | seq_printf(s, ",errors=%s", state); | 1333 | seq_printf(s, ",errors=%s", state); |
1261 | } | 1334 | } |
1335 | if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) | ||
1336 | seq_printf(s, ",nobarrier"); | ||
1337 | |||
1262 | return 0; | 1338 | return 0; |
1263 | } | 1339 | } |
1264 | 1340 | ||
@@ -1277,9 +1353,6 @@ static void gfs2_delete_inode(struct inode *inode) | |||
1277 | struct gfs2_holder gh; | 1353 | struct gfs2_holder gh; |
1278 | int error; | 1354 | int error; |
1279 | 1355 | ||
1280 | if (!test_bit(GIF_USER, &ip->i_flags)) | ||
1281 | goto out; | ||
1282 | |||
1283 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 1356 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
1284 | if (unlikely(error)) { | 1357 | if (unlikely(error)) { |
1285 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1358 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |