]> Gentwo Git Trees - linux/.git/commitdiff
gfs2: Clean up SDF_JOURNAL_LIVE flag handling
authorAndreas Gruenbacher <agruenba@redhat.com>
Wed, 29 Oct 2025 21:00:18 +0000 (21:00 +0000)
committerAndreas Gruenbacher <agruenba@redhat.com>
Wed, 26 Nov 2025 23:52:28 +0000 (23:52 +0000)
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>
fs/gfs2/lops.c
fs/gfs2/trans.c
fs/gfs2/util.c

index c7ee4c16d1eba388624c17f34f77f8d090d24689..d27a0b1080a97f446832687b46b7d9afa3e77237 100644 (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",
                               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) {
index 1cce8e0f85da4d553533acd735bcdb9197a3391f..6df65540e13d7829153695da4969b4e63264b73d 100644 (file)
@@ -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,
index b8ce04338b24a4fdad797d903979e97290113894..02603200846d6fa161ea3124557e37a7d1ee4324 100644 (file)
@@ -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, ...)