Skip to content

Commit 942b0cd

Browse files
committed
GFS2: Withdraw for IO errors writing to the journal or statfs
Before this patch, if GFS2 encountered IO errors while writing to the journal, it would not report the problem, so they would go unnoticed, sometimes for many hours. Sometimes this would only be noticed later, when recovery tried to do journal replay and failed due to invalid metadata at the blocks that resulted in IO errors. This patch makes GFS2's log daemon check for IO errors. If it encounters one, it withdraws from the file system and reports why in dmesg. A similar action is taken when IO errors occur when writing to the system statfs file. These errors are also reported back to any callers of fsync, since that requires the journal to be flushed. Therefore, any IO errors that would previously go unnoticed are now noticed and the file system is withdrawn as early as possible, thus preventing further file system damage. Also note that this reintroduces superblock variable sd_log_error, which Christoph removed with commit f729b66. Signed-off-by: Bob Peterson <[email protected]>
1 parent cc1dfa8 commit 942b0cd

File tree

5 files changed

+21
-5
lines changed

5 files changed

+21
-5
lines changed

fs/gfs2/incore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ struct gfs2_sbd {
817817
atomic_t sd_log_in_flight;
818818
struct bio *sd_log_bio;
819819
wait_queue_head_t sd_log_flush_wait;
820+
int sd_log_error;
820821

821822
atomic_t sd_reserving_log;
822823
wait_queue_head_t sd_reserving_log_wait;

fs/gfs2/log.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,15 @@ int gfs2_logd(void *data)
923923

924924
while (!kthread_should_stop()) {
925925

926+
/* Check for errors writing to the journal */
927+
if (sdp->sd_log_error) {
928+
gfs2_lm_withdraw(sdp,
929+
"GFS2: fsid=%s: error %d: "
930+
"withdrawing the file system to "
931+
"prevent further damage.\n",
932+
sdp->sd_fsname, sdp->sd_log_error);
933+
}
934+
926935
did_flush = false;
927936
if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
928937
gfs2_ail1_empty(sdp);

fs/gfs2/lops.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,11 @@ static void gfs2_end_log_write(struct bio *bio)
207207
struct page *page;
208208
int i;
209209

210-
if (bio->bi_status)
211-
fs_err(sdp, "Error %d writing to log\n", bio->bi_status);
210+
if (bio->bi_status) {
211+
fs_err(sdp, "Error %d writing to journal, jid=%u\n",
212+
bio->bi_status, sdp->sd_jdesc->jd_jid);
213+
wake_up(&sdp->sd_logd_waitq);
214+
}
212215

213216
bio_for_each_segment_all(bvec, bio, i) {
214217
page = bvec->bv_page;

fs/gfs2/quota.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1474,8 +1474,11 @@ static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error)
14741474
{
14751475
if (error == 0 || error == -EROFS)
14761476
return;
1477-
if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
1477+
if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) {
14781478
fs_err(sdp, "gfs2_quotad: %s error %d\n", msg, error);
1479+
sdp->sd_log_error = error;
1480+
wake_up(&sdp->sd_logd_waitq);
1481+
}
14791482
}
14801483

14811484
static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg,

fs/gfs2/super.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,9 +944,9 @@ static int gfs2_sync_fs(struct super_block *sb, int wait)
944944
struct gfs2_sbd *sdp = sb->s_fs_info;
945945

946946
gfs2_quota_sync(sb, -1);
947-
if (wait && sdp)
947+
if (wait)
948948
gfs2_log_flush(sdp, NULL, NORMAL_FLUSH);
949-
return 0;
949+
return sdp->sd_log_error;
950950
}
951951

952952
void gfs2_freeze_func(struct work_struct *work)

0 commit comments

Comments
 (0)