diff options
-rw-r--r-- | fs/gfs2/incore.h | 7 | ||||
-rw-r--r-- | fs/gfs2/log.c | 16 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 2 |
3 files changed, 16 insertions, 9 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index b95c8a31d309..ab89f746b3b6 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -615,9 +615,8 @@ enum { SDF_RORECOVERY = 7, /* read only recovery */ SDF_SKIP_DLM_UNLOCK = 8, SDF_FORCE_AIL_FLUSH = 9, - SDF_AIL1_IO_ERROR = 10, - SDF_FS_FROZEN = 11, - SDF_WITHDRAWING = 12, /* Will withdraw eventually */ + SDF_FS_FROZEN = 10, + SDF_WITHDRAWING = 11, /* Will withdraw eventually */ }; enum gfs2_freeze_state { @@ -828,7 +827,7 @@ struct gfs2_sbd { atomic_t sd_log_in_flight; struct bio *sd_log_bio; wait_queue_head_t sd_log_flush_wait; - int sd_log_error; + int sd_log_error; /* First log error */ atomic_t sd_reserving_log; wait_queue_head_t sd_reserving_log_wait; diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 9ebec6f93fa3..584bb7ce15bf 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -108,8 +108,7 @@ __acquires(&sdp->sd_ail_lock) &tr->tr_ail2_list); continue; } - if (!test_and_set_bit(SDF_AIL1_IO_ERROR, - &sdp->sd_flags)) { + if (!cmpxchg(&sdp->sd_log_error, 0, -EIO)) { gfs2_io_error_bh(sdp, bh); gfs2_withdraw_delayed(sdp); } @@ -205,10 +204,19 @@ static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr) bd_ail_st_list) { bh = bd->bd_bh; gfs2_assert(sdp, bd->bd_tr == tr); - if (buffer_busy(bh)) + /* + * If another process flagged an io error, e.g. writing to the + * journal, error all other bhs and move them off the ail1 to + * prevent a tight loop when unmount tries to flush ail1, + * regardless of whether they're still busy. If no outside + * errors were found and the buffer is busy, move to the next. + * If the ail buffer is not busy and caught an error, flag it + * for others. + */ + if (!sdp->sd_log_error && buffer_busy(bh)) continue; if (!buffer_uptodate(bh) && - !test_and_set_bit(SDF_AIL1_IO_ERROR, &sdp->sd_flags)) { + !cmpxchg(&sdp->sd_log_error, 0, -EIO)) { gfs2_io_error_bh(sdp, bh); gfs2_withdraw_delayed(sdp); } diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index e9f93045eb01..ca2194cfa38e 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1477,7 +1477,7 @@ static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error) return; if (!gfs2_withdrawn(sdp)) { fs_err(sdp, "gfs2_quotad: %s error %d\n", msg, error); - sdp->sd_log_error = error; + cmpxchg(&sdp->sd_log_error, 0, error); wake_up(&sdp->sd_logd_waitq); } } |