nfsd41: Backchannel: callback infrastructure
authorAndy Adamson <andros@netapp.com>
Thu, 10 Sep 2009 09:25:59 +0000 (12:25 +0300)
committerJ. Bruce Fields <bfields@citi.umich.edu>
Wed, 16 Sep 2009 00:49:55 +0000 (20:49 -0400)
Keep the xprt used for create_session in cl_cb_xprt.
Mark cl_callback.cb_minorversion = 1 and remember
the client provided cl_callback.cb_prog rpc program number.
Use it to probe the callback path.

Use the client's network address to initialize as the
callback's address as expected by the xprt creation
routines.

Define xdr sizes and code nfs4_cb_compound header to be able
to send a null callback rpc.

Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
[get callback minorversion from fore channel's]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfsd41: change bc_sock to bc_xprt]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[pulled definition for cl_cb_xprt]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfsd41: set up backchannel's cb_addr]
[moved rpc_create_args init to "nfsd: modify nfsd4.1 backchannel to use new xprt class"]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4state.c
include/linux/nfsd/state.h

index 128519769ea843e56dd005bd8b5d42177473f8c5..db4188ce9b000d74c76cd09e3f5d1296d0329268 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/svcsock.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/state.h>
 #include <linux/sunrpc/sched.h>
 
 #define NFSPROC4_CB_NULL 0
 #define NFSPROC4_CB_COMPOUND 1
+#define NFS4_STATEID_SIZE 16
 
 /* Index of predefined Linux callback client operations */
 
 enum {
        NFSPROC4_CLNT_CB_NULL = 0,
        NFSPROC4_CLNT_CB_RECALL,
+       NFSPROC4_CLNT_CB_SEQUENCE,
 };
 
 enum nfs_cb_opnum4 {
        OP_CB_RECALL            = 4,
+       OP_CB_SEQUENCE          = 11,
 };
 
 #define NFS4_MAXTAGLEN         20
@@ -70,15 +74,22 @@ enum nfs_cb_opnum4 {
 #define NFS4_dec_cb_null_sz            0
 #define cb_compound_enc_hdr_sz         4
 #define cb_compound_dec_hdr_sz         (3 + (NFS4_MAXTAGLEN >> 2))
+#define sessionid_sz                   (NFS4_MAX_SESSIONID_LEN >> 2)
+#define cb_sequence_enc_sz             (sessionid_sz + 4 +             \
+                                       1 /* no referring calls list yet */)
+#define cb_sequence_dec_sz             (op_dec_sz + sessionid_sz + 4)
+
 #define op_enc_sz                      1
 #define op_dec_sz                      2
 #define enc_nfs4_fh_sz                 (1 + (NFS4_FHSIZE >> 2))
 #define enc_stateid_sz                 (NFS4_STATEID_SIZE >> 2)
 #define NFS4_enc_cb_recall_sz          (cb_compound_enc_hdr_sz +       \
+                                       cb_sequence_enc_sz +            \
                                        1 + enc_stateid_sz +            \
                                        enc_nfs4_fh_sz)
 
 #define NFS4_dec_cb_recall_sz          (cb_compound_dec_hdr_sz  +      \
+                                       cb_sequence_dec_sz +            \
                                        op_dec_sz)
 
 /*
@@ -137,11 +148,13 @@ xdr_error:                                      \
 } while (0)
 
 struct nfs4_cb_compound_hdr {
-       int             status;
-       u32             ident;
+       /* args */
+       u32             ident;  /* minorversion 0 only */
        u32             nops;
        __be32          *nops_p;
        u32             minorversion;
+       /* res */
+       int             status;
        u32             taglen;
        char            *tag;
 };
index 0445192d660d5414467dc367e4e1a6baf56f43da..d8196b453f616e6e29f610c48981654653a1051e 100644 (file)
@@ -702,6 +702,8 @@ static inline void
 free_client(struct nfs4_client *clp)
 {
        shutdown_callback_client(clp);
+       if (clp->cl_cb_xprt)
+               svc_xprt_put(clp->cl_cb_xprt);
        if (clp->cl_cred.cr_group_info)
                put_group_info(clp->cl_cred.cr_group_info);
        kfree(clp->cl_principal);
@@ -1317,6 +1319,18 @@ nfsd4_create_session(struct svc_rqst *rqstp,
                cr_ses->flags &= ~SESSION4_PERSIST;
                cr_ses->flags &= ~SESSION4_RDMA;
 
+               if (cr_ses->flags & SESSION4_BACK_CHAN) {
+                       unconf->cl_cb_xprt = rqstp->rq_xprt;
+                       svc_xprt_get(unconf->cl_cb_xprt);
+                       rpc_copy_addr(
+                               (struct sockaddr *)&unconf->cl_cb_conn.cb_addr,
+                               sa);
+                       unconf->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
+                       unconf->cl_cb_conn.cb_minorversion =
+                               cstate->minorversion;
+                       unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
+                       nfsd4_probe_callback(unconf);
+               }
                conf = unconf;
        } else {
                status = nfserr_stale_clientid;
index 9bf3aa8c5aeacd9a2bc17fa55bc4df3887db01b1..c916032570c46f022f206d9161b1be4353fb3ddd 100644 (file)
@@ -211,6 +211,9 @@ struct nfs4_client {
        struct nfsd4_clid_slot  cl_cs_slot;     /* create_session slot */
        u32                     cl_exchange_flags;
        struct nfs4_sessionid   cl_sessionid;
+
+       /* for nfs41 callbacks */
+       struct svc_xprt         *cl_cb_xprt;    /* 4.1 callback transport */
 };
 
 /* struct nfs4_client_reset