gfs2: flesh out delayed withdraw for gfs2_log_flush
authorBob Peterson <rpeterso@redhat.com>
Wed, 8 Jan 2020 17:37:30 +0000 (11:37 -0600)
committerBob Peterson <rpeterso@redhat.com>
Thu, 27 Feb 2020 13:53:18 +0000 (07:53 -0600)
Function gfs2_log_flush() had a few places where it tried to withdraw
from the file system when errors were encountered. The problem is,
it should delay those withdraws until the log flush lock is no longer
held.

This patch creates a new function just for delayed withdraws for
situations like this. If errors=panic was specified on mount, we
still want to do it the old fashioned way because the panic it does
not help to delay in that situation.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/log.c
fs/gfs2/util.c
fs/gfs2/util.h

index 010c319caade4c7b388ccdc3247bf3cec4a82e35..67465a34954eecdfec55133df11f4429c124ab98 100644 (file)
@@ -872,13 +872,17 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
                INIT_LIST_HEAD(&tr->tr_ail2_list);
                tr->tr_first = sdp->sd_log_flush_head;
                if (unlikely (state == SFS_FROZEN))
-                       gfs2_assert_withdraw(sdp, !tr->tr_num_buf_new && !tr->tr_num_databuf_new);
+                       if (gfs2_assert_withdraw_delayed(sdp,
+                              !tr->tr_num_buf_new && !tr->tr_num_databuf_new))
+                               goto out;
        }
 
        if (unlikely(state == SFS_FROZEN))
-               gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
-       gfs2_assert_withdraw(sdp,
-                       sdp->sd_log_num_revoke == sdp->sd_log_committed_revoke);
+               if (gfs2_assert_withdraw_delayed(sdp, !sdp->sd_log_num_revoke))
+                       goto out;
+       if (gfs2_assert_withdraw_delayed(sdp,
+                       sdp->sd_log_num_revoke == sdp->sd_log_committed_revoke))
+               goto out;
 
        gfs2_ordered_write(sdp);
        if (gfs2_withdrawn(sdp))
index 20a5860841e2c811f76dbac66a04ad6cef9801c3..9b64d40ab379391ba3a668974ec9954910824b18 100644 (file)
@@ -318,13 +318,28 @@ int gfs2_withdraw(struct gfs2_sbd *sdp)
  */
 
 void gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
-                           const char *function, char *file, unsigned int line)
+                           const char *function, char *file, unsigned int line,
+                           bool delayed)
 {
-       gfs2_lm(sdp,
-               "fatal: assertion \"%s\" failed\n"
-               "   function = %s, file = %s, line = %u\n",
-               assertion, function, file, line);
-       gfs2_withdraw(sdp);
+       if (gfs2_withdrawn(sdp))
+               return;
+
+       fs_err(sdp,
+              "fatal: assertion \"%s\" failed\n"
+              "   function = %s, file = %s, line = %u\n",
+              assertion, function, file, line);
+
+       /*
+        * If errors=panic was specified on mount, it won't help to delay the
+        * withdraw.
+        */
+       if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
+               delayed = false;
+
+       if (delayed)
+               gfs2_withdraw_delayed(sdp);
+       else
+               gfs2_withdraw(sdp);
        dump_stack();
 }
 
index 97117a766bde9cde0ec096118aa0ba322b9951c9..a3542560da6ffdc25f6ab97f79cbec7028aaf875 100644 (file)
@@ -37,14 +37,24 @@ do { \
 
 
 void gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
-                           const char *function, char *file, unsigned int line);
+                           const char *function, char *file, unsigned int line,
+                           bool delayed);
 
 #define gfs2_assert_withdraw(sdp, assertion) \
        ({ \
                bool _bool = (assertion); \
                if (unlikely(!_bool)) \
                        gfs2_assert_withdraw_i((sdp), #assertion, \
-                                       __func__, __FILE__, __LINE__); \
+                                       __func__, __FILE__, __LINE__, false); \
+               !_bool; \
+       })
+
+#define gfs2_assert_withdraw_delayed(sdp, assertion) \
+       ({ \
+               bool _bool = (assertion); \
+               if (unlikely(!_bool)) \
+                       gfs2_assert_withdraw_i((sdp), #assertion, \
+                                       __func__, __FILE__, __LINE__, true); \
                !_bool; \
        })