diff options
Diffstat (limited to 'fs/gfs2/super.c')
-rw-r--r-- | fs/gfs2/super.c | 86 |
1 files changed, 68 insertions, 18 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0a6801336470..0ec3ec672de1 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "trans.h" | 38 | #include "trans.h" |
39 | #include "util.h" | 39 | #include "util.h" |
40 | #include "sys.h" | 40 | #include "sys.h" |
41 | #include "eattr.h" | 41 | #include "xattr.h" |
42 | 42 | ||
43 | #define args_neq(a1, a2, x) ((a1)->ar_##x != (a2)->ar_##x) | 43 | #define args_neq(a1, a2, x) ((a1)->ar_##x != (a2)->ar_##x) |
44 | 44 | ||
@@ -68,6 +68,8 @@ enum { | |||
68 | Opt_discard, | 68 | Opt_discard, |
69 | Opt_nodiscard, | 69 | Opt_nodiscard, |
70 | Opt_commit, | 70 | Opt_commit, |
71 | Opt_err_withdraw, | ||
72 | Opt_err_panic, | ||
71 | Opt_error, | 73 | Opt_error, |
72 | }; | 74 | }; |
73 | 75 | ||
@@ -97,6 +99,8 @@ static const match_table_t tokens = { | |||
97 | {Opt_discard, "discard"}, | 99 | {Opt_discard, "discard"}, |
98 | {Opt_nodiscard, "nodiscard"}, | 100 | {Opt_nodiscard, "nodiscard"}, |
99 | {Opt_commit, "commit=%d"}, | 101 | {Opt_commit, "commit=%d"}, |
102 | {Opt_err_withdraw, "errors=withdraw"}, | ||
103 | {Opt_err_panic, "errors=panic"}, | ||
100 | {Opt_error, NULL} | 104 | {Opt_error, NULL} |
101 | }; | 105 | }; |
102 | 106 | ||
@@ -152,6 +156,11 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
152 | args->ar_localcaching = 1; | 156 | args->ar_localcaching = 1; |
153 | break; | 157 | break; |
154 | case Opt_debug: | 158 | case Opt_debug: |
159 | if (args->ar_errors == GFS2_ERRORS_PANIC) { | ||
160 | fs_info(sdp, "-o debug and -o errors=panic " | ||
161 | "are mutually exclusive.\n"); | ||
162 | return -EINVAL; | ||
163 | } | ||
155 | args->ar_debug = 1; | 164 | args->ar_debug = 1; |
156 | break; | 165 | break; |
157 | case Opt_nodebug: | 166 | case Opt_nodebug: |
@@ -205,6 +214,17 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
205 | return rv ? rv : -EINVAL; | 214 | return rv ? rv : -EINVAL; |
206 | } | 215 | } |
207 | break; | 216 | break; |
217 | case Opt_err_withdraw: | ||
218 | args->ar_errors = GFS2_ERRORS_WITHDRAW; | ||
219 | break; | ||
220 | case Opt_err_panic: | ||
221 | if (args->ar_debug) { | ||
222 | fs_info(sdp, "-o debug and -o errors=panic " | ||
223 | "are mutually exclusive.\n"); | ||
224 | return -EINVAL; | ||
225 | } | ||
226 | args->ar_errors = GFS2_ERRORS_PANIC; | ||
227 | break; | ||
208 | case Opt_error: | 228 | case Opt_error: |
209 | default: | 229 | default: |
210 | fs_info(sdp, "invalid mount option: %s\n", o); | 230 | fs_info(sdp, "invalid mount option: %s\n", o); |
@@ -353,7 +373,7 @@ fail: | |||
353 | return error; | 373 | return error; |
354 | } | 374 | } |
355 | 375 | ||
356 | static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) | 376 | void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) |
357 | { | 377 | { |
358 | const struct gfs2_statfs_change *str = buf; | 378 | const struct gfs2_statfs_change *str = buf; |
359 | 379 | ||
@@ -441,6 +461,29 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | |||
441 | brelse(l_bh); | 461 | brelse(l_bh); |
442 | } | 462 | } |
443 | 463 | ||
464 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | ||
465 | struct buffer_head *l_bh) | ||
466 | { | ||
467 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
468 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | ||
469 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
470 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
471 | |||
472 | gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); | ||
473 | |||
474 | spin_lock(&sdp->sd_statfs_spin); | ||
475 | m_sc->sc_total += l_sc->sc_total; | ||
476 | m_sc->sc_free += l_sc->sc_free; | ||
477 | m_sc->sc_dinodes += l_sc->sc_dinodes; | ||
478 | memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); | ||
479 | memset(l_bh->b_data + sizeof(struct gfs2_dinode), | ||
480 | 0, sizeof(struct gfs2_statfs_change)); | ||
481 | spin_unlock(&sdp->sd_statfs_spin); | ||
482 | |||
483 | gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); | ||
484 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | ||
485 | } | ||
486 | |||
444 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) | 487 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) |
445 | { | 488 | { |
446 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | 489 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); |
@@ -477,19 +520,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp) | |||
477 | if (error) | 520 | if (error) |
478 | goto out_bh2; | 521 | goto out_bh2; |
479 | 522 | ||
480 | gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); | 523 | update_statfs(sdp, m_bh, l_bh); |
481 | |||
482 | spin_lock(&sdp->sd_statfs_spin); | ||
483 | m_sc->sc_total += l_sc->sc_total; | ||
484 | m_sc->sc_free += l_sc->sc_free; | ||
485 | m_sc->sc_dinodes += l_sc->sc_dinodes; | ||
486 | memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); | ||
487 | memset(l_bh->b_data + sizeof(struct gfs2_dinode), | ||
488 | 0, sizeof(struct gfs2_statfs_change)); | ||
489 | spin_unlock(&sdp->sd_statfs_spin); | ||
490 | |||
491 | gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); | ||
492 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | ||
493 | 524 | ||
494 | gfs2_trans_end(sdp); | 525 | gfs2_trans_end(sdp); |
495 | 526 | ||
@@ -680,6 +711,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
680 | struct gfs2_holder t_gh; | 711 | struct gfs2_holder t_gh; |
681 | int error; | 712 | int error; |
682 | 713 | ||
714 | flush_workqueue(gfs2_delete_workqueue); | ||
683 | gfs2_quota_sync(sdp); | 715 | gfs2_quota_sync(sdp); |
684 | gfs2_statfs_sync(sdp); | 716 | gfs2_statfs_sync(sdp); |
685 | 717 | ||
@@ -756,7 +788,6 @@ restart: | |||
756 | /* Release stuff */ | 788 | /* Release stuff */ |
757 | 789 | ||
758 | iput(sdp->sd_jindex); | 790 | iput(sdp->sd_jindex); |
759 | iput(sdp->sd_inum_inode); | ||
760 | iput(sdp->sd_statfs_inode); | 791 | iput(sdp->sd_statfs_inode); |
761 | iput(sdp->sd_rindex); | 792 | iput(sdp->sd_rindex); |
762 | iput(sdp->sd_quota_inode); | 793 | iput(sdp->sd_quota_inode); |
@@ -767,10 +798,8 @@ restart: | |||
767 | if (!sdp->sd_args.ar_spectator) { | 798 | if (!sdp->sd_args.ar_spectator) { |
768 | gfs2_glock_dq_uninit(&sdp->sd_journal_gh); | 799 | gfs2_glock_dq_uninit(&sdp->sd_journal_gh); |
769 | gfs2_glock_dq_uninit(&sdp->sd_jinode_gh); | 800 | gfs2_glock_dq_uninit(&sdp->sd_jinode_gh); |
770 | gfs2_glock_dq_uninit(&sdp->sd_ir_gh); | ||
771 | gfs2_glock_dq_uninit(&sdp->sd_sc_gh); | 801 | gfs2_glock_dq_uninit(&sdp->sd_sc_gh); |
772 | gfs2_glock_dq_uninit(&sdp->sd_qc_gh); | 802 | gfs2_glock_dq_uninit(&sdp->sd_qc_gh); |
773 | iput(sdp->sd_ir_inode); | ||
774 | iput(sdp->sd_sc_inode); | 803 | iput(sdp->sd_sc_inode); |
775 | iput(sdp->sd_qc_inode); | 804 | iput(sdp->sd_qc_inode); |
776 | } | 805 | } |
@@ -1072,6 +1101,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | |||
1072 | gt->gt_log_flush_secs = args.ar_commit; | 1101 | gt->gt_log_flush_secs = args.ar_commit; |
1073 | spin_unlock(>->gt_spin); | 1102 | spin_unlock(>->gt_spin); |
1074 | 1103 | ||
1104 | gfs2_online_uevent(sdp); | ||
1075 | return 0; | 1105 | return 0; |
1076 | } | 1106 | } |
1077 | 1107 | ||
@@ -1213,6 +1243,22 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1213 | lfsecs = sdp->sd_tune.gt_log_flush_secs; | 1243 | lfsecs = sdp->sd_tune.gt_log_flush_secs; |
1214 | if (lfsecs != 60) | 1244 | if (lfsecs != 60) |
1215 | seq_printf(s, ",commit=%d", lfsecs); | 1245 | seq_printf(s, ",commit=%d", lfsecs); |
1246 | if (args->ar_errors != GFS2_ERRORS_DEFAULT) { | ||
1247 | const char *state; | ||
1248 | |||
1249 | switch (args->ar_errors) { | ||
1250 | case GFS2_ERRORS_WITHDRAW: | ||
1251 | state = "withdraw"; | ||
1252 | break; | ||
1253 | case GFS2_ERRORS_PANIC: | ||
1254 | state = "panic"; | ||
1255 | break; | ||
1256 | default: | ||
1257 | state = "unknown"; | ||
1258 | break; | ||
1259 | } | ||
1260 | seq_printf(s, ",errors=%s", state); | ||
1261 | } | ||
1216 | return 0; | 1262 | return 0; |
1217 | } | 1263 | } |
1218 | 1264 | ||
@@ -1240,6 +1286,10 @@ static void gfs2_delete_inode(struct inode *inode) | |||
1240 | goto out; | 1286 | goto out; |
1241 | } | 1287 | } |
1242 | 1288 | ||
1289 | error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED); | ||
1290 | if (error) | ||
1291 | goto out_truncate; | ||
1292 | |||
1243 | gfs2_glock_dq_wait(&ip->i_iopen_gh); | 1293 | gfs2_glock_dq_wait(&ip->i_iopen_gh); |
1244 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); | 1294 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); |
1245 | error = gfs2_glock_nq(&ip->i_iopen_gh); | 1295 | error = gfs2_glock_nq(&ip->i_iopen_gh); |