[pnfs] [PATCH 21/21] pnfsblock: STUB: encode layoutcommit

Fred Isaman iisaman at citi.umich.edu
Thu Apr 10 10:07:37 EDT 2008


XDR encodes the layout specific portion of layoutcommit.

This code works, but there are several issues dealing with the generic
pnfs framework which need to be fixed before this code is made more "real".
For example:
1. Layout locking is missing (and needs revamping in general)
2. There needs to be a way to pass data from the setup to the cleanup function.
3. Status of the result needs to passed into cleanup.

Signed-off-by: Fred Isaman <iisaman at citi.umich.edu>
Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
 fs/nfs/blocklayout/blocklayout.c |   85 ++++++++++++++++++++++++++++++++++++--
 fs/nfs/blocklayout/blocklayout.h |   19 ++++++++-
 fs/nfs/pnfs.c                    |    9 +++-
 include/linux/nfs4_pnfs.h        |    9 +++-
 include/linux/pnfs_xdr.h         |    1 +
 5 files changed, 113 insertions(+), 10 deletions(-)

diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index f9c2a1d..51b04d4 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -320,6 +320,11 @@ split_inval_extent(struct pnfs_layout_segment *lseg,
 	}
 	rv->be_state = PNFS_BLOCK_NEEDS_INIT;
 	rv->be_bitmap = (1 << (len >> (PAGE_CACHE_SHIFT - 9))) - 1;
+	spin_lock(&BLK_LOT(lseg)->blt_lock);
+	list_add_tail(&rv->be_lc_node, &BLK_LOT(lseg)->blt_commit_list);
+	BLK_LOT(lseg)->blt_count++;
+	kref_get(&rv->be_refcnt);
+	spin_unlock(&BLK_LOT(lseg)->blt_lock);
  out:
 	spin_unlock(&bl->bl_ext_lock);
 	if (rv)
@@ -617,7 +622,22 @@ release_extents(struct pnfs_block_layout *bl)
 static void
 bl_free_layout(struct pnfs_layout_type *lt)
 {
+	struct pnfs_block_extent *be;
+	struct pnfs_block_layout_top *priv;
+
 	dprintk("%s enter\n", __func__);
+	if (!lt)
+		return;
+	priv = (struct pnfs_block_layout_top *) lt->ld_data;
+	spin_lock(&priv->blt_lock);
+	while (!list_empty(&priv->blt_commit_list)) {
+		be = list_first_entry(&priv->blt_commit_list,
+				      struct pnfs_block_extent,
+				      be_lc_node);
+		list_del(&be->be_lc_node);
+		put_extent(be);
+	}
+	spin_unlock(&priv->blt_lock);
 	kfree(lt);
 	return;
 }
@@ -627,9 +647,15 @@ static struct pnfs_layout_type *
 bl_alloc_layout(struct pnfs_mount_type *mtype, struct inode *inode)
 {
 	struct pnfs_layout_type		*lt;
+	struct pnfs_block_layout_top	*priv;
 
 	dprintk("%s enter\n", __func__);
-	lt = kzalloc(sizeof(*lt) + 0, GFP_KERNEL);
+	lt = kzalloc(sizeof(*lt) + sizeof(*priv), GFP_KERNEL);
+	if (!lt)
+		return NULL;
+	priv = (struct pnfs_block_layout_top *) lt->ld_data;
+	spin_lock_init(&priv->blt_lock);
+	INIT_LIST_HEAD(&priv->blt_commit_list);
 	return lt;
 }
 
@@ -676,9 +702,14 @@ bl_alloc_lseg(struct pnfs_layout_type *layoutid,
 
 static int
 bl_setup_layoutcommit(struct pnfs_layout_type *lo,
-		struct pnfs_layoutcommit_arg *arg)
+		      struct pnfs_layoutcommit_arg *arg,
+		      struct list_head *local_list)
 {
 	struct nfs_server *nfss = PNFS_NFS_SERVER(lo);
+	struct pnfs_block_layout_top *priv;
+	struct pnfs_block_extent *be;
+	int count;
+	__be32 *p, *buf;
 
 	dprintk("%s enter\n", __func__);
 	/* Need to ensure commit is block-size aligned */
@@ -688,15 +719,61 @@ bl_setup_layoutcommit(struct pnfs_layout_type *lo,
 		arg->lseg.length += mask;
 		arg->lseg.length &= ~mask;
 	}
+	if (!lo)
+		return -EIO;
+	priv = (struct pnfs_block_layout_top *) lo->ld_data;
+
+	/* Find NEEDS INIT pieces in range
+	 * (STUB - just use them all - really need a private field so we
+	 * can pass data to cleanup */
+	spin_lock(&priv->blt_lock);
+	list_splice_init(&priv->blt_commit_list, local_list);
+	count = priv->blt_count;
+	priv->blt_count = 0;
+	spin_unlock(&priv->blt_lock);
+	buf = kmalloc((11 * count + 1) * sizeof(__be32), GFP_KERNEL);
+	if (!buf) {
+		/* Need to put extents back.  Note not caring about order */
+		spin_lock(&priv->blt_lock);
+		list_splice_init(local_list, &priv->blt_commit_list);
+		priv->blt_count += count;
+		spin_unlock(&priv->blt_lock);
+		return -ENOMEM;
+	}
+	/* Parse into XDR */
+	p = buf;
+	WRITE32(count);
+	list_for_each_entry(be, local_list, be_lc_node) {
+		WRITE_DEVID(&be->be_devid);
+		WRITE64(be->be_f_offset << 9);
+		WRITE64(be->be_length << 9);
+		WRITE64(be->be_v_offset << 9);
+		WRITE32(PNFS_BLOCK_READWRITE_DATA);
+	}
+	/* Set args */
+	arg->new_layout = buf;
+	arg->new_layout_size = (11 * count + 1) * 4;
 	return 0;
 }
 
 static void
 bl_cleanup_layoutcommit(struct pnfs_layout_type *layoutid,
-		struct pnfs_layoutcommit_arg *arg,
-		struct pnfs_layoutcommit_res *res)
+			struct pnfs_layoutcommit_arg *arg,
+			struct pnfs_layoutcommit_res *res,
+			struct list_head *local_list)
 {
+	struct pnfs_block_extent *be;
+
 	dprintk("%s enter\n", __func__);
+	/* Free buffer */
+	kfree(arg->new_layout);
+	/* If Succes, change NEEDS_INIT into RW, else to INVAL */
+	/* STUB - there seems to be no way to get status - assume passed */
+	/* Merge back together - how get list lock? */
+	list_for_each_entry(be, local_list, be_lc_node) {
+		/* huge STUB - but works given current limits */
+		be->be_state = PNFS_BLOCK_READWRITE_DATA;
+	}
 }
 
 static void free_blk_mountid(struct block_mount_id *mid)
diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
index f804f02..9d07b2e 100644
--- a/fs/nfs/blocklayout/blocklayout.h
+++ b/fs/nfs/blocklayout/blocklayout.h
@@ -113,7 +113,8 @@ enum exstate4 {
 
 /* sector_t fields are all in 512-byte sectors */
 struct pnfs_block_extent {
-	struct list_head be_node;
+	struct list_head be_node;     /* link into lseg list */
+	struct list_head be_lc_node;  /* link into layoutcommit list */
 	struct pnfs_deviceid be_devid;
 	struct block_device *be_mdev;
 	sector_t	be_f_offset;  /* the starting offset in the file */
@@ -124,6 +125,12 @@ struct pnfs_block_extent {
 	struct kref	be_refcnt;
 };
 
+struct pnfs_block_layout_top {
+	struct list_head	blt_commit_list; /* extents for layoutcommit */
+	int			blt_count;       /* number of entries in list */
+	spinlock_t		blt_lock;        /* protects blt_commit_list */
+};
+
 struct pnfs_block_layout {
 	spinlock_t		bl_ext_lock;    /* protects list manipulation */
 	uint32_t		bl_n_ext;
@@ -132,6 +139,7 @@ struct pnfs_block_layout {
 
 #define BLK_ID(lt)	((struct block_mount_id *)(PNFS_MOUNTID(lt)->mountid))
 #define BLK_LO(lseg)	((struct pnfs_block_layout *)lseg->ld_data)
+#define BLK_LOT(lseg)	((struct pnfs_block_layout_top *)lseg->layout->ld_data)
 
 uint32_t *blk_overflow(uint32_t *p, uint32_t *end, size_t nbytes);
 
@@ -145,6 +153,15 @@ uint32_t *blk_overflow(uint32_t *p, uint32_t *end, size_t nbytes);
 	} \
 } while (0)
 
+#define WRITE32(n)               *p++ = htonl(n)
+#define WRITE64(n)               do {				\
+	*p++ = htonl((uint32_t)((n) >> 32));				\
+	*p++ = htonl((uint32_t)(n));					\
+} while (0)
+#define WRITEMEM(ptr,nbytes)     do {				\
+	p = xdr_encode_opaque_fixed(p, ptr, nbytes);		\
+} while (0)
+#define WRITE_DEVID(x)	WRITEMEM((x)->data, NFS4_PNFS_DEVICEID4_SIZE)
 #define READ32(x)         (x) = ntohl(*p++)
 #define READ64(x)         do {                  \
 	(x) = (uint64_t)ntohl(*p++) << 32;           \
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index a0b80c2..8739f7c 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -76,8 +76,10 @@ static inline struct pnfs_layoutcommit_data *pnfs_layoutcommit_alloc(void)
 {
 	struct pnfs_layoutcommit_data *p =
 			mempool_alloc(pnfs_layoutcommit_mempool, GFP_NOFS);
-	if (p)
+	if (p) {
 		memset(p, 0, sizeof(*p));
+		INIT_LIST_HEAD(&p->ld_data);
+	}
 
 	return p;
 }
@@ -1760,7 +1762,8 @@ pnfs_layoutcommit_done(
 		nfss->pnfs_curr_ld->ld_io_ops->cleanup_layoutcommit(
 							nfsi->current_layout,
 							&data->args,
-							&data->res);
+							&data->res,
+							&data->ld_data);
 
 	/* release the open_context acquired in pnfs_writeback_done */
 	put_nfs_open_context(data->ctx);
@@ -1867,7 +1870,7 @@ pnfs_layoutcommit_setup(struct pnfs_layoutcommit_data *data, int sync)
 	if (nfss->pnfs_curr_ld->ld_io_ops->setup_layoutcommit) {
 		result = nfss->pnfs_curr_ld->ld_io_ops->setup_layoutcommit(
 				nfsi->current_layout,
-				&data->args);
+				&data->args, &data->ld_data);
 		if (result)
 			goto out;
 	}
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index d9a231f..3aa26fd 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -165,8 +165,13 @@ struct layoutdriver_io_operations {
 	struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_type *layoutid, struct nfs4_pnfs_layoutget_res *lgr);
 	void (*free_lseg) (struct pnfs_layout_segment *lseg);
 
-	int (*setup_layoutcommit) (struct pnfs_layout_type *layoutid, struct pnfs_layoutcommit_arg *arg);
-	void (*cleanup_layoutcommit) (struct pnfs_layout_type *layoutid, struct pnfs_layoutcommit_arg *arg, struct pnfs_layoutcommit_res *res);
+	int (*setup_layoutcommit) (struct pnfs_layout_type *layoutid,
+				   struct pnfs_layoutcommit_arg *arg,
+				   struct list_head *ld_data);
+	void (*cleanup_layoutcommit) (struct pnfs_layout_type *layoutid,
+				      struct pnfs_layoutcommit_arg *arg,
+				      struct pnfs_layoutcommit_res *res,
+				      struct list_head *ld_data);
 
 	/* Registration information for a new mounted file system
 	 */
diff --git a/include/linux/pnfs_xdr.h b/include/linux/pnfs_xdr.h
index c443d19..8a2f2cb 100644
--- a/include/linux/pnfs_xdr.h
+++ b/include/linux/pnfs_xdr.h
@@ -87,6 +87,7 @@ struct pnfs_layoutcommit_res {
 };
 
 struct pnfs_layoutcommit_data {
+	struct list_head ld_data; /* STUB */
 	struct rpc_task task;
 	struct inode *inode;
 	struct rpc_cred *cred;
-- 
1.5.3.3



More information about the pNFS mailing list