[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