[pnfs] [PATCH 09/10] pnfs: get_layout stateid processing

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


From: Andy Adamson <andros at umich.edu>

Protect the pnfs_layout_type nfs4_stateid with a seqlock for parallel
layout operation access. Add routines to get and set the layout.
Send either an open stateid or an initialized layout stateid on LAYOUTGET.

Signed-off-by: Andy Adamson<andros at netapp.com>
---
 fs/nfs/pnfs.c             |   54 +++++++++++++++++++++++++++++++++++++++++++-
 fs/nfs/pnfs.h             |    2 +
 include/linux/nfs4_pnfs.h |    1 +
 3 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ec755ec..5f93c1e 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -459,6 +459,45 @@ lo_seg_intersecting(struct nfs4_pnfs_layout_segment *l1,
 	       (end2 == NFS4_LENGTH_EOF || end2 > start1);
 }
 
+static void
+pnfs_set_layout_stateid(struct pnfs_layout_type *lo, nfs4_stateid *stateid)
+{
+	write_seqlock(&lo->seqlock);
+	memcpy(lo->stateid.data, stateid->data, sizeof(lo->stateid.data));
+	write_sequnlock(&lo->seqlock);
+}
+
+static void
+pnfs_get_layout_stateid(nfs4_stateid *dst, struct pnfs_layout_type *lo)
+{
+	int seq;
+
+	dprintk("--> %s\n", __func__);
+
+	do {
+		seq = read_seqbegin(&lo->seqlock);
+		memcpy(dst->data, lo->stateid.data, sizeof(lo->stateid.data));
+	} while (read_seqretry(&lo->seqlock, seq));
+
+	dprintk("<-- %s\n", __func__);
+}
+
+static void
+pnfs_layout_from_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
+{
+	int seq;
+
+	dprintk("--> %s\n", __func__);
+
+	do {
+		seq = read_seqbegin(&state->seqlock);
+		memcpy(dst->data, state->stateid.data,
+				sizeof(state->stateid.data));
+	} while (read_seqretry(&state->seqlock, seq));
+
+	dprintk("<-- %s\n", __func__);
+}
+
 /*
 * Get layout from server.
 *    for now, assume that whole file layouts are requested.
@@ -475,7 +514,8 @@ static int
 get_layout(struct inode *ino,
 	   struct nfs_open_context *ctx,
 	   struct nfs4_pnfs_layout_segment *range,
-	   struct pnfs_layout_segment **lsegpp)
+	   struct pnfs_layout_segment **lsegpp,
+	   struct pnfs_layout_type *lo)
 {
 	int status;
 	struct nfs_server *server = NFS_SERVER(ino);
@@ -496,6 +536,11 @@ get_layout(struct inode *ino,
 	lgp->args.ctx = ctx;
 	lgp->lsegpp = lsegpp;
 
+	if (!memcmp(lo->stateid.data, &zero_stateid, NFS4_STATEID_SIZE))
+		pnfs_layout_from_open_stateid(&lgp->args.stateid, ctx->state);
+	else
+		pnfs_get_layout_stateid(&lgp->args.stateid, lo);
+
 	/* Retrieve layout information from server */
 	status = NFS_PROTO(ino)->pnfs_layoutget(lgp);
 
@@ -695,6 +740,8 @@ alloc_init_layout(struct inode *ino, struct layoutdriver_io_operations *io_ops)
 		return NULL;
 	}
 
+	seqlock_init(&lo->seqlock);
+	memset(&lo->stateid, 0, NFS4_STATEID_SIZE);
 	lo->refcount = 1;
 	INIT_LIST_HEAD(&lo->segs);
 	lo->roc_iomode = 0;
@@ -889,7 +936,7 @@ pnfs_update_layout(struct inode *ino,
 
 	spin_unlock(&nfsi->lo_lock);
 
-	result = get_layout(ino, ctx, &arg, lsegpp);
+	result = get_layout(ino, ctx, &arg, lsegpp, lo);
 out:
 	dprintk("%s end (err:%d) state 0x%lx lseg %p\n",
 			__func__, result, nfsi->pnfs_layout_state, lseg);
@@ -980,6 +1027,9 @@ get_out:
 		nfsi->pnfs_layout_state |= NFS_INO_LAYOUT_FAILED;
 	spin_unlock(&nfsi->lo_lock);
 
+	/* Done processing layoutget. Set the layout stateid */
+	pnfs_set_layout_stateid(lo, &res->stateid);
+
 	/* res->layout.buf kalloc'ed by the xdr decoder? */
 	kfree(res->layout.buf);
 
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index acbce4b..27a3926 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -24,6 +24,8 @@ extern int nfs4_pnfs_getdeviceinfo(struct super_block *sb, struct nfs_fh *fh,
 				   struct pnfs_device *dev);
 
 /* pnfs.c */
+extern const nfs4_stateid zero_stateid;
+
 int pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
 	size_t count, loff_t pos, enum pnfs_iomode access_type,
 	struct pnfs_layout_segment **lsegpp);
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index c83aae6..71f7d32 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -44,6 +44,7 @@ struct pnfs_layout_type {
 	struct list_head segs;		/* layout segments list */
 	int roc_iomode;			/* iomode to return on close, 0=none */
 	struct inode *inode;
+	seqlock_t seqlock;		/* Protects the stateid */
 	nfs4_stateid stateid;
 	u8 ld_data[];			/* layout driver private data */
 };
-- 
1.5.4.1



More information about the pNFS mailing list