[pnfs] Add support for layout recall one client and server.

Marc Eshel eshel at almaden.ibm.com
Tue Jul 25 00:38:39 EDT 2006


Add support for layout recall one client and server.

Index: fs/nfs/callback.h
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfs/callback.h,v
retrieving revision 1.3
diff -u -r1.3 callback.h
--- fs/nfs/callback.h    20 Mar 2006 16:05:31 -0000    1.3
+++ fs/nfs/callback.h    25 Jul 2006 04:11:43 -0000
@@ -60,11 +60,21 @@
     uint32_t truncate;
 };
 
+enum layout_recall_type {
+    RECALL_FILE = 1,
+    RECALL_FSID = 2
+};
+
 struct cb_pnfs_layoutrecallargs {
-    struct sockaddr_in *addr;
-    struct nfs_fh fh;
-    uint64_t offset;
-    uint64_t length;
+    struct sockaddr_in    *cbl_addr;
+    struct nfs_fh        cbl_fh;
+    uint64_t        cbl_offset;
+    uint64_t        cbl_length;
+    struct nfs_fsid        cbl_fsid;
+    uint32_t        cbl_recall_type;
+    uint32_t        cbl_layout_type;
+    uint32_t        cbl_iomode;
+    uint32_t        cbl_layoutchanged;
 };
 
 extern unsigned nfs4_callback_getattr(struct cb_getattrargs *args, 
struct cb_getattrres *res);
Index: fs/nfs/callback_proc.c
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfs/callback_proc.c,v
retrieving revision 1.3
diff -u -r1.3 callback_proc.c
--- fs/nfs/callback_proc.c    20 Mar 2006 16:05:31 -0000    1.3
+++ fs/nfs/callback_proc.c    25 Jul 2006 04:11:43 -0000
@@ -100,32 +100,32 @@
 unsigned nfs4_callback_pnfs_layoutrecall(struct 
cb_pnfs_layoutrecallargs *args, void *dummy)
 {
     struct nfs4_client *clp;
-    struct inode *inode;
-    unsigned res;
+    struct inode *inode = NULL;
+    unsigned res = -ENOENT;
 
     res = htonl(NFS4ERR_BADHANDLE);
-    clp = nfs4_find_client(&args->addr->sin_addr);
+    clp = nfs4_find_client(&args->cbl_addr->sin_addr);
     if (clp == NULL)
         goto out;
 
-    /* XXX Need to customize this lookup for a layout delegation */
-    inode = nfs_delegation_find_inode(clp, &args->fh);
-    if (inode == NULL)
-        goto out_putclient;
-    /* XXX Need to actually implement recall of layout */
-    /* Set up a helper thread to actually return the delegation
-    switch(nfs_async_inode_return_delegation(inode, &args->stateid)) {
+    if (args->cbl_recall_type == RECALL_FILE) {
+        inode = nfs_layout_find_inode(clp, &args->cbl_fh);
+        if (inode == NULL)
+            goto out_putclient;
+    }
+    /* Set up a helper thread to actually return the delegation */
+    switch(nfs_async_return_layout(clp, inode, &args->cbl_fsid)) {
         case 0:
             res = 0;
             break;
         case -ENOENT:
-            res = htonl(NFS4ERR_BAD_STATEID);
+            res = htonl(NFS4ERR_NOENT);
             break;
         default:
             res = htonl(NFS4ERR_RESOURCE);
     }
-    */
-    iput(inode);
+    if (inode)
+        iput(inode);
 out_putclient:
     nfs4_put_client(clp);
 out:
Index: fs/nfs/callback_xdr.c
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfs/callback_xdr.c,v
retrieving revision 1.4
diff -u -r1.4 callback_xdr.c
--- fs/nfs/callback_xdr.c    13 Jul 2006 17:18:40 -0000    1.4
+++ fs/nfs/callback_xdr.c    25 Jul 2006 04:11:43 -0000
@@ -24,6 +24,11 @@
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
 
+#define READ64(x)         do {            \
+    (x) = (u64)ntohl(*p++) << 32;        \
+    (x) |= ntohl(*p++);            \
+} while (0)
+
 typedef unsigned (*callback_process_op_t)(void *, void *);
 typedef unsigned (*callback_decode_arg_t)(struct svc_rqst *, struct 
xdr_stream *, void *);
 typedef unsigned (*callback_encode_res_t)(struct svc_rqst *, struct 
xdr_stream *, void *);
@@ -209,19 +214,31 @@
 static unsigned decode_pnfs_layoutrecall_args(struct svc_rqst *rqstp, 
struct xdr_stream *xdr, struct cb_pnfs_layoutrecallargs *args)
 {
     uint32_t *p;
-    unsigned status;
+    unsigned status = 0;
 
-    args->addr = &rqstp->rq_addr;
-    status = decode_fh(xdr, &args->fh);
-    if (unlikely(status != 0))
-        goto out;
-    p = read_buf(xdr, 16);
-    if (unlikely(p == NULL)) {
-        status = htonl(NFS4ERR_RESOURCE);
-        goto out;
+    args->cbl_addr = &rqstp->rq_addr;
+    p = read_buf(xdr, 28);
+
+    args->cbl_layout_type = ntohl(*p++);
+    args->cbl_iomode = ntohl(*p++);
+    args->cbl_layoutchanged = ntohl(*p++);
+    args->cbl_recall_type = ntohl(*p++);
+    
+        if (args->cbl_recall_type == RECALL_FSID) {
+        READ64(args->cbl_fsid.major);
+        READ64(args->cbl_fsid.minor);
+        }
+        else {
+        status = decode_fh(xdr, &args->cbl_fh);
+        if (unlikely(status != 0))
+            goto out;
+        READ64(args->cbl_offset);
+        READ64(args->cbl_length);
     }
-    p = xdr_decode_hyper(p, &args->offset);
-    p = xdr_decode_hyper(p, &args->length);
+    dprintk("%s: ltype %d iomode %d changed %d recall_type %d fsid 
%llx-%llx\n",
+        __FUNCTION__, args->cbl_layout_type, args->cbl_iomode,
+        args->cbl_layoutchanged, args->cbl_recall_type,
+        args->cbl_fsid.major, args->cbl_fsid.minor);
 out:
     dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
     return 0;
Index: fs/nfs/delegation.c
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfs/delegation.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 delegation.c
--- fs/nfs/delegation.c    16 Mar 2006 17:58:32 -0000    1.1.1.2
+++ fs/nfs/delegation.c    25 Jul 2006 04:11:43 -0000
@@ -16,9 +16,13 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_xdr.h>
+#include <linux/writeback.h>
 
 #include "nfs4_fs.h"
 #include "delegation.h"
+#include "pnfs.h"
+
+#define NFSDBG_FACILITY NFSDBG_CALLBACK
 
 static struct nfs_delegation *nfs_alloc_delegation(void)
 {
@@ -307,6 +311,15 @@
     int result;
 };
 
+struct recall_layout_threadargs {
+    struct inode *inode;
+    struct nfs4_client *clp;
+    const nfs4_stateid *stateid;
+        struct nfs_fsid fsid;
+    struct completion started;
+    int result;
+};
+
 static int recall_thread(void *data)
 {
     struct recall_threadargs *args = (struct recall_threadargs *)data;
@@ -346,6 +359,58 @@
     module_put_and_exit(0);
 }
 
+static int recall_layout_thread(void *data)
+{
+    struct inode *inode;
+    struct nfs4_client *clp;
+    struct nfs_server *server= NULL;
+    struct super_block *sb = NULL;
+    struct recall_layout_threadargs *args = (struct 
recall_layout_threadargs *)data;
+
+    daemonize("nfsv4-layoutreturn");
+
+    printk("%s: fsid 0x%llx-0x%llx start\n",
+        __FUNCTION__, args->fsid.major, args->fsid.minor);
+
+    clp = args->clp;
+    args->result = 0;
+    complete(&args->started);
+
+//??? commit the files first ???
+
+    if (args->inode != NULL) {
+        pnfs_return_layout(args->inode);
+        goto out;
+    }
+    down_read(&clp->cl_sem);
+    list_for_each_entry(server, &clp->cl_superblocks, nfs4_siblings) {
+        printk("%s: fsid 0x%llx-0x%llx 0x%llx-0x%llx\n",
+            __FUNCTION__, args->fsid.major, args->fsid.minor,
+            server->fsid.major, server->fsid.minor);
+            
+        if (server->fsid.major == args->fsid.major &&
+            server->fsid.minor == args->fsid.minor)
+            break;
+    }
+    up_read(&clp->cl_sem);
+        if (server) {
+            sb = server->sb;
+        if (!sb)
+            goto out;
+    }
+    spin_lock(&inode_lock);
+    list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+        pnfs_return_layout(inode);
+        continue;
+    }
+    spin_unlock(&inode_lock);
+
+out:
+    module_put_and_exit(0);
+    printk("%s: exit status %d\n", __FUNCTION__, args->result);
+    return 0;
+}
+
 /*
  * Asynchronous delegation recall!
  */
@@ -370,6 +435,30 @@
 }
 
 /*
+ * Asynchronous layout recall!
+ */
+int nfs_async_return_layout(struct nfs4_client *clp, struct inode 
*inode, struct nfs_fsid *fsid)
+{
+    struct recall_layout_threadargs data = {
+        .clp = clp,
+        .inode = inode,
+        .fsid = *fsid,
+    };
+    int status;
+
+    init_completion(&data.started);
+    __module_get(THIS_MODULE);
+    status = kernel_thread(recall_layout_thread, &data, CLONE_KERNEL);
+    if (status < 0)
+        goto out_module_put;
+    wait_for_completion(&data.started);
+    return data.result;
+out_module_put:
+    module_put(THIS_MODULE);
+    return status;
+}
+
+/*
  * Retrieve the inode associated with a delegation
  */
 struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const 
struct nfs_fh *fhandle)
@@ -384,6 +473,31 @@
         }
     }
     spin_unlock(&clp->cl_lock);
+    return res;
+}
+
+/*
+ * Retrieve the inode associated with a layout
+ */
+struct inode *nfs_layout_find_inode(struct nfs4_client *clp, const 
struct nfs_fh *fhandle)
+{
+    struct nfs4_state_owner *sp;
+    struct nfs4_state *state;
+    struct inode *res = NULL;
+
+    /* Reset all sequence ids to zero */
+    list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+        spin_lock(&sp->so_lock);
+        list_for_each_entry(state, &sp->so_states, open_states) {
+            if (nfs_compare_fh(fhandle, &NFS_I(state->inode)->fh) == 0) {
+                res = igrab(state->inode);
+                break;
+            }
+        }
+        spin_unlock(&sp->so_lock);
+        if (res)
+            break;
+    }
     return res;
 }
 
Index: fs/nfs/delegation.h
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfs/delegation.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 delegation.h
--- fs/nfs/delegation.h    16 Mar 2006 17:58:32 -0000    1.1.1.2
+++ fs/nfs/delegation.h    25 Jul 2006 04:11:43 -0000
@@ -28,8 +28,10 @@
 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred 
*cred, struct nfs_openres *res);
 int __nfs_inode_return_delegation(struct inode *inode);
 int nfs_async_inode_return_delegation(struct inode *inode, const 
nfs4_stateid *stateid);
+int nfs_async_return_layout(struct nfs4_client *clp, struct inode 
*inode, struct nfs_fsid *fsid);
 
 struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const 
struct nfs_fh *fhandle);
+struct inode *nfs_layout_find_inode(struct nfs4_client *clp, const 
struct nfs_fh *fhandle);
 void nfs_return_all_delegations(struct super_block *sb);
 void nfs_expire_all_delegations(struct nfs4_client *clp);
 void nfs_handle_cb_pathdown(struct nfs4_client *clp);
Index: fs/nfs/pnfs.c
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfs/pnfs.c,v
retrieving revision 1.39
diff -u -r1.39 pnfs.c
--- fs/nfs/pnfs.c    23 May 2006 16:09:23 -0000    1.39
+++ fs/nfs/pnfs.c    25 Jul 2006 04:11:43 -0000
@@ -351,6 +351,11 @@
 
     /* Retrieve layout information from server */
     status = NFS_PROTO(ino)->pnfs_layoutreturn(&gdata);
+
+    dprintk ("%s: removing layout\n", __FUNCTION__);
+   
 NFS_SERVER(ino)->pnfs_curr_ld->ld_io_ops->free_layout(NFS_I(ino)->current_layout, 
ino, 0, 0);
+    NFS_I(ino)->current_layout = NULL;
+
     dprintk("%s:Exit status %d\n", __FUNCTION__, status);
     return status;
 }
Index: fs/nfs/pnfs.h
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfs/pnfs.h,v
retrieving revision 1.15
diff -u -r1.15 pnfs.h
--- fs/nfs/pnfs.h    23 May 2006 16:09:23 -0000    1.15
+++ fs/nfs/pnfs.h    25 Jul 2006 04:11:43 -0000
@@ -12,6 +12,7 @@
 #ifndef FS_NFS_PNFS_H
 #define FS_NFS_PNFS_H
 
+int pnfs_return_layout(struct inode* ino);
 void set_pnfs_layoutdriver(struct super_block *sb, u32 id);
 void unmount_pnfs_layoutdriver(struct super_block *sb);
 ssize_t pnfs_file_write(struct file* filp, const char __user *buf, 
size_t count, loff_t* pos);
Index: fs/nfs/super.c
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfs/super.c,v
retrieving revision 1.4
diff -u -r1.4 super.c
--- fs/nfs/super.c    13 Jul 2006 18:17:54 -0000    1.4
+++ fs/nfs/super.c    25 Jul 2006 04:11:43 -0000
@@ -961,7 +961,9 @@
 
 static int nfs_set_super(struct super_block *s, void *data)
 {
+    struct nfs_server *server = data;
     s->s_fs_info = data;
+        server->sb = s;
     return set_anon_super(s, data);
 }
 
Index: fs/nfsd/export.c
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfsd/export.c,v
retrieving revision 1.9
diff -u -r1.9 export.c
--- fs/nfsd/export.c    13 Jul 2006 17:18:41 -0000    1.9
+++ fs/nfsd/export.c    25 Jul 2006 04:11:43 -0000
@@ -385,11 +385,11 @@
 static int cb_layout_recall(struct super_block *sb, struct inode *inode,
 void *p)
 {
-    struct layout_recall *lr = (struct layout_recall *)p;
+    struct nfs4_cb_layout *lr = (struct nfs4_cb_layout *)p;
 
     dprintk("cb_layout_recall lr %p\n", lr);
 
-    return 0;
+        return nfsd_layout_recall_cb(lr);
 }
 EXPORT_SYMBOL(cb_layout_recall);
 
Index: fs/nfsd/nfs4callback.c
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfsd/nfs4callback.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 nfs4callback.c
--- fs/nfsd/nfs4callback.c    12 Jul 2006 19:53:43 -0000    1.1.1.4
+++ fs/nfsd/nfs4callback.c    25 Jul 2006 04:11:43 -0000
@@ -60,10 +60,12 @@
 enum {
         NFSPROC4_CLNT_CB_NULL = 0,
     NFSPROC4_CLNT_CB_RECALL,
+    NFSPROC4_CLNT_CB_LAYOUT,
 };
 
 enum nfs_cb_opnum4 {
     OP_CB_RECALL            = 4,
+    OP_CB_LAYOUT            = 5,
 };
 
 #define NFS4_MAXTAGLEN        20
@@ -82,6 +84,12 @@
 
 #define NFS4_dec_cb_recall_sz        (cb_compound_dec_hdr_sz  +      \
                     op_dec_sz)
+#define NFS4_enc_cb_layout_sz        (cb_compound_enc_hdr_sz +       \
+                    1 + enc_stateid_sz +            \
+                    enc_nfs4_fh_sz)
+
+#define NFS4_dec_cb_layout_sz        (cb_compound_dec_hdr_sz  +      \
+                    op_dec_sz)
 
 /*
 * Generic encode routines from fs/nfs/nfs4xdr.c
@@ -98,6 +106,10 @@
 }
 
 #define WRITE32(n)               *p++ = htonl(n)
+#define WRITE64(n)               do {                \
+    *p++ = htonl((u32)((n) >> 32));                \
+    *p++ = htonl((u32)(n));                    \
+} while (0)
 #define WRITEMEM(ptr,nbytes)     do {                           \
     p = xdr_writemem(p, ptr, nbytes);                       \
 } while (0)
@@ -232,6 +244,40 @@
 }
 
 static int
+encode_cb_layout(struct xdr_stream *xdr, struct nfs4_cb_layout *lr)
+{
+    u32 *p;
+    int len = lr->cbl_fhlen;
+
+    RESERVE_SPACE(48 + len);
+
+    WRITE32(OP_CB_LAYOUT);
+    WRITE32(lr->cbl_layout_type);
+    WRITE32(lr->cbl_iomode);
+    WRITE32(lr->cbl_layoutchanged);
+    WRITE32(lr->cbl_recall_type);
+    if (lr->cbl_recall_type == RECALL_FSID) {
+        WRITE64(lr->cbl_fsid.major);
+        WRITE64(lr->cbl_fsid.minor);
+        dprintk("%s: type %d iomode %d changed %d recall_type %d fsid 
0x%llx-0x%llx\n",
+            __FUNCTION__, lr->cbl_layout_type, lr->cbl_iomode,
+            lr->cbl_layoutchanged, lr->cbl_recall_type,
+            lr->cbl_fsid.major, lr->cbl_fsid.minor);
+    }
+    else {
+        WRITE32(len);
+        WRITEMEM(lr->cbl_fhval, len);
+        WRITE64(lr->cbl_offset);
+        WRITE64(lr->cbl_length);
+        dprintk("%s: type %d iomode %d changed %d recall_type %d offset 
%lld length %lld\n",
+            __FUNCTION__, lr->cbl_layout_type, lr->cbl_iomode,
+            lr->cbl_layoutchanged, lr->cbl_recall_type,
+            lr->cbl_offset,    lr->cbl_length);
+    }
+    return 0;
+}
+
+static int
 nfs4_xdr_enc_cb_null(struct rpc_rqst *req, u32 *p)
 {
     struct xdr_stream xdrs, *xdr = &xdrs;
@@ -255,6 +301,21 @@
     return (encode_cb_recall(&xdr, args));
 }
 
+static int
+nfs4_xdr_enc_cb_layout(struct rpc_rqst *req, u32 *p, struct 
nfs4_cb_layout *args)
+{
+    struct xdr_stream xdr;
+
+    struct nfs4_cb_compound_hdr hdr = {
+        .ident = args->cbl_ident,
+        .nops   = 1,
+    };
+
+    xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+    encode_cb_compound_hdr(&xdr, &hdr);
+
+    return (encode_cb_layout(&xdr, args));
+}
 
 static int
 decode_cb_compound_hdr(struct xdr_stream *xdr, struct 
nfs4_cb_compound_hdr *hdr){
@@ -313,6 +374,22 @@
     return status;
 }
 
+static int
+nfs4_xdr_dec_cb_layout(struct rpc_rqst *rqstp, u32 *p)
+{
+    struct xdr_stream xdr;
+    struct nfs4_cb_compound_hdr hdr;
+    int status;
+
+    xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+    status = decode_cb_compound_hdr(&xdr, &hdr);
+    if (status)
+        goto out;
+    status = decode_cb_op_hdr(&xdr, OP_CB_LAYOUT);
+out:
+    return status;
+}
+
 /*
  * RPC procedure tables
  */
@@ -333,6 +410,7 @@
 static struct rpc_procinfo     nfs4_cb_procedures[] = {
     PROC(CB_NULL,      NULL,     enc_cb_null,     dec_cb_null),
     PROC(CB_RECALL,    COMPOUND,   enc_cb_recall,      dec_cb_recall),
+    PROC(CB_LAYOUT,    COMPOUND,   enc_cb_layout,      dec_cb_layout),
 };
 
 static struct rpc_version       nfs_cb_version4 = {
@@ -545,5 +623,58 @@
      * or deleg_return. */
     dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, 
dp->dl_flock, atomic_read(&dp->dl_count));
     nfs4_put_delegation(dp);
+    return;
+}
+
+/*
+ * called with dp->dl_count inc'ed.
+ * nfs4_lock_state() may or may not have been called.
+ */
+void
+nfsd4_cb_layout(struct nfs4_cb_layout *cbl)
+{
+    struct nfs4_client *clp = cbl->cbl_client;
+    struct rpc_clnt *clnt = NULL;
+    struct rpc_message msg = {
+        .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_LAYOUT],
+        .rpc_argp = cbl,
+    };
+    int retries = 1;
+    int status = 0;
+
+    if (clp)
+        clnt = clp->cl_callback.cb_client;
+
+    if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt)
+        return;
+
+    msg.rpc_cred = nfsd4_lookupcred(clp, 0);
+    if (IS_ERR(msg.rpc_cred))
+        goto out;
+
+    status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+    while (retries--) {
+        switch (status) {
+            case -EIO:
+                /* Network partition? */
+            case -EBADHANDLE:
+                break;
+            default:
+                goto out_put_cred;
+        }
+        ssleep(2);
+        status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+    }
+
+out_put_cred:
+    put_rpccred(msg.rpc_cred);
+
+out:
+    if (status == -EIO)
+        atomic_set(&clp->cl_callback.cb_set, 0);
+    /* Success or failure, now we're either waiting for lease expiration
+       or layout_return. */
+    dprintk("NFSD: nfsd4_cb_layout: status %d\n", status);
+
     return;
 }
Index: fs/nfsd/nfs4state.c
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/fs/nfsd/nfs4state.c,v
retrieving revision 1.12
diff -u -r1.12 nfs4state.c
--- fs/nfsd/nfs4state.c    13 Jul 2006 17:18:41 -0000    1.12
+++ fs/nfsd/nfs4state.c    25 Jul 2006 04:11:43 -0000
@@ -3418,4 +3418,60 @@
     return status;
 }
 
+/*
+ * Recall a layout
+ */
+static int
+do_layout_recall(void *__lr)
+{
+    struct nfs4_cb_layout *lr = __lr;
+    struct nfs4_client *clp = NULL;
+        unsigned int i;
+
+    daemonize("nfsv4-layout");
+
+    /* if recall all */
+    if (lr->cbl_recall_type == RECALL_FSID) {
+
+        for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+            list_for_each_entry(clp, &conf_str_hashtbl[i], cl_strhash) {
+                if (clp) {
+                    if (!clp->cl_callback.cb_client)
+                        continue;
+                    lr->cbl_client = clp;
+                    nfsd4_cb_layout(lr);
+                }
+            }
+        }
+    }
+    else {
+        /* recall one layout ??? */
+        if (lr->cbl_client)
+            nfsd4_cb_layout(lr);
+    }
+    return 0;
+}
+
+/*
+ * Spawn a thread to perform a recall layout
+ *
+ */
+void nfsd_layout_recall_cb(struct nfs4_cb_layout *lr)
+{
+    struct task_struct *t;
+
+    dprintk("NFSD nfsd_layout_recall_cb: lp %p\n",lr);
+    if (!lr)
+        return;
+
+    t = kthread_run(do_layout_recall, lr, "%s", "nfs4_cb_recall");
+    if (IS_ERR(t)) {
+        struct nfs4_client *clp = lr->cbl_client;
+
+        printk(KERN_INFO "NFSD: Callback thread failed for "
+            "for client (clientid %08x/%08x)\n",
+            clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+    }
+}
+
 #endif /* CONFIG_PNFS */
Index: include/linux/nfs_fs_sb.h
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/include/linux/nfs_fs_sb.h,v
retrieving revision 1.5
diff -u -r1.5 nfs_fs_sb.h
--- include/linux/nfs_fs_sb.h    13 Jul 2006 17:18:47 -0000    1.5
+++ include/linux/nfs_fs_sb.h    25 Jul 2006 04:11:49 -0000
@@ -37,6 +37,7 @@
     struct sockaddr_in    addr;
     struct nfs_fsid        fsid;
     unsigned long        mount_time;    /* when this fs was mounted */
+    struct super_block    *sb;
 #ifdef CONFIG_NFS_V4
     /* Our own IP address, as a null-terminated string.
      * This is used to generate the clientid, and the callback address.
Index: include/linux/nfsd/nfsd4_pnfs.h
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/include/linux/nfsd/nfsd4_pnfs.h,v
retrieving revision 1.3
diff -u -r1.3 nfsd4_pnfs.h
--- include/linux/nfsd/nfsd4_pnfs.h    20 Apr 2006 16:21:17 -0000    1.3
+++ include/linux/nfsd/nfsd4_pnfs.h    25 Jul 2006 04:11:49 -0000
@@ -113,20 +113,6 @@
     u32                lr_type;    /* request */
 };
 
-enum layout_recall_type {
-    RECALL_FILE = 1,
-    RECALL_FSID = 2
-};
-
-struct layout_recall {
-    u32            layout_type;
-    u32            iomode;
-    u32            layoutchanged;
-    u64            offset;
-    u64            length;
-    struct super_block    *fsid;
-};
-
 struct layout_return {
     u64    offset;
     u64    length;
Index: include/linux/nfsd/state.h
===================================================================
RCS file: /cvs/nfsv4/cvs/pnfs/include/linux/nfsd/state.h,v
retrieving revision 1.6
diff -u -r1.6 state.h
--- include/linux/nfsd/state.h    12 Apr 2006 17:59:58 -0000    1.6
+++ include/linux/nfsd/state.h    25 Jul 2006 04:11:49 -0000
@@ -39,6 +39,7 @@
 
 #include <linux/list.h>
 #include <linux/kref.h>
+#include <linux/nfs_xdr.h>
 #include <linux/sunrpc/clnt.h>
 
 #define CONFIG_PNFS    1
@@ -136,6 +137,26 @@
     u32            cl_firststate;    /* recovery dir creation */
 };
 
+enum layout_recall_type {
+    RECALL_FILE = 1,
+    RECALL_FSID = 2
+};
+
+struct nfs4_cb_layout {
+    struct super_block    *cbl_sb;
+    struct nfs4_client    *cbl_client;
+    u32            cbl_ident;
+    u32            cbl_recall_type;
+    u32            cbl_layout_type;
+    u32            cbl_iomode;
+    u32            cbl_layoutchanged;
+    u64            cbl_offset;
+    u64            cbl_length;
+    struct nfs_fsid        cbl_fsid;
+    u32            cbl_fhlen;
+    u32            cbl_fhval[NFS4_FHSIZE];
+};
+
 /* struct nfs4_client_reset
  * one per old client. Populates reset_str_hashtbl. Filled from 
conf_id_hashtbl
  * upon lease reset, or from upcall to state_daemon (to read in state
@@ -299,6 +320,7 @@
 extern void nfs4_free_stateowner(struct kref *kref);
 extern void nfsd4_probe_callback(struct nfs4_client *clp);
 extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
+extern void nfsd4_cb_layout(struct nfs4_cb_layout *lp);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
 extern int nfs4_make_rec_clidname(char *clidname, struct xdr_netobj 
*clname);
 extern void nfsd4_init_recdir(char *recdir_name);



More information about the pNFS mailing list