[pnfs] [PATCH 19/38] [v1] pnfs: client layout cache: introduce get_alloc_layout

Benny Halevy bhalevy at panasas.com
Fri Jan 4 05:52:34 EST 2008


get_alloc_layout gets or allocates if needed the pnfs_layout_type structure
alloc_init_layout calls the layout driver's alloc_layout function
and initializes the allocated pnfs_layout_type struct.

Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
 fs/nfs/pnfs.c             |   79 ++++++++++++++++++++++++++++++++-------------
 include/linux/nfs4_pnfs.h |    1 +
 include/linux/nfs_fs.h    |    2 +-
 3 files changed, 58 insertions(+), 24 deletions(-)

diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 8c3c022..b91f5d7 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -412,38 +412,65 @@ out:
  *     the I/O module has its read/write methods called.
  */
 static struct pnfs_layout_type *
-pnfs_inject_layout(struct nfs_inode *nfsi,
-		   struct layoutdriver_io_operations *io_ops,
+pnfs_inject_layout(struct pnfs_layout_type *layid,
 		   struct nfs4_pnfs_layoutget_res *lgr)
 {
-	struct pnfs_layout_type *layid;
-	struct inode *inode = &nfsi->vfs_inode;
-	struct nfs_server *server = NFS_SERVER(inode);
+	struct layoutdriver_io_operations *io_ops = PNFS_LD_IO_OPS(layid);
 
 	dprintk("%s Begin\n", __FUNCTION__);
 
-	if (!io_ops->alloc_layout || !io_ops->set_layout) {
+	if (!io_ops->set_layout) {
 		printk(KERN_ERR "%s ERROR! Layout driver lacking pNFS layout ops!!!\n", __FUNCTION__);
 		return NULL;
 	}
 
-	if (nfsi->current_layout == NULL) {
-		dprintk("%s Alloc'ing layout\n", __FUNCTION__);
-		layid = io_ops->alloc_layout(server->pnfs_mountid, inode);
-		if (layid)
-			layid->inode = inode;
-	} else {
-		dprintk("%s Adding to current layout\n", __FUNCTION__);
-		layid = nfsi->current_layout;
-	}
+	dprintk("%s Calling set layout\n", __FUNCTION__);
+	return io_ops->set_layout(layid, lgr);
+}
 
-	if (!layid) {
-		printk(KERN_ERR "%s ERROR! Layout id non-existent!!!\n",
-		       __FUNCTION__);
+static struct pnfs_layout_type *
+alloc_init_layout(struct inode *ino, struct layoutdriver_io_operations *io_ops)
+{
+	struct pnfs_layout_type *lo;
+
+	lo = io_ops->alloc_layout(NFS_SERVER(ino)->pnfs_mountid, ino);
+	if (!lo) {
+		printk(KERN_ERR
+			"%s: out of memory: io_ops->alloc_layout failed\n",
+			__FUNCTION__);
 		return NULL;
 	}
-	dprintk("%s Calling set layout\n", __FUNCTION__);
-	return io_ops->set_layout(layid, lgr);
+
+	lo->roc_iomode = 0;
+	lo->inode = ino;
+	return lo;
+}
+
+/*
+ * get, possibly allocate current_layout
+ */
+static struct pnfs_layout_type *
+get_alloc_layout(struct inode *ino,
+		 struct layoutdriver_io_operations *io_ops)
+{
+	struct nfs_inode *nfsi = NFS_I(ino);
+	struct pnfs_layout_type *lo;
+
+	dprintk("%s Begin\n", __FUNCTION__);
+
+	if ((lo = nfsi->current_layout) == NULL) {
+		lo = nfsi->current_layout = alloc_init_layout(ino, io_ops);
+		if (!lo)
+			lo = ERR_PTR(-ENOMEM);
+	}
+
+#ifdef NFS_DEBUG
+	if (!IS_ERR(lo))
+		dprintk("%s Return %p\n", __FUNCTION__, lo);
+	else
+		dprintk("%s Return error %ld\n", __FUNCTION__, PTR_ERR(lo));
+#endif
+	return lo;
 }
 
 /* Update the file's layout for the given range and iomode.
@@ -463,6 +490,12 @@ pnfs_update_layout(struct inode *ino,
 	struct pnfs_layout_type *layout_new;
 	int result = -EIO;
 
+	layout_new = get_alloc_layout(ino, nfss->pnfs_curr_ld->ld_io_ops);
+	if (IS_ERR(layout_new)) {
+		result = PTR_ERR(layout_new);
+		goto ret;
+	}
+
 	arg.lseg.iomode = iomode;
 	arg.lseg.offset = pos;
 	arg.lseg.length = count;
@@ -538,8 +571,7 @@ pnfs_update_layout(struct inode *ino,
 	}
 
 	/* Inject layout blob into I/O device driver */
-	layout_new = pnfs_inject_layout(nfsi,
-					nfss->pnfs_curr_ld->ld_io_ops,
+	layout_new = pnfs_inject_layout(nfsi->current_layout,
 					&res);
 	if (layout_new == NULL) {
 		printk(KERN_ERR "%s: ERROR!  Could not inject layout (%d)\n",
@@ -564,7 +596,8 @@ out:
 
 	/* res.layout.buf kalloc'ed by the xdr decoder? */
 	kfree(res.layout.buf);
-	dprintk("%s end (err:%d) state %d\n",
+ret:
+	dprintk("%s end (err:%d) state 0x%lx\n",
 		__FUNCTION__, result, nfsi->pnfs_layout_state);
 	return result;
 }
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index d862aac..7ea5c33 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -37,6 +37,7 @@ struct pnfs_mount_type {
  * A reference is stored in the nfs_inode structure.
  */
 struct pnfs_layout_type {
+	int refcount;
 	int roc_iomode;			/* iomode to return on close, 0=none */
 	struct inode *inode;
 	u8 ld_data[];			/* layout driver private data */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 548498d..3d6bfbf 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -176,7 +176,7 @@ struct nfs_inode {
 
 	/* pNFS layout information */
 #if defined(CONFIG_PNFS)
-	u32 pnfs_layout_state;
+	unsigned long pnfs_layout_state;
 #define NFS_INO_LAYOUT_FAILED	0x0001	/* get layout failed, stop trying */
 	time_t pnfs_layout_suspend;
 	struct pnfs_layout_type *current_layout;
-- 
1.5.3.3



More information about the pNFS mailing list