cluster-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
From: Bob Peterson <rpeterso@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [GFS2 v8 PATCH 01/22] gfs2: Introduce concept of a pending withdraw
Date: Mon,  9 Dec 2019 09:36:39 -0600	[thread overview]
Message-ID: <20191209153700.700208-2-rpeterso@redhat.com> (raw)
In-Reply-To: <20191209153700.700208-1-rpeterso@redhat.com>

File system withdraws can be delayed when inconsistencies are
discovered when we cannot withdraw immediately, for example, when
critical spin_locks are held. But delaying the withdraw can cause
gfs2 to ignore the error and keep running for a short period of time.
For example, an rgrp glock may be dequeued and demoted while there
are still buffers that haven't been properly revoked, due to io
errors writing to the journal.

This patch introduces a new concept of a pending withdraw, which
means an inconsistency has been discovered and we need to withdraw
at the earliest possible opportunity. In these cases, we aren't
quite withdrawn yet, but we still need to not dequeue glocks and
other critical things. If we dequeue the glocks and the withdraw
results in our journal being replayed, the replay could overwrite
data that's been modified by a different node that acquired the
glock in the meantime.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
 fs/gfs2/incore.h |  1 +
 fs/gfs2/log.c    | 21 ++++++++-------------
 fs/gfs2/util.c   | 14 +++++++-------
 fs/gfs2/util.h   |  3 ++-
 4 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 5f89c515f5bb..6042babb7324 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -619,6 +619,7 @@ enum {
 	SDF_FORCE_AIL_FLUSH     = 9,
 	SDF_AIL1_IO_ERROR	= 10,
 	SDF_FS_FROZEN           = 11,
+	SDF_WITHDRAWING		= 12, /* Will withdraw eventually */
 };
 
 enum gfs2_freeze_state {
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index eb3f2e7b8085..38a03c2203de 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -91,8 +91,7 @@ static void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
 
 static int gfs2_ail1_start_one(struct gfs2_sbd *sdp,
 			       struct writeback_control *wbc,
-			       struct gfs2_trans *tr,
-			       bool *withdraw)
+			       struct gfs2_trans *tr)
 __releases(&sdp->sd_ail_lock)
 __acquires(&sdp->sd_ail_lock)
 {
@@ -111,7 +110,7 @@ __acquires(&sdp->sd_ail_lock)
 			    !test_and_set_bit(SDF_AIL1_IO_ERROR,
 					      &sdp->sd_flags)) {
 				gfs2_io_error_bh(sdp, bh);
-				*withdraw = true;
+				set_bit(SDF_WITHDRAWING, &sdp->sd_flags);
 			}
 			list_move(&bd->bd_ail_st_list, &tr->tr_ail2_list);
 			continue;
@@ -152,7 +151,6 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
 	struct list_head *head = &sdp->sd_ail1_list;
 	struct gfs2_trans *tr;
 	struct blk_plug plug;
-	bool withdraw = false;
 
 	trace_gfs2_ail_flush(sdp, wbc, 1);
 	blk_start_plug(&plug);
@@ -161,13 +159,12 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
 	list_for_each_entry_reverse(tr, head, tr_list) {
 		if (wbc->nr_to_write <= 0)
 			break;
-		if (gfs2_ail1_start_one(sdp, wbc, tr, &withdraw) &&
-		    !gfs2_withdrawn(sdp))
+		if (gfs2_ail1_start_one(sdp, wbc, tr) && !gfs2_withdrawn(sdp))
 			goto restart;
 	}
 	spin_unlock(&sdp->sd_ail_lock);
 	blk_finish_plug(&plug);
-	if (withdraw)
+	if (test_bit(SDF_WITHDRAWING, &sdp->sd_flags))
 		gfs2_lm_withdraw(sdp, NULL);
 	trace_gfs2_ail_flush(sdp, wbc, 0);
 }
@@ -196,8 +193,7 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp)
  *
  */
 
-static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr,
-				bool *withdraw)
+static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
 	struct gfs2_bufdata *bd, *s;
 	struct buffer_head *bh;
@@ -211,7 +207,7 @@ static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr,
 		if (!buffer_uptodate(bh) &&
 		    !test_and_set_bit(SDF_AIL1_IO_ERROR, &sdp->sd_flags)) {
 			gfs2_io_error_bh(sdp, bh);
-			*withdraw = true;
+			set_bit(SDF_WITHDRAWING, &sdp->sd_flags);
 		}
 		list_move(&bd->bd_ail_st_list, &tr->tr_ail2_list);
 	}
@@ -229,11 +225,10 @@ static int gfs2_ail1_empty(struct gfs2_sbd *sdp)
 	struct gfs2_trans *tr, *s;
 	int oldest_tr = 1;
 	int ret;
-	bool withdraw = false;
 
 	spin_lock(&sdp->sd_ail_lock);
 	list_for_each_entry_safe_reverse(tr, s, &sdp->sd_ail1_list, tr_list) {
-		gfs2_ail1_empty_one(sdp, tr, &withdraw);
+		gfs2_ail1_empty_one(sdp, tr);
 		if (list_empty(&tr->tr_ail1_list) && oldest_tr)
 			list_move(&tr->tr_list, &sdp->sd_ail2_list);
 		else
@@ -242,7 +237,7 @@ static int gfs2_ail1_empty(struct gfs2_sbd *sdp)
 	ret = list_empty(&sdp->sd_ail1_list);
 	spin_unlock(&sdp->sd_ail_lock);
 
-	if (withdraw)
+	if (test_bit(SDF_WITHDRAWING, &sdp->sd_flags))
 		gfs2_lm_withdraw(sdp, "fatal: I/O error(s)\n");
 
 	return ret;
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index ec600b487498..7305a7036c3e 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -258,13 +258,13 @@ void gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
 			const char *function, char *file, unsigned int line,
 			bool withdraw)
 {
-	if (!gfs2_withdrawn(sdp))
-		fs_err(sdp,
-		       "fatal: I/O error\n"
-		       "  block = %llu\n"
-		       "  function = %s, file = %s, line = %u\n",
-		       (unsigned long long)bh->b_blocknr,
-		       function, file, line);
+	if (gfs2_withdrawn(sdp))
+		return;
+
+	fs_err(sdp, "fatal: I/O error\n"
+	       "  block = %llu\n"
+	       "  function = %s, file = %s, line = %u\n",
+	       (unsigned long long)bh->b_blocknr, function, file, line);
 	if (withdraw)
 		gfs2_lm_withdraw(sdp, NULL);
 }
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
index f2702bc9837c..c0ea08c2beee 100644
--- a/fs/gfs2/util.h
+++ b/fs/gfs2/util.h
@@ -170,7 +170,8 @@ static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
  */
 static inline bool gfs2_withdrawn(struct gfs2_sbd *sdp)
 {
-	return test_bit(SDF_WITHDRAWN, &sdp->sd_flags);
+	return test_bit(SDF_WITHDRAWN, &sdp->sd_flags) ||
+		test_bit(SDF_WITHDRAWING, &sdp->sd_flags);
 }
 
 #define gfs2_tune_get(sdp, field) \
-- 
2.23.0



  reply	other threads:[~2019-12-09 15:36 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-09 15:36 [Cluster-devel] [GFS2 v8 PATCH 00/22] GFS2 Recovery corruption patches v8 Bob Peterson
2019-12-09 15:36 ` Bob Peterson [this message]
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 02/22] gfs2: clear ail1 list when gfs2 withdraws Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 03/22] gfs2: Rework how rgrp buffer_heads are managed Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 04/22] gfs2: log error reform Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 05/22] gfs2: Only complain the first time an io error occurs in quota or log Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 06/22] gfs2: Ignore dlm recovery requests if gfs2 is withdrawn Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 07/22] gfs2: move check_journal_clean to util.c for future use Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 08/22] gfs2: Allow some glocks to be used during withdraw Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 09/22] gfs2: Make secondary withdrawers wait for first withdrawer Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 10/22] gfs2: Force withdraw to replay journals and wait for it to finish Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 11/22] gfs2: fix infinite loop when checking ail item count before go_inval Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 12/22] gfs2: Add verbose option to check_journal_clean Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 13/22] gfs2: Issue revokes more intelligently Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 14/22] gfs2: Prepare to withdraw as soon as an IO error occurs in log write Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 15/22] gfs2: Check for log write errors before telling dlm to unlock Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 16/22] gfs2: new slab for transactions Bob Peterson
2020-01-23 22:22   ` Andreas Gruenbacher
2020-01-24 13:45     ` Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 17/22] gfs2: Do log_flush in gfs2_ail_empty_gl even if ail list is empty Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 18/22] gfs2: Don't skip log flush if glock still has revokes Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 19/22] gfs2: Withdraw in gfs2_ail1_flush if write_cache_pages returns error Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 20/22] gfs2: drain the ail2 list after io errors Bob Peterson
2019-12-09 15:36 ` [Cluster-devel] [GFS2 v8 PATCH 21/22] gfs2: Don't demote a glock until its revokes are written Bob Peterson
2019-12-09 15:37 ` [Cluster-devel] [GFS2 v8 PATCH 22/22] gfs2: Do proper error checking for go_sync family of glops functions Bob Peterson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191209153700.700208-2-rpeterso@redhat.com \
    --to=rpeterso@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).