gfs2: flesh out delayed withdraw for gfs2_log_flush

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>
This commit is contained in:
Bob Peterson 2020-01-08 11:37:30 -06:00
parent 1c634f94c3
commit ca399c96e9
3 changed files with 41 additions and 12 deletions

View 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); INIT_LIST_HEAD(&tr->tr_ail2_list);
tr->tr_first = sdp->sd_log_flush_head; tr->tr_first = sdp->sd_log_flush_head;
if (unlikely (state == SFS_FROZEN)) 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)) if (unlikely(state == SFS_FROZEN))
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); if (gfs2_assert_withdraw_delayed(sdp, !sdp->sd_log_num_revoke))
gfs2_assert_withdraw(sdp, goto out;
sdp->sd_log_num_revoke == sdp->sd_log_committed_revoke); if (gfs2_assert_withdraw_delayed(sdp,
sdp->sd_log_num_revoke == sdp->sd_log_committed_revoke))
goto out;
gfs2_ordered_write(sdp); gfs2_ordered_write(sdp);
if (gfs2_withdrawn(sdp)) if (gfs2_withdrawn(sdp))

View File

@ -318,13 +318,28 @@ int gfs2_withdraw(struct gfs2_sbd *sdp)
*/ */
void gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion, 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, if (gfs2_withdrawn(sdp))
"fatal: assertion \"%s\" failed\n" return;
" function = %s, file = %s, line = %u\n",
assertion, function, file, line); fs_err(sdp,
gfs2_withdraw(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(); dump_stack();
} }

View File

@ -37,14 +37,24 @@ do { \
void gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion, 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) \ #define gfs2_assert_withdraw(sdp, assertion) \
({ \ ({ \
bool _bool = (assertion); \ bool _bool = (assertion); \
if (unlikely(!_bool)) \ if (unlikely(!_bool)) \
gfs2_assert_withdraw_i((sdp), #assertion, \ 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; \ !_bool; \
}) })