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 PATCH v3 18/19] gfs2: Check for log write errors before telling dlm to unlock
Date: Tue, 30 Apr 2019 17:03:18 -0600	[thread overview]
Message-ID: <20190430230319.10375-19-rpeterso@redhat.com> (raw)
In-Reply-To: <20190430230319.10375-1-rpeterso@redhat.com>

Before this patch, function do_xmote just assumed all the writes
submitted to the journal were finished and successful, and it
called the go_unlock function to release the dlm lock. But if
they're not, and a revoke failed to make its way to the journal,
a journal replay on another node will cause corruption if we
let the go_inval function continue and tell dlm to release the
glock to another node. This patch adds a couple checks for errors
in do_xmote after the calls to go_sync and go_inval. If an error
is found, we cannot withdraw yet, because the withdraw itself
uses glocks to make the file system read-only. Instead, we flag
the error. Later, asserts should cause another node to replay
the journal before continuing, thus protecting rgrp and dinode
glocks and maintaining the integrity of the metadata. Note that
we only need to do this for journaled glocks. System glocks
should be able to progress even under withdrawn conditions.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
 fs/gfs2/glock.c | 44 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 3d1b9bdfd0de..f4129305a815 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -570,8 +570,47 @@ __acquires(&gl->gl_lockref.lock)
 	spin_unlock(&gl->gl_lockref.lock);
 	if (glops->go_sync)
 		glops->go_sync(gl);
+	/**
+	 * Check for an error encountered since we called go_sync. If so, we
+	 * can't withdraw from the glock code because the withdraw code itself
+	 * uses glocks (see function signal_our_withdraw) to change the mount
+	 * to read-only. Most importantly, we must not call dlm to unlock the
+	 * glock until the journal is in a known good state (after journal
+	 * replay) otherwise other nodes may use the object (rgrp or dinode)
+	 * and then later, journal replay will corrupt the file system. The
+	 * best we can do now is wait for the logd daemon to see sd_log_error
+	 * and withdraw, and in the meantime, requeue the work for later.
+	 */
+	if ((glops->go_flags & GLOF_JOURNALED) && sdp->sd_log_error) {
+		gfs2_glock_hold(gl);
+		finish_xmote(gl, LM_OUT_ERROR | LM_ST_UNLOCKED);
+		gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
+		goto out;
+	}
 	if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
 		glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA);
+	/**
+	 * If the go_inval left some items on the ail, that's a problem. We
+	 * need to withdraw, but we can't, as explained above. Warn about the
+	 * error, dump the glock, then fall through and wait for logd to do
+	 * the withdraw for us.
+	 */
+	if (atomic_read(&gl->gl_ail_count) != 0) {
+		if (!cmpxchg(&sdp->sd_log_error, 0, -EIO)) {
+			gfs2_assert_warn(sdp, !atomic_read(&gl->gl_ail_count));
+			gfs2_dump_glock(NULL, gl);
+		}
+	}
+	/**
+	 * Check for an error encountered while we were doing go_inval, and
+	 * handle it the same way we did for the go_sync case.
+	 */
+	if ((glops->go_flags & GLOF_JOURNALED) && sdp->sd_log_error) {
+		gfs2_glock_hold(gl);
+		finish_xmote(gl, LM_OUT_ERROR | LM_ST_UNLOCKED);
+		gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
+		goto out;
+	}
 	clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
 
 	gfs2_glock_hold(gl);
@@ -583,8 +622,7 @@ __acquires(&gl->gl_lockref.lock)
 		    test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags)) {
 			finish_xmote(gl, target);
 			gfs2_glock_queue_work(gl, 0);
-		}
-		else if (ret) {
+		} else if (ret) {
 			fs_err(sdp, "lm_lock ret %d\n", ret);
 			GLOCK_BUG_ON(gl, !gfs2_withdrawn(sdp));
 		}
@@ -592,7 +630,7 @@ __acquires(&gl->gl_lockref.lock)
 		finish_xmote(gl, target);
 		gfs2_glock_queue_work(gl, 0);
 	}
-
+out:
 	spin_lock(&gl->gl_lockref.lock);
 }
 
-- 
2.20.1



  parent reply	other threads:[~2019-04-30 23:03 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-30 23:03 [Cluster-devel] [GFS2 PATCH v3 00/19] gfs2: misc recovery patch collection Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 01/19] gfs2: kthread and remount improvements Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 02/19] gfs2: eliminate tr_num_revoke_rm Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 03/19] gfs2: log which portion of the journal is replayed Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 04/19] gfs2: Warn when a journal replay overwrites a rgrp with buffers Bob Peterson
2019-05-07 14:26   ` Andreas Gruenbacher
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 05/19] gfs2: Introduce concept of a pending withdraw Bob Peterson
2019-05-07 14:36   ` Andreas Gruenbacher
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 06/19] gfs2: log error reform Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 07/19] gfs2: Only complain the first time an io error occurs in quota or log Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 08/19] gfs2: Stop ail1 wait loop when withdrawn Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 09/19] gfs2: Ignore recovery attempts if gfs2 has io error or is withdrawn Bob Peterson
2019-05-01  0:08   ` Steven Whitehouse
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 10/19] gfs2: move check_journal_clean to util.c for future use Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 11/19] gfs2: Allow some glocks to be used during withdraw Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 12/19] gfs2: Don't loop forever in gfs2_freeze if withdrawn Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 13/19] gfs2: Make secondary withdrawers wait for first withdrawer Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 14/19] gfs2: Don't write log headers after file system withdraw Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 15/19] gfs2: Force withdraw to replay journals and wait for it to finish Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 16/19] gfs2: simply gfs2_freeze by removing case Bob Peterson
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 17/19] gfs2: Add verbose option to check_journal_clean Bob Peterson
2019-04-30 23:03 ` Bob Peterson [this message]
2019-04-30 23:03 ` [Cluster-devel] [GFS2 PATCH v3 19/19] gfs2: Do log_flush in gfs2_ail_empty_gl even if ail list is empty Bob Peterson
2019-05-01  0:10 ` [Cluster-devel] [GFS2 PATCH v3 00/19] gfs2: misc recovery patch collection Steven Whitehouse

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=20190430230319.10375-19-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).