Commit 38524ab3 authored by Andy Adamson's avatar Andy Adamson Committed by J. Bruce Fields

nfsd41: Backchannel: callback infrastructure

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: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarRicardo Labiaga <Ricardo.Labiaga@netapp.com>
[get callback minorversion from fore channel's]
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
[nfsd41: change bc_sock to bc_xprt]
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
[pulled definition for cl_cb_xprt]
Signed-off-by: default avatarBenny 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: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 80fc015b
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <linux/sunrpc/xdr.h> #include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svc.h> #include <linux/sunrpc/svc.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/nfsd/nfsd.h> #include <linux/nfsd/nfsd.h>
#include <linux/nfsd/state.h> #include <linux/nfsd/state.h>
#include <linux/sunrpc/sched.h> #include <linux/sunrpc/sched.h>
...@@ -52,16 +53,19 @@ ...@@ -52,16 +53,19 @@
#define NFSPROC4_CB_NULL 0 #define NFSPROC4_CB_NULL 0
#define NFSPROC4_CB_COMPOUND 1 #define NFSPROC4_CB_COMPOUND 1
#define NFS4_STATEID_SIZE 16
/* Index of predefined Linux callback client operations */ /* Index of predefined Linux callback client operations */
enum { enum {
NFSPROC4_CLNT_CB_NULL = 0, NFSPROC4_CLNT_CB_NULL = 0,
NFSPROC4_CLNT_CB_RECALL, NFSPROC4_CLNT_CB_RECALL,
NFSPROC4_CLNT_CB_SEQUENCE,
}; };
enum nfs_cb_opnum4 { enum nfs_cb_opnum4 {
OP_CB_RECALL = 4, OP_CB_RECALL = 4,
OP_CB_SEQUENCE = 11,
}; };
#define NFS4_MAXTAGLEN 20 #define NFS4_MAXTAGLEN 20
...@@ -70,15 +74,22 @@ enum nfs_cb_opnum4 { ...@@ -70,15 +74,22 @@ enum nfs_cb_opnum4 {
#define NFS4_dec_cb_null_sz 0 #define NFS4_dec_cb_null_sz 0
#define cb_compound_enc_hdr_sz 4 #define cb_compound_enc_hdr_sz 4
#define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2)) #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_enc_sz 1
#define op_dec_sz 2 #define op_dec_sz 2
#define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2)) #define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2))
#define enc_stateid_sz (NFS4_STATEID_SIZE >> 2) #define enc_stateid_sz (NFS4_STATEID_SIZE >> 2)
#define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \ #define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \
cb_sequence_enc_sz + \
1 + enc_stateid_sz + \ 1 + enc_stateid_sz + \
enc_nfs4_fh_sz) enc_nfs4_fh_sz)
#define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \ #define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \
cb_sequence_dec_sz + \
op_dec_sz) op_dec_sz)
/* /*
...@@ -137,11 +148,13 @@ xdr_error: \ ...@@ -137,11 +148,13 @@ xdr_error: \
} while (0) } while (0)
struct nfs4_cb_compound_hdr { struct nfs4_cb_compound_hdr {
int status; /* args */
u32 ident; u32 ident; /* minorversion 0 only */
u32 nops; u32 nops;
__be32 *nops_p; __be32 *nops_p;
u32 minorversion; u32 minorversion;
/* res */
int status;
u32 taglen; u32 taglen;
char *tag; char *tag;
}; };
......
...@@ -702,6 +702,8 @@ static inline void ...@@ -702,6 +702,8 @@ static inline void
free_client(struct nfs4_client *clp) free_client(struct nfs4_client *clp)
{ {
shutdown_callback_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) if (clp->cl_cred.cr_group_info)
put_group_info(clp->cl_cred.cr_group_info); put_group_info(clp->cl_cred.cr_group_info);
kfree(clp->cl_principal); kfree(clp->cl_principal);
...@@ -1317,6 +1319,18 @@ nfsd4_create_session(struct svc_rqst *rqstp, ...@@ -1317,6 +1319,18 @@ nfsd4_create_session(struct svc_rqst *rqstp,
cr_ses->flags &= ~SESSION4_PERSIST; cr_ses->flags &= ~SESSION4_PERSIST;
cr_ses->flags &= ~SESSION4_RDMA; 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; conf = unconf;
} else { } else {
status = nfserr_stale_clientid; status = nfserr_stale_clientid;
......
...@@ -211,6 +211,9 @@ struct nfs4_client { ...@@ -211,6 +211,9 @@ struct nfs4_client {
struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */ struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */
u32 cl_exchange_flags; u32 cl_exchange_flags;
struct nfs4_sessionid cl_sessionid; struct nfs4_sessionid cl_sessionid;
/* for nfs41 callbacks */
struct svc_xprt *cl_cb_xprt; /* 4.1 callback transport */
}; };
/* struct nfs4_client_reset /* struct nfs4_client_reset
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment