aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4callback.c17
-rw-r--r--fs/nfsd/nfs4state.c14
-rw-r--r--include/linux/nfsd/state.h3
3 files changed, 32 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 128519769ea8..db4188ce9b00 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -43,6 +43,7 @@
43#include <linux/sunrpc/xdr.h> 43#include <linux/sunrpc/xdr.h>
44#include <linux/sunrpc/svc.h> 44#include <linux/sunrpc/svc.h>
45#include <linux/sunrpc/clnt.h> 45#include <linux/sunrpc/clnt.h>
46#include <linux/sunrpc/svcsock.h>
46#include <linux/nfsd/nfsd.h> 47#include <linux/nfsd/nfsd.h>
47#include <linux/nfsd/state.h> 48#include <linux/nfsd/state.h>
48#include <linux/sunrpc/sched.h> 49#include <linux/sunrpc/sched.h>
@@ -52,16 +53,19 @@
52 53
53#define NFSPROC4_CB_NULL 0 54#define NFSPROC4_CB_NULL 0
54#define NFSPROC4_CB_COMPOUND 1 55#define NFSPROC4_CB_COMPOUND 1
56#define NFS4_STATEID_SIZE 16
55 57
56/* Index of predefined Linux callback client operations */ 58/* Index of predefined Linux callback client operations */
57 59
58enum { 60enum {
59 NFSPROC4_CLNT_CB_NULL = 0, 61 NFSPROC4_CLNT_CB_NULL = 0,
60 NFSPROC4_CLNT_CB_RECALL, 62 NFSPROC4_CLNT_CB_RECALL,
63 NFSPROC4_CLNT_CB_SEQUENCE,
61}; 64};
62 65
63enum nfs_cb_opnum4 { 66enum nfs_cb_opnum4 {
64 OP_CB_RECALL = 4, 67 OP_CB_RECALL = 4,
68 OP_CB_SEQUENCE = 11,
65}; 69};
66 70
67#define NFS4_MAXTAGLEN 20 71#define NFS4_MAXTAGLEN 20
@@ -70,15 +74,22 @@ enum nfs_cb_opnum4 {
70#define NFS4_dec_cb_null_sz 0 74#define NFS4_dec_cb_null_sz 0
71#define cb_compound_enc_hdr_sz 4 75#define cb_compound_enc_hdr_sz 4
72#define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2)) 76#define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2))
77#define sessionid_sz (NFS4_MAX_SESSIONID_LEN >> 2)
78#define cb_sequence_enc_sz (sessionid_sz + 4 + \
79 1 /* no referring calls list yet */)
80#define cb_sequence_dec_sz (op_dec_sz + sessionid_sz + 4)
81
73#define op_enc_sz 1 82#define op_enc_sz 1
74#define op_dec_sz 2 83#define op_dec_sz 2
75#define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2)) 84#define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2))
76#define enc_stateid_sz (NFS4_STATEID_SIZE >> 2) 85#define enc_stateid_sz (NFS4_STATEID_SIZE >> 2)
77#define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \ 86#define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \
87 cb_sequence_enc_sz + \
78 1 + enc_stateid_sz + \ 88 1 + enc_stateid_sz + \
79 enc_nfs4_fh_sz) 89 enc_nfs4_fh_sz)
80 90
81#define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \ 91#define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \
92 cb_sequence_dec_sz + \
82 op_dec_sz) 93 op_dec_sz)
83 94
84/* 95/*
@@ -137,11 +148,13 @@ xdr_error: \
137} while (0) 148} while (0)
138 149
139struct nfs4_cb_compound_hdr { 150struct nfs4_cb_compound_hdr {
140 int status; 151 /* args */
141 u32 ident; 152 u32 ident; /* minorversion 0 only */
142 u32 nops; 153 u32 nops;
143 __be32 *nops_p; 154 __be32 *nops_p;
144 u32 minorversion; 155 u32 minorversion;
156 /* res */
157 int status;
145 u32 taglen; 158 u32 taglen;
146 char *tag; 159 char *tag;
147}; 160};
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 0445192d660d..d8196b453f61 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -702,6 +702,8 @@ static inline void
702free_client(struct nfs4_client *clp) 702free_client(struct nfs4_client *clp)
703{ 703{
704 shutdown_callback_client(clp); 704 shutdown_callback_client(clp);
705 if (clp->cl_cb_xprt)
706 svc_xprt_put(clp->cl_cb_xprt);
705 if (clp->cl_cred.cr_group_info) 707 if (clp->cl_cred.cr_group_info)
706 put_group_info(clp->cl_cred.cr_group_info); 708 put_group_info(clp->cl_cred.cr_group_info);
707 kfree(clp->cl_principal); 709 kfree(clp->cl_principal);
@@ -1317,6 +1319,18 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1317 cr_ses->flags &= ~SESSION4_PERSIST; 1319 cr_ses->flags &= ~SESSION4_PERSIST;
1318 cr_ses->flags &= ~SESSION4_RDMA; 1320 cr_ses->flags &= ~SESSION4_RDMA;
1319 1321
1322 if (cr_ses->flags & SESSION4_BACK_CHAN) {
1323 unconf->cl_cb_xprt = rqstp->rq_xprt;
1324 svc_xprt_get(unconf->cl_cb_xprt);
1325 rpc_copy_addr(
1326 (struct sockaddr *)&unconf->cl_cb_conn.cb_addr,
1327 sa);
1328 unconf->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
1329 unconf->cl_cb_conn.cb_minorversion =
1330 cstate->minorversion;
1331 unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
1332 nfsd4_probe_callback(unconf);
1333 }
1320 conf = unconf; 1334 conf = unconf;
1321 } else { 1335 } else {
1322 status = nfserr_stale_clientid; 1336 status = nfserr_stale_clientid;
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 9bf3aa8c5aea..c916032570c4 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -211,6 +211,9 @@ struct nfs4_client {
211 struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */ 211 struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */
212 u32 cl_exchange_flags; 212 u32 cl_exchange_flags;
213 struct nfs4_sessionid cl_sessionid; 213 struct nfs4_sessionid cl_sessionid;
214
215 /* for nfs41 callbacks */
216 struct svc_xprt *cl_cb_xprt; /* 4.1 callback transport */
214}; 217};
215 218
216/* struct nfs4_client_reset 219/* struct nfs4_client_reset