[pnfs] [Fwd: [PATCH 13/13] pnfs: nfs4_callback_pnfs_layoutrecall proc implementation]

Benny Halevy bhalevy at panasas.com
Wed Jan 23 05:49:21 EST 2008


Resending since previous message didn't get to the mailing list.

On Jan. 22, 2008, 21:34 +0200, Benny Halevy <bhalevy at panasas.com> wrote:

Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
 fs/nfs/callback_proc.c |  154 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index d12e1d9..6f1e126 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -13,7 +13,11 @@
 #include "internal.h"
 
 #if defined(CONFIG_PNFS)
+#include <linux/kthread.h>
+#include <linux/module.h>
 #include <linux/writeback.h>
+
+#include "pnfs.h"
 #endif
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
@@ -132,6 +136,156 @@ nfs_layoutrecall_find_inode(struct nfs_client *clp,
 	return ino;
 }
 
+struct recall_layout_threadargs {
+	struct inode *inode;
+	struct nfs_client *clp;
+	struct completion started;
+	struct cb_pnfs_layoutrecallargs rl;
+	int result;
+};
+
+static int pnfs_recall_layout(void *data)
+{
+	struct inode *ino;
+	struct nfs_client *clp;
+	struct nfs_server *server = NULL;
+	struct recall_layout_threadargs *args =
+		(struct recall_layout_threadargs *)data;
+	struct nfs4_pnfs_layoutreturn_arg lr_arg;
+	int status;
+
+	daemonize("nfsv4-layoutreturn");
+
+	dprintk("%s: recall_type=%d fsid 0x%llx-0x%llx start\n",
+		__func__, args->rl.cbl_recall_type,
+		args->rl.cbl_fsid.major, args->rl.cbl_fsid.minor);
+
+	clp = args->clp;
+	args->result = 0;
+	complete(&args->started);
+
+/* FIXME: need barrier here:
+   pause I/O to data servers
+   pause layoutgets
+   drain all outstanding writes to storage devices
+   wait for any outstanding layoutreturns and layoutgets mentioned in
+   cb_sequence.
+   then return layouts, resume after layoutreturns complete
+ */
+
+	if (args->rl.cbl_recall_type == RECALL_FILE) {
+		pnfs_return_layout(args->inode, &args->rl.cbl_seg);
+		goto out;
+	}
+
+	args->rl.cbl_seg.offset = 0;
+	args->rl.cbl_seg.length = NFS4_LENGTH_EOF;
+
+	/* FIXME: This loop is inefficient, running in O(|s_inodes|^2) */
+	while ((ino = nfs_layoutrecall_find_inode(clp, &args->rl)) != NULL) {
+		pnfs_return_layout(ino, &args->rl.cbl_seg);
+		iput(ino);
+	}
+
+	/* send final layoutreturn */
+	lr_arg.reclaim = 0;
+	lr_arg.layout_type = NFS_SERVER(args->inode)->pnfs_curr_ld->id;
+	lr_arg.return_type = args->rl.cbl_recall_type;
+	lr_arg.lseg = args->rl.cbl_seg;
+	lr_arg.inode = args->inode;
+
+	status = pnfs_return_layout_rpc(server, &lr_arg);
+	if (status)
+		printk(KERN_INFO
+		       "%s: ignoring pnfs_return_layout_rpc status=%d\n",
+		       __func__, status);
+	iput(args->inode);
+
+out:
+	module_put_and_exit(0);
+	dprintk("%s: exit status %d\n", __func__, args->result);
+	return 0;
+}
+
+/*
+ * Asynchronous layout recall!
+ */
+static int pnfs_async_return_layout(struct nfs_client *clp, struct inode *inode,
+				    struct cb_pnfs_layoutrecallargs *rl)
+{
+	struct recall_layout_threadargs data = {
+		.clp = clp,
+		.inode = inode,
+	};
+	struct task_struct *t;
+	int status;
+
+	/* should have returned NFS4ERR_NOMATCHING_LAYOUT... */
+	BUG_ON(inode == NULL);
+
+	data.rl = *rl;
+
+	init_completion(&data.started);
+	__module_get(THIS_MODULE);
+
+	t = kthread_run(pnfs_recall_layout, &data, "%s", "pnfs_recall_layout");
+	if (IS_ERR(t)) {
+		printk(KERN_INFO "NFS: Layout recall callback thread failed "
+			"for client (clientid %08x/%08x)\n",
+			(unsigned)(clp->cl_clientid >> 32),
+			(unsigned)(clp->cl_clientid));
+		status = PTR_ERR(t);
+		goto out_module_put;
+	}
+	wait_for_completion(&data.started);
+	return data.result;
+out_module_put:
+	module_put(THIS_MODULE);
+	return status;
+}
+
+unsigned pnfs_cb_layoutrecall(struct cb_pnfs_layoutrecallargs *args,
+			      void *dummy)
+{
+	struct nfs_client *clp;
+	struct inode *inode = NULL;
+	unsigned res;
+
+	res = htonl(NFS4ERR_INVAL);
+	clp = nfs_find_client(args->cbl_addr, 4);
+	if (clp == NULL) {
+		dprintk("%s: no client for addr %u.%u.%u.%u\n",
+			__func__, NIPQUAD(args->cbl_addr));
+		goto out;
+	}
+
+	res = htonl(NFS4ERR_NOMATCHING_LAYOUT);
+	inode = nfs_layoutrecall_find_inode(clp, args);
+	if (inode == NULL) {
+		dprintk("%s: no inode for RECALL_FILE\n", __func__);
+
+		goto out_putclient;
+	}
+
+	if (args->cbl_recall_type == RECALL_FILE &&
+	    !NFS_I(inode)->current_layout)
+		goto out_putinode;
+
+	res = 0;
+	/* Set up a helper thread to actually return the delegation */
+	if (!pnfs_async_return_layout(clp, inode, args))
+		goto out_putclient;
+
+	res = htonl(NFS4ERR_RESOURCE);
+out_putinode:
+	iput(inode);
+out_putclient:
+	nfs_put_client(clp);
+out:
+	dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
+	return res;
+}
+
 #endif /* defined(CONFIG_PNFS) */
 
 #if defined(CONFIG_NFS_V4_1)
-- 
1.5.3.3


-- 
Benny Halevy
Software Architect
Tel/Fax: +972-3-647-8340
Mobile: +972-54-802-8340
US:      +1-412-203-3187
bhalevy at panasas.com
 
Panasas, Inc.
The Leader in Parallel Storage
www.panasas.com


More information about the pNFS mailing list