diff options
| author | Andreas Gruenbacher <agruenba@redhat.com> | 2025-10-29 21:00:18 +0000 |
|---|---|---|
| committer | Andreas Gruenbacher <agruenba@redhat.com> | 2025-11-26 23:52:28 +0000 |
| commit | 83348905e4137742c93bfd8104ce71c637121d38 (patch) | |
| tree | b99f3a9ed3db3f7efcbc67ce84e31336db22a264 | |
| parent | 16c31979840399e6e5542f861c6fb18f9086f3c9 (diff) | |
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>
| -rw-r--r-- | fs/gfs2/lops.c | 3 | ||||
| -rw-r--r-- | fs/gfs2/trans.c | 23 | ||||
| -rw-r--r-- | fs/gfs2/util.c | 43 |
3 files changed, 33 insertions, 36 deletions
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index c7ee4c16d1eb..d27a0b1080a9 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -210,9 +210,6 @@ static void gfs2_end_log_write(struct bio *bio) fs_err(sdp, "Error %d writing to journal, jid=%u\n", err, sdp->sd_jdesc->jd_jid); 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) { diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 1cce8e0f85da..6df65540e13d 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -49,7 +49,7 @@ int __gfs2_trans_begin(struct gfs2_trans *tr, struct gfs2_sbd *sdp, } BUG_ON(blocks == 0 && revokes == 0); - if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) + if (gfs2_withdrawn(sdp)) return -EROFS; 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); + if (unlikely(!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))) + goto out_not_live; if (gfs2_log_try_reserve(sdp, tr, &extra_revokes)) goto reserved; + up_read(&sdp->sd_log_flush_lock); gfs2_log_reserve(sdp, tr, &extra_revokes); down_read(&sdp->sd_log_flush_lock); - -reserved: - gfs2_log_release_revokes(sdp, extra_revokes); if (unlikely(!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))) { - gfs2_log_release_revokes(sdp, tr->tr_revokes); - up_read(&sdp->sd_log_flush_lock); + revokes = tr->tr_revokes + extra_revokes; + gfs2_log_release_revokes(sdp, revokes); gfs2_log_release(sdp, tr->tr_reserved); - sb_end_intwrite(sdp->sd_vfs); - return -EROFS; + goto out_not_live; } +reserved: + gfs2_log_release_revokes(sdp, extra_revokes); current->journal_info = tr; - return 0; + +out_not_live: + up_read(&sdp->sd_log_flush_lock); + sb_end_intwrite(sdp->sd_vfs); + return -EROFS; } int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index b8ce04338b24..02603200846d 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -117,35 +117,30 @@ void gfs2_freeze_unlock(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 */ - /* - * 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_quota_wait); + wake_up(&sdp->sd_logd_waitq); + wake_up(&sdp->sd_quota_wait); - wait_event_timeout(sdp->sd_log_waitq, - gfs2_log_is_empty(sdp), - HZ * 5); + wait_event_timeout(sdp->sd_log_waitq, + gfs2_log_is_empty(sdp), + HZ * 5); - sdp->sd_vfs->s_flags |= SB_RDONLY; + sdp->sd_vfs->s_flags |= SB_RDONLY; - /* - * Dequeue any pending non-system glock holders that can no - * longer be granted because the file system is withdrawn. - */ - gfs2_withdraw_glocks(sdp); - } + /* + * Dequeue any pending non-system glock holders that can no + * longer be granted because the file system is withdrawn. + */ + gfs2_withdraw_glocks(sdp); } void gfs2_lm(struct gfs2_sbd *sdp, const char *fmt, ...) |
