[pnfs] [PATCH 03/10] pnfsd: process the layout stateid

andros at netapp.com andros at netapp.com
Wed May 7 16:53:38 EDT 2008


From: Andy Adamson <andros at umich.edu>

Common function for LAYOUTGET and LAYOUTRETURN layout stateid processing.

The 'first open, delegation, or lock stateid' presented by the client is
looked up for verification.

Both initial and non-initial parallel LAYOUTGET operations and parallel
LAYOUTRETURN operations are supported.

Note: layout stateid seqid checking is more lax than that specified in
draft-ietf-nfsv4-minorversion1-22 for Connectathon.

Signed-off-by: Andy Adamson<andros at netapp.com>
---
 fs/nfsd/nfs4state.c |  138 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 138 insertions(+), 0 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 608d5b2..68e1332 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4124,6 +4124,144 @@ find_get_layout_state(struct nfs4_client *clp, struct nfs4_file *fp)
 	return NULL;
 }
 
+static int
+verify_stateid(struct nfs4_file *fp, stateid_t *stateid)
+{
+	struct nfs4_stateid *local = NULL;
+	struct nfs4_delegation *temp = NULL;
+
+	/* check if open or lock stateid */
+	local = find_stateid(stateid, RD_STATE);
+	if (local)
+		return 0;
+	temp = find_delegation_stateid(fp->fi_inode, stateid);
+	if (temp)
+		return 0;
+	return nfserr_bad_stateid;
+}
+
+/*
+ * nfs4_preocess_layout_stateid ()
+ *
+ * We have looked up the nfs4_file corresponding to the current_fh, and
+ * confirmed the clientid. Pull the few tests from nfs4_preprocess_stateid_op()
+ * that make sense with a layout stateid.
+ *
+ * Called with the nfs_lock held.
+ * Returns zero and stateid is updated, or error.
+ *
+ * Note: the struct nfs4_layout_state pointer is only set by layoutget.
+ */
+static __be32
+nfs4_process_layout_stateid(struct nfs4_client *clp, struct nfs4_file *fp,
+			    stateid_t *stateid, struct nfs4_layout_state **lsp)
+{
+	struct nfs4_layout_state *ls = NULL;
+	int status = 0;
+
+	dprintk("--> %s clp %p fp %p \n", __func__, clp, fp);
+
+	dprintk("%s:  operation stateid=(%08x/%08x/%08x/%08x)\n\n", __func__,
+					stateid->si_boot,
+					stateid->si_stateownerid,
+					stateid->si_fileid,
+					stateid->si_generation);
+
+	/* STALE STATEID */
+	status = nfserr_stale_stateid;
+	if (STALE_STATEID(stateid))
+		goto out;
+
+	/* BAD STATEID */
+	status = nfserr_bad_stateid;
+	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
+		goto out;
+
+	/* Is this the first use of this layout ? */
+	ls = find_get_layout_state(clp, fp);
+	if (!ls) {
+		/* Only alloc layout state on layoutget (which sets lsp). */
+		if (!lsp) {
+			dprintk("%s ERROR: Not layoutget & no layout stateid\n",
+							__func__);
+			status = nfserr_bad_stateid;
+			goto out;
+		}
+		dprintk("%s Initial stateid for layout: file %p client %p\n",
+				__func__, fp, clp);
+
+		/* verify input stateid */
+		status = verify_stateid(fp, stateid);
+		if (status < 0) {
+			dprintk("%s ERROR: invalid open/deleg/lock stateid\n",
+							__func__);
+			goto out;
+		}
+		ls = alloc_init_layout_state(clp, fp, stateid);
+		if (!ls) {
+			dprintk("%s pNFS ERROR: no memory for layout state\n",
+							__func__);
+			status = nfserr_resource;
+			goto out;
+		}
+		dprintk("pNFS %s: before GET ls %p ls_ref %d\n",
+					__func__, ls,
+					atomic_read(&ls->ls_ref.refcount));
+		get_layout_state(ls);
+	} else {
+		dprintk("%s Not initial stateid. Layout state %p file %p\n",
+						__func__, ls, fp);
+
+		/* BAD STATEID */
+		status = nfserr_bad_stateid;
+		if (memcmp(&ls->ls_stateid.si_opaque, &stateid->si_opaque,
+		    sizeof(stateid_opaque_t)) != 0) {
+
+			/* if a LAYOUTGET operation and stateid is a valid
+			* open/deleg/lock stateid, accept it as a parallel
+			* initial layout stateid
+			*/
+			if (lsp && ((verify_stateid(fp, stateid)) == 0)) {
+				dprintk("%s parallel initial layout state\n",
+								__func__);
+				goto update;
+			}
+
+			dprintk("%s ERROR bad opaque in stateid 1\n", __func__);
+			goto out_put;
+		}
+
+		/* stateid is a valid layout stateid for this file. */
+		if (stateid->si_generation > ls->ls_stateid.si_generation) {
+			dprintk("%s bad stateid 1\n", __func__);
+			goto out_put;
+		}
+update:
+		update_stateid(&ls->ls_stateid);
+		dprintk("%s Updated ls_stateid to %d on layoutstate %p\n",
+				__func__, ls->ls_stateid.si_generation, ls);
+	}
+	status = 0;
+	/* Set the stateid to be encoded */
+	memcpy(stateid, &ls->ls_stateid, sizeof(stateid_t));
+
+/* Return the layout state if requested */
+	if (lsp)
+		*lsp = ls;
+out_put:
+	dprintk("%s PUT LO STATE:\n", __func__);
+	put_layout_state(ls);
+out:
+	dprintk("<-- %s status %d\n", __func__, htonl(status));
+	dprintk("%s: layout stateid=(%08x/%08x/%08x/%08x)\n\n", __func__,
+					ls->ls_stateid.si_boot,
+					ls->ls_stateid.si_stateownerid,
+					ls->ls_stateid.si_fileid,
+					ls->ls_stateid.si_generation);
+
+	return status;
+}
+
 static inline struct nfs4_layout *
 alloc_layout(void)
 {
-- 
1.5.4.1



More information about the pNFS mailing list