cluster-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
From: Andreas Gruenbacher <agruenba@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [PATCH 05/11] gfs2: Give up the iopen glock on contention
Date: Mon, 20 Jan 2020 10:12:59 +0100	[thread overview]
Message-ID: <20200120091305.24997-6-agruenba@redhat.com> (raw)
In-Reply-To: <20200120091305.24997-1-agruenba@redhat.com>

When there's contention on the iopen glock, it means that the link count
of the corresponding inode has dropped to zero on a remote node and that
node is trying to delete the inode.  In that case, try to evict the
inode so that the iopen glock will be released and give the remote node
some time to delete the inode itself.

When the inode is still open, the inode's reference count won't drop to
zero, and we'll keep hold of the inode and its iopen glock.  The remote
node will time out its request to grab the iopen glock, and when the
inode is closed, we'll try to delete it ourself.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/gfs2/glock.c  | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/gfs2/incore.h |  1 +
 fs/gfs2/super.c  |  7 +++++--
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index e71f23ebb99b..38ba77b35b50 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -696,6 +696,42 @@ bool gfs2_inode_already_deleted(struct gfs2_glock *gl, u64 generation)
 	return generation <= be64_to_cpu(ri->ri_generation_deleted);
 }
 
+static bool gfs2_try_evict(struct gfs2_glock *gl)
+{
+	struct gfs2_inode *ip;
+	bool evicted = false;
+
+	/*
+	 * If there is contention on the iopen glock and we have an inode, try
+	 * to grab and release the inode so that it can be evicted.  This will
+	 * allow the remote node to go ahead and delete the inode without us
+	 * having to do it, which will avoid rgrp glock thrashing.
+	 *
+	 * The remote node is likely still holding the corresponding inode
+	 * glock, so it will run before we get to verify that the delete has
+	 * happened below.
+	 */
+	spin_lock(&gl->gl_lockref.lock);
+	ip = gl->gl_object;
+	if (ip && !igrab(&ip->i_inode))
+		ip = NULL;
+	spin_unlock(&gl->gl_lockref.lock);
+	if (ip) {
+		set_bit(GIF_DEFERRED_DELETE, &ip->i_flags);
+		d_prune_aliases(&ip->i_inode);
+		iput(&ip->i_inode);
+
+		/* If the inode was evicted, gl->gl_object will now be NULL. */
+		spin_lock(&gl->gl_lockref.lock);
+		ip = gl->gl_object;
+		if (ip)
+			clear_bit(GIF_DEFERRED_DELETE, &ip->i_flags);
+		spin_unlock(&gl->gl_lockref.lock);
+		evicted = !ip;
+	}
+	return evicted;
+}
+
 static void delete_work_func(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
@@ -710,6 +746,22 @@ static void delete_work_func(struct work_struct *work)
 	if (test_bit(GLF_INODE_CREATING, &gl->gl_flags))
 		goto out;
 
+	if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
+		/*
+		 * If we can evict the inode, give the remote node trying to
+		 * delete the inode some time before verifying that the delete
+		 * has happened.  If we cause contention on the inode glock
+		 * immediately, the remote node will think that we still have
+		 * the inode in use, and so it will give up waiting.
+		 */
+		if (gfs2_try_evict(gl)) {
+			if (queue_delayed_work(gfs2_delete_workqueue,
+					       &gl->gl_delete, 5 * HZ))
+				return;
+			goto out;
+		}
+	}
+
 	inode = gfs2_lookup_by_inum(sdp, no_addr, NULL, GFS2_BLKST_UNLINKED);
 	if (!IS_ERR_OR_NULL(inode)) {
 		d_prune_aliases(inode);
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index d7282356cbf5..aecdde83c22c 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -397,6 +397,7 @@ enum {
 	GIF_ORDERED		= 4,
 	GIF_FREE_VFS_INODE      = 5,
 	GIF_GLOP_PENDING	= 6,
+	GIF_DEFERRED_DELETE	= 7,
 };
 
 struct gfs2_inode {
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 1a029beaaaca..874949b17495 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1263,9 +1263,12 @@ static void gfs2_evict_inode(struct inode *inode)
 	if (test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) {
 		BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));
 		gfs2_holder_mark_uninitialized(&gh);
-		goto alloc_failed;
+		goto out_delete;
 	}
 
+	if (test_bit(GIF_DEFERRED_DELETE, &ip->i_flags))
+		goto out;
+
 	/* Deletes should never happen under memory pressure anymore.  */
 	if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))
 		goto out;
@@ -1297,7 +1300,7 @@ static void gfs2_evict_inode(struct inode *inode)
 	if (inode->i_nlink)
 		goto out_truncate;
 
-alloc_failed:
+out_delete:
 	if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
 	    test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
 		ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
-- 
2.20.1



  parent reply	other threads:[~2020-01-20  9:12 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-20  9:12 [Cluster-devel] [PATCH 00/11] gfs2: iopen glock locking scheme rework Andreas Gruenbacher
2020-01-20  9:12 ` [Cluster-devel] [PATCH 01/11] gfs2: Allow ASPACE glocks to also have an lvb Andreas Gruenbacher
2020-01-20  9:12 ` [Cluster-devel] [PATCH 02/11] gfs2: Don't add glocks to the LRU while still in use Andreas Gruenbacher
2020-01-20  9:12 ` [Cluster-devel] [PATCH 03/11] gfs2: Keep track of deletes in inode LVBs Andreas Gruenbacher
2020-01-20  9:12 ` [Cluster-devel] [PATCH 04/11] gfs2: Turn gl_delete into a delayed work Andreas Gruenbacher
2020-01-20  9:12 ` Andreas Gruenbacher [this message]
2020-01-20  9:13 ` [Cluster-devel] [PATCH 06/11] gfs2: Try harder to delete inodes locally Andreas Gruenbacher
2020-01-20  9:13 ` [Cluster-devel] [PATCH 07/11] gfs2: Minor gfs2_lookup_by_inum cleanup Andreas Gruenbacher
2020-01-20  9:13 ` [Cluster-devel] [PATCH 08/11] gfs2: Move inode generation number check into gfs2_inode_lookup Andreas Gruenbacher
2020-01-20  9:13 ` [Cluster-devel] [PATCH 09/11] gfs2: Check inode generation number in delete_work_func Andreas Gruenbacher
2020-01-20  9:13 ` [Cluster-devel] [PATCH 10/11] gfs2: Wake up when setting GLF_DEMOTE Andreas Gruenbacher
2020-01-20  9:13 ` [Cluster-devel] [PATCH 11/11] gfs2: Smarter iopen glock waiting Andreas Gruenbacher
2020-01-23 12:41 ` [Cluster-devel] [PATCH 08/11] gfs2: Move inode generation number check into gfs2_inode_lookup Andreas Gruenbacher

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=20200120091305.24997-6-agruenba@redhat.com \
    --to=agruenba@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).