[pnfs] [PATCH 20/37] pnfs: client layout cache: {get_lock, put_unlock}_current_layout

Benny Halevy bhalevy at panasas.com
Tue Jan 1 05:50:53 EST 2008


get_lock_current_layout locks and takes a reference count on pnfs_layout_type
put_unlock_current_layout: reverses that

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

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index c891492..20c6292 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1184,6 +1184,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
 #endif
 #ifdef CONFIG_PNFS
 	init_waitqueue_head(&nfsi->lo_waitq);
+	spin_lock_init(&nfsi->lo_lock);
 #endif /* CONFIG_PNFS */
 }
 
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 714de9d..d11145c 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -295,6 +295,44 @@ pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
 }
 
 /*
+ * pNFS client layout cache
+ */
+#define BUG_ON_UNLOCKED_LO(lo) \
+	BUG_ON(spin_trylock(&PNFS_NFS_INODE(lo)->lo_lock))
+
+/*
+ * get and lock nfs->current_layout
+ */
+static inline struct pnfs_layout_type *
+get_lock_current_layout(struct nfs_inode *nfsi)
+{
+	struct pnfs_layout_type *lo;
+
+	spin_lock(&nfsi->lo_lock);
+	lo = nfsi->current_layout;
+	if (lo)
+		lo->refcount++;
+	else
+		spin_unlock(&nfsi->lo_lock);
+
+	return lo;
+}
+
+/*
+ * put and unlock nfs->current_layout
+ */
+static inline void
+put_unlock_current_layout(struct nfs_inode *nfsi,
+			    struct pnfs_layout_type *lo)
+{
+	BUG_ON_UNLOCKED_LO(lo);
+	BUG_ON(lo->refcount <= 0);
+
+	--lo->refcount;
+	spin_unlock(&nfsi->lo_lock);
+}
+
+/*
 * Get layout from server.
 *    for now, assume that whole file layouts are requested.
 *    arg->offset: 0
@@ -334,18 +372,21 @@ get_layout(struct inode *ino,
 int
 pnfs_return_layout(struct inode *ino, struct nfs4_pnfs_layout_segment *range)
 {
+	struct pnfs_layout_type *lo;
 	struct nfs_inode *nfsi = NFS_I(ino);
 	struct nfs_server *server = NFS_SERVER(ino);
 	struct nfs4_pnfs_layoutreturn_arg arg;
 	int status;
 
-	dprintk("%s:Begin layout %p\n", __FUNCTION__, nfsi->current_layout);
+	lo = get_lock_current_layout(nfsi);
+	dprintk("%s:Begin layout %p\n", __FUNCTION__, lo);
 
-	if (nfsi->current_layout == NULL)
+	if (lo == NULL)
 		return 0;
 
 	server->pnfs_curr_ld->ld_io_ops->free_layout(
 		&nfsi->current_layout, &arg.lseg);
+	put_unlock_current_layout(nfsi, lo);
 
 	arg.reclaim = 0;
 	arg.layout_type = server->pnfs_curr_ld->id;
@@ -428,6 +469,7 @@ alloc_init_layout(struct inode *ino, struct layoutdriver_io_operations *io_ops)
 	if (!lo)
 		return NULL;
 
+	lo->refcount = 1;
 	lo->roc_iomode = 0;
 	lo->inode = ino;
 	return lo;
@@ -442,7 +484,7 @@ static int pnfs_wait_schedule(void *word)
 }
 
 /*
- * get, possibly allocate current_layout
+ * get, possibly allocate, and lock current_layout
  */
 static struct pnfs_layout_type *
 get_alloc_layout(struct inode *ino,
@@ -455,7 +497,7 @@ get_alloc_layout(struct inode *ino,
 	dprintk("%s Begin\n", __FUNCTION__);
 
 retry:
-	lo = nfsi->current_layout;
+	lo = get_lock_current_layout(nfsi);
 	if (lo)
 		goto out;
 
@@ -481,6 +523,7 @@ retry:
 		goto err;
 	}
 
+	spin_lock(&nfsi->lo_lock);
 out:
 	dprintk("%s Return %p\n", __FUNCTION__, lo);
 	return lo;
@@ -613,6 +656,7 @@ out:
 
 	/* res.layout.buf kalloc'ed by the xdr decoder? */
 	kfree(res.layout.buf);
+	put_unlock_current_layout(nfsi, layout_new);
 ret:
 	dprintk("%s end (err:%d) state 0x%lx\n",
 		__FUNCTION__, result, nfsi->pnfs_layout_state);
@@ -703,9 +747,11 @@ pnfs_getboundary(struct inode *inode)
 		goto out;
 
 	nfsi = NFS_I(inode);
-	lo = nfsi->current_layout;
-	if (lo)
+	lo = get_lock_current_layout(nfsi);;
+	if (lo) {
 		stripe_size = policy_ops->get_stripesize(lo);
+		put_unlock_current_layout(nfsi, lo);
+	}
 out:
 	return stripe_size;
 }
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 1a093b1..99dfe9c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -181,6 +181,7 @@ struct nfs_inode {
 #define NFS_INO_LAYOUT_ALLOC	0x0002	/* get layout failed, stop trying */
 	time_t pnfs_layout_suspend;
 	wait_queue_head_t lo_waitq;
+	spinlock_t lo_lock;
 	struct pnfs_layout_type *current_layout;
 	/* use rpc_creds in this open_context to send LAYOUTCOMMIT to MDS */
 	struct nfs_open_context *layoutcommit_ctx;
-- 
1.5.3.3



More information about the pNFS mailing list