gfs2: Clean up SDF_JOURNAL_LIVE flag handling

Change do_withdraw() to clear the SDF_JOURNAL_LIVE flag under the log
flush lock.  In addition, change __gfs2_trans_begin() to check if the
filesystem is already known to be withdrawn using gfs2_withdrawn().
Then, once we are holding the log flush lock, check if the
SDF_JOURNAL_LIVE flag is still set.  This second check ensures that the
filesystem will remain live until the transaction is submitted.

With these changes, it is no longer useful to clear SDF_JOURNAL_LIVE in
gfs2_end_log_write() after calling gfs2_withdraw().

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
pull/1354/merge
Andreas Gruenbacher 2025-10-29 21:00:18 +00:00
parent 16c3197984
commit 83348905e4
3 changed files with 35 additions and 38 deletions

View File

@ -210,9 +210,6 @@ static void gfs2_end_log_write(struct bio *bio)
fs_err(sdp, "Error %d writing to journal, jid=%u\n", fs_err(sdp, "Error %d writing to journal, jid=%u\n",
err, sdp->sd_jdesc->jd_jid); err, sdp->sd_jdesc->jd_jid);
gfs2_withdraw(sdp); gfs2_withdraw(sdp);
/* prevent more writes to the journal */
clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
wake_up(&sdp->sd_logd_waitq);
} }
bio_for_each_segment_all(bvec, bio, iter_all) { bio_for_each_segment_all(bvec, bio, iter_all) {

View File

@ -49,7 +49,7 @@ int __gfs2_trans_begin(struct gfs2_trans *tr, struct gfs2_sbd *sdp,
} }
BUG_ON(blocks == 0 && revokes == 0); BUG_ON(blocks == 0 && revokes == 0);
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) if (gfs2_withdrawn(sdp))
return -EROFS; return -EROFS;
tr->tr_ip = ip; tr->tr_ip = ip;
@ -85,25 +85,30 @@ int __gfs2_trans_begin(struct gfs2_trans *tr, struct gfs2_sbd *sdp,
*/ */
down_read(&sdp->sd_log_flush_lock); down_read(&sdp->sd_log_flush_lock);
if (unlikely(!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)))
goto out_not_live;
if (gfs2_log_try_reserve(sdp, tr, &extra_revokes)) if (gfs2_log_try_reserve(sdp, tr, &extra_revokes))
goto reserved; goto reserved;
up_read(&sdp->sd_log_flush_lock); up_read(&sdp->sd_log_flush_lock);
gfs2_log_reserve(sdp, tr, &extra_revokes); gfs2_log_reserve(sdp, tr, &extra_revokes);
down_read(&sdp->sd_log_flush_lock); down_read(&sdp->sd_log_flush_lock);
if (unlikely(!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))) {
revokes = tr->tr_revokes + extra_revokes;
gfs2_log_release_revokes(sdp, revokes);
gfs2_log_release(sdp, tr->tr_reserved);
goto out_not_live;
}
reserved: reserved:
gfs2_log_release_revokes(sdp, extra_revokes); gfs2_log_release_revokes(sdp, extra_revokes);
if (unlikely(!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))) { current->journal_info = tr;
gfs2_log_release_revokes(sdp, tr->tr_revokes); return 0;
out_not_live:
up_read(&sdp->sd_log_flush_lock); up_read(&sdp->sd_log_flush_lock);
gfs2_log_release(sdp, tr->tr_reserved);
sb_end_intwrite(sdp->sd_vfs); sb_end_intwrite(sdp->sd_vfs);
return -EROFS; return -EROFS;
}
current->journal_info = tr;
return 0;
} }
int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,

View File

@ -117,20 +117,16 @@ void gfs2_freeze_unlock(struct gfs2_sbd *sdp)
static void do_withdraw(struct gfs2_sbd *sdp) static void do_withdraw(struct gfs2_sbd *sdp)
{ {
down_write(&sdp->sd_log_flush_lock);
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
up_write(&sdp->sd_log_flush_lock);
return;
}
clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
up_write(&sdp->sd_log_flush_lock);
gfs2_ail_drain(sdp); /* frees all transactions */ gfs2_ail_drain(sdp); /* frees all transactions */
/*
* Don't tell dlm we're bailing until we have no more buffers in the
* wind. If journal had an IO error, the log code should just purge
* the outstanding buffers rather than submitting new IO.
*
* During a normal unmount, gfs2_make_fs_ro calls gfs2_log_shutdown
* which clears SDF_JOURNAL_LIVE. In a withdraw, we must not write
* any UNMOUNT log header, so we can't call gfs2_log_shutdown, and
* therefore we need to clear SDF_JOURNAL_LIVE manually.
*/
clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
if (!sb_rdonly(sdp->sd_vfs)) {
wake_up(&sdp->sd_logd_waitq); wake_up(&sdp->sd_logd_waitq);
wake_up(&sdp->sd_quota_wait); wake_up(&sdp->sd_quota_wait);
@ -145,7 +141,6 @@ static void do_withdraw(struct gfs2_sbd *sdp)
* longer be granted because the file system is withdrawn. * longer be granted because the file system is withdrawn.
*/ */
gfs2_withdraw_glocks(sdp); gfs2_withdraw_glocks(sdp);
}
} }
void gfs2_lm(struct gfs2_sbd *sdp, const char *fmt, ...) void gfs2_lm(struct gfs2_sbd *sdp, const char *fmt, ...)