All of lore.kernel.org
 help / color / mirror / Atom feed
From: Trond Myklebust <trond.myklebust@primarydata.com>
To: linux-nfs@vger.kernel.org
Subject: [PATCH 08/26] pNFS: Delay getting the layout header in CB_LAYOUTRECALL handlers
Date: Thu,  1 Dec 2016 17:19:04 -0500	[thread overview]
Message-ID: <20161201221922.15657-9-trond.myklebust@primarydata.com> (raw)
In-Reply-To: <20161201221922.15657-8-trond.myklebust@primarydata.com>

Instead of grabbing the layout, we want to get the inode so that we
can reduce races between layoutget and layoutrecall when the server
does not support call referring.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/callback_proc.c | 99 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 67 insertions(+), 32 deletions(-)

diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index e9aa235e9d10..f073a6d2c6a5 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -110,20 +110,52 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
 #if defined(CONFIG_NFS_V4_1)
 
 /*
- * Lookup a layout by filehandle.
+ * Lookup a layout inode by stateid
  *
- * Note: gets a refcount on the layout hdr and on its respective inode.
- * Caller must put the layout hdr and the inode.
+ * Note: returns a refcount on the inode and superblock
+ */
+static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp,
+		const nfs4_stateid *stateid)
+{
+	struct nfs_server *server;
+	struct inode *inode;
+	struct pnfs_layout_hdr *lo;
+
+restart:
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
+		list_for_each_entry(lo, &server->layouts, plh_layouts) {
+			if (stateid != NULL &&
+			    !nfs4_stateid_match_other(stateid, &lo->plh_stateid))
+				continue;
+			inode = igrab(lo->plh_inode);
+			if (!inode)
+				continue;
+			if (!nfs_sb_active(inode->i_sb)) {
+				rcu_read_lock();
+				spin_unlock(&clp->cl_lock);
+				iput(inode);
+				spin_lock(&clp->cl_lock);
+				goto restart;
+			}
+			return inode;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * Lookup a layout inode by filehandle.
+ *
+ * Note: returns a refcount on the inode and superblock
  *
- * TODO: keep track of all layouts (and delegations) in a hash table
- * hashed by filehandle.
  */
-static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
-		struct nfs_fh *fh)
+static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp,
+		const struct nfs_fh *fh)
 {
 	struct nfs_server *server;
 	struct nfs_inode *nfsi;
-	struct inode *ino;
+	struct inode *inode;
 	struct pnfs_layout_hdr *lo;
 
 restart:
@@ -134,37 +166,38 @@ static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
 				continue;
 			if (nfsi->layout != lo)
 				continue;
-			ino = igrab(lo->plh_inode);
-			if (!ino)
-				break;
-			spin_lock(&ino->i_lock);
-			/* Is this layout in the process of being freed? */
-			if (nfsi->layout != lo) {
-				spin_unlock(&ino->i_lock);
-				iput(ino);
+			inode = igrab(lo->plh_inode);
+			if (!inode)
+				continue;
+			if (!nfs_sb_active(inode->i_sb)) {
+				rcu_read_lock();
+				spin_unlock(&clp->cl_lock);
+				iput(inode);
+				spin_lock(&clp->cl_lock);
 				goto restart;
 			}
-			pnfs_get_layout_hdr(lo);
-			spin_unlock(&ino->i_lock);
-			return lo;
+			return inode;
 		}
 	}
 
 	return NULL;
 }
 
-static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp,
-		struct nfs_fh *fh)
+static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
+		const struct nfs_fh *fh,
+		const nfs4_stateid *stateid)
 {
-	struct pnfs_layout_hdr *lo;
+	struct inode *inode;
 
 	spin_lock(&clp->cl_lock);
 	rcu_read_lock();
-	lo = get_layout_by_fh_locked(clp, fh);
+	inode = nfs_layout_find_inode_by_stateid(clp, stateid);
+	if (!inode)
+		inode = nfs_layout_find_inode_by_fh(clp, fh);
 	rcu_read_unlock();
 	spin_unlock(&clp->cl_lock);
 
-	return lo;
+	return inode;
 }
 
 /*
@@ -213,18 +246,20 @@ static u32 initiate_file_draining(struct nfs_client *clp,
 	u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
 	LIST_HEAD(free_me_list);
 
-	lo = get_layout_by_fh(clp, &args->cbl_fh);
-	if (!lo) {
-		trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, NULL,
-				&args->cbl_stateid, -rv);
+	ino = nfs_layout_find_inode(clp, &args->cbl_fh, &args->cbl_stateid);
+	if (!ino)
 		goto out;
-	}
 
-	ino = lo->plh_inode;
 	pnfs_layoutcommit_inode(ino, false);
 
 
 	spin_lock(&ino->i_lock);
+	lo = NFS_I(ino)->layout;
+	if (!lo) {
+		spin_unlock(&ino->i_lock);
+		goto out;
+	}
+	pnfs_get_layout_hdr(lo);
 	rv = pnfs_check_callback_stateid(lo, &args->cbl_stateid);
 	if (rv != NFS_OK)
 		goto unlock;
@@ -258,10 +293,10 @@ static u32 initiate_file_draining(struct nfs_client *clp,
 	/* Free all lsegs that are attached to commit buckets */
 	nfs_commit_inode(ino, 0);
 	pnfs_put_layout_hdr(lo);
+out:
 	trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
 			&args->cbl_stateid, -rv);
-	iput(ino);
-out:
+	nfs_iput_and_deactive(ino);
 	return rv;
 }
 
-- 
2.9.3


  reply	other threads:[~2016-12-01 22:19 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-01 22:18 [PATCH 00/26] pNFS updates for v4.10 Trond Myklebust
2016-12-01 22:18 ` [PATCH 01/26] pNFS: Fix a deadlock between read resends and layoutreturn Trond Myklebust
2016-12-01 22:18   ` [PATCH 02/26] pNFS: Don't clear the layout stateid if a layout return is outstanding Trond Myklebust
2016-12-01 22:18     ` [PATCH 03/26] pNFS: Clear NFS_LAYOUT_RETURN_REQUESTED when invalidating the layout stateid Trond Myklebust
2016-12-01 22:19       ` [PATCH 04/26] pNFS: Force a retry of LAYOUTGET if the stateid doesn't match our cache Trond Myklebust
2016-12-01 22:19         ` [PATCH 05/26] pNFS: On error, do not send LAYOUTGET until the LAYOUTRETURN has completed Trond Myklebust
2016-12-01 22:19           ` [PATCH 06/26] pNFS: Fix race in pnfs_wait_on_layoutreturn Trond Myklebust
2016-12-01 22:19             ` [PATCH 07/26] pNFS: consolidate the different range intersection tests Trond Myklebust
2016-12-01 22:19               ` Trond Myklebust [this message]
2016-12-01 22:19                 ` [PATCH 09/26] pNFS: Do not free layout segments that are marked for return Trond Myklebust
2016-12-01 22:19                   ` [PATCH 10/26] NFSv4: Ignore LAYOUTRETURN result if the layout doesn't match or is invalid Trond Myklebust
2016-12-01 22:19                     ` [PATCH 11/26] pNFS: Remove spurious wake up in pnfs_layout_remove_lseg() Trond Myklebust
2016-12-01 22:19                       ` [PATCH 12/26] pNFS: Skip checking for return-on-close if the layout is invalid Trond Myklebust
2016-12-01 22:19                         ` [PATCH 13/26] pNFS: Get rid of unnecessary layout parameter in encode_layoutreturn callback Trond Myklebust
2016-12-01 22:19                           ` [PATCH 14/26] pNFS: Don't mark layout segments invalid on layoutreturn in pnfs_roc Trond Myklebust
2016-12-01 22:19                             ` [PATCH 15/26] NFSv4: Fix missing operation accounting in NFS4_dec_delegreturn_sz Trond Myklebust
2016-12-01 22:19                               ` [PATCH 16/26] NFSv4: Add encode/decode of the layoutreturn op in CLOSE Trond Myklebust
2016-12-01 22:19                                 ` [PATCH 17/26] NFSv4: Add encode/decode of the layoutreturn op in DELEGRETURN Trond Myklebust
2016-12-01 22:19                                   ` [PATCH 18/26] pNFS: Clean up - add a helper to initialise struct layoutreturn_args Trond Myklebust
2016-12-01 22:19                                     ` [PATCH 19/26] pNFS: Enable layoutreturn operation for return-on-close Trond Myklebust
2016-12-01 22:19                                       ` [PATCH 20/26] pNFS: Prevent unnecessary layoutreturns after delegreturn Trond Myklebust
2016-12-01 22:19                                         ` [PATCH 21/26] pNFS: Clear all layout segment state in pnfs_mark_layout_stateid_invalid Trond Myklebust
2016-12-01 22:19                                           ` [PATCH 22/26] pNFS: Fix bugs in _pnfs_return_layout Trond Myklebust
2016-12-01 22:19                                             ` [PATCH 23/26] pNFS: Sync the layout state bits in pnfs_cache_lseg_for_layoutreturn Trond Myklebust
2016-12-01 22:19                                               ` [PATCH 24/26] pNFS: Don't mark the layout as freed if the last lseg is marked for return Trond Myklebust
2016-12-01 22:19                                                 ` [PATCH 25/26] pNFS: Wait on outstanding layoutreturns to complete in pnfs_roc() Trond Myklebust
2016-12-01 22:19                                                   ` [PATCH 26/26] pNFS: Skip invalid stateids when doing a bulk destroy Trond Myklebust

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=20161201221922.15657-9-trond.myklebust@primarydata.com \
    --to=trond.myklebust@primarydata.com \
    --cc=linux-nfs@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.