[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