aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/Kconfig9
-rw-r--r--fs/nfs/callback.c214
-rw-r--r--fs/nfs/callback.h68
-rw-r--r--fs/nfs/callback_proc.c127
-rw-r--r--fs/nfs/callback_xdr.c280
-rw-r--r--fs/nfs/client.c182
-rw-r--r--fs/nfs/direct.c9
-rw-r--r--fs/nfs/internal.h62
-rw-r--r--fs/nfs/nfs4_fs.h37
-rw-r--r--fs/nfs/nfs4proc.c1287
-rw-r--r--fs/nfs/nfs4renewd.c6
-rw-r--r--fs/nfs/nfs4state.c153
-rw-r--r--fs/nfs/nfs4xdr.c1072
-rw-r--r--fs/nfs/read.c33
-rw-r--r--fs/nfs/super.c13
-rw-r--r--fs/nfs/unlink.c20
-rw-r--r--fs/nfs/write.c31
-rw-r--r--include/linux/nfs4.h18
-rw-r--r--include/linux/nfs_fs_sb.h67
-rw-r--r--include/linux/nfs_xdr.h171
-rw-r--r--include/linux/nfsd/state.h1
-rw-r--r--include/linux/sunrpc/bc_xprt.h49
-rw-r--r--include/linux/sunrpc/clnt.h1
-rw-r--r--include/linux/sunrpc/sched.h3
-rw-r--r--include/linux/sunrpc/svc.h11
-rw-r--r--include/linux/sunrpc/svcsock.h2
-rw-r--r--include/linux/sunrpc/xprt.h38
-rw-r--r--net/sunrpc/Makefile1
-rw-r--r--net/sunrpc/backchannel_rqst.c278
-rw-r--r--net/sunrpc/bc_svc.c81
-rw-r--r--net/sunrpc/clnt.c143
-rw-r--r--net/sunrpc/sched.c2
-rw-r--r--net/sunrpc/stats.c8
-rw-r--r--net/sunrpc/sunrpc.h37
-rw-r--r--net/sunrpc/svc.c134
-rw-r--r--net/sunrpc/svcsock.c39
-rw-r--r--net/sunrpc/xprt.c60
-rw-r--r--net/sunrpc/xprtsock.c216
38 files changed, 4589 insertions, 374 deletions
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index e67f3ec07736..5d6d6f415935 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -74,6 +74,15 @@ config NFS_V4
74 74
75 If unsure, say N. 75 If unsure, say N.
76 76
77config NFS_V4_1
78 bool "NFS client support for NFSv4.1 (DEVELOPER ONLY)"
79 depends on NFS_V4 && EXPERIMENTAL
80 help
81 This option enables support for minor version 1 of the NFSv4 protocol
82 (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client.
83
84 Unless you're an NFS developer, say N.
85
77config ROOT_NFS 86config ROOT_NFS
78 bool "Root file system on NFS" 87 bool "Root file system on NFS"
79 depends on NFS_FS=y && IP_PNP 88 depends on NFS_FS=y && IP_PNP
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index a886e692ddd0..e69b8f61189e 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -17,6 +17,9 @@
17#include <linux/freezer.h> 17#include <linux/freezer.h>
18#include <linux/kthread.h> 18#include <linux/kthread.h>
19#include <linux/sunrpc/svcauth_gss.h> 19#include <linux/sunrpc/svcauth_gss.h>
20#if defined(CONFIG_NFS_V4_1)
21#include <linux/sunrpc/bc_xprt.h>
22#endif
20 23
21#include <net/inet_sock.h> 24#include <net/inet_sock.h>
22 25
@@ -28,11 +31,12 @@
28 31
29struct nfs_callback_data { 32struct nfs_callback_data {
30 unsigned int users; 33 unsigned int users;
34 struct svc_serv *serv;
31 struct svc_rqst *rqst; 35 struct svc_rqst *rqst;
32 struct task_struct *task; 36 struct task_struct *task;
33}; 37};
34 38
35static struct nfs_callback_data nfs_callback_info; 39static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
36static DEFINE_MUTEX(nfs_callback_mutex); 40static DEFINE_MUTEX(nfs_callback_mutex);
37static struct svc_program nfs4_callback_program; 41static struct svc_program nfs4_callback_program;
38 42
@@ -56,10 +60,10 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
56 &nfs_callback_set_tcpport, 0644); 60 &nfs_callback_set_tcpport, 0644);
57 61
58/* 62/*
59 * This is the callback kernel thread. 63 * This is the NFSv4 callback kernel thread.
60 */ 64 */
61static int 65static int
62nfs_callback_svc(void *vrqstp) 66nfs4_callback_svc(void *vrqstp)
63{ 67{
64 int err, preverr = 0; 68 int err, preverr = 0;
65 struct svc_rqst *rqstp = vrqstp; 69 struct svc_rqst *rqstp = vrqstp;
@@ -97,20 +101,12 @@ nfs_callback_svc(void *vrqstp)
97} 101}
98 102
99/* 103/*
100 * Bring up the callback thread if it is not already up. 104 * Prepare to bring up the NFSv4 callback service
101 */ 105 */
102int nfs_callback_up(void) 106struct svc_rqst *
107nfs4_callback_up(struct svc_serv *serv)
103{ 108{
104 struct svc_serv *serv = NULL; 109 int ret;
105 int ret = 0;
106
107 mutex_lock(&nfs_callback_mutex);
108 if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
109 goto out;
110 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
111 ret = -ENOMEM;
112 if (!serv)
113 goto out_err;
114 110
115 ret = svc_create_xprt(serv, "tcp", PF_INET, 111 ret = svc_create_xprt(serv, "tcp", PF_INET,
116 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 112 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
@@ -131,23 +127,168 @@ int nfs_callback_up(void)
131 goto out_err; 127 goto out_err;
132#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ 128#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
133 129
134 nfs_callback_info.rqst = svc_prepare_thread(serv, &serv->sv_pools[0]); 130 return svc_prepare_thread(serv, &serv->sv_pools[0]);
135 if (IS_ERR(nfs_callback_info.rqst)) { 131
136 ret = PTR_ERR(nfs_callback_info.rqst); 132out_err:
137 nfs_callback_info.rqst = NULL; 133 if (ret == 0)
134 ret = -ENOMEM;
135 return ERR_PTR(ret);
136}
137
138#if defined(CONFIG_NFS_V4_1)
139/*
140 * The callback service for NFSv4.1 callbacks
141 */
142static int
143nfs41_callback_svc(void *vrqstp)
144{
145 struct svc_rqst *rqstp = vrqstp;
146 struct svc_serv *serv = rqstp->rq_server;
147 struct rpc_rqst *req;
148 int error;
149 DEFINE_WAIT(wq);
150
151 set_freezable();
152
153 /*
154 * FIXME: do we really need to run this under the BKL? If so, please
155 * add a comment about what it's intended to protect.
156 */
157 lock_kernel();
158 while (!kthread_should_stop()) {
159 prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
160 spin_lock_bh(&serv->sv_cb_lock);
161 if (!list_empty(&serv->sv_cb_list)) {
162 req = list_first_entry(&serv->sv_cb_list,
163 struct rpc_rqst, rq_bc_list);
164 list_del(&req->rq_bc_list);
165 spin_unlock_bh(&serv->sv_cb_lock);
166 dprintk("Invoking bc_svc_process()\n");
167 error = bc_svc_process(serv, req, rqstp);
168 dprintk("bc_svc_process() returned w/ error code= %d\n",
169 error);
170 } else {
171 spin_unlock_bh(&serv->sv_cb_lock);
172 schedule();
173 }
174 finish_wait(&serv->sv_cb_waitq, &wq);
175 }
176 unlock_kernel();
177 return 0;
178}
179
180/*
181 * Bring up the NFSv4.1 callback service
182 */
183struct svc_rqst *
184nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
185{
186 struct svc_xprt *bc_xprt;
187 struct svc_rqst *rqstp = ERR_PTR(-ENOMEM);
188
189 dprintk("--> %s\n", __func__);
190 /* Create a svc_sock for the service */
191 bc_xprt = svc_sock_create(serv, xprt->prot);
192 if (!bc_xprt)
193 goto out;
194
195 /*
196 * Save the svc_serv in the transport so that it can
197 * be referenced when the session backchannel is initialized
198 */
199 serv->bc_xprt = bc_xprt;
200 xprt->bc_serv = serv;
201
202 INIT_LIST_HEAD(&serv->sv_cb_list);
203 spin_lock_init(&serv->sv_cb_lock);
204 init_waitqueue_head(&serv->sv_cb_waitq);
205 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
206 if (IS_ERR(rqstp))
207 svc_sock_destroy(bc_xprt);
208out:
209 dprintk("--> %s return %p\n", __func__, rqstp);
210 return rqstp;
211}
212
213static inline int nfs_minorversion_callback_svc_setup(u32 minorversion,
214 struct svc_serv *serv, struct rpc_xprt *xprt,
215 struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
216{
217 if (minorversion) {
218 *rqstpp = nfs41_callback_up(serv, xprt);
219 *callback_svc = nfs41_callback_svc;
220 }
221 return minorversion;
222}
223
224static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
225 struct nfs_callback_data *cb_info)
226{
227 if (minorversion)
228 xprt->bc_serv = cb_info->serv;
229}
230#else
231static inline int nfs_minorversion_callback_svc_setup(u32 minorversion,
232 struct svc_serv *serv, struct rpc_xprt *xprt,
233 struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
234{
235 return 0;
236}
237
238static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
239 struct nfs_callback_data *cb_info)
240{
241}
242#endif /* CONFIG_NFS_V4_1 */
243
244/*
245 * Bring up the callback thread if it is not already up.
246 */
247int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
248{
249 struct svc_serv *serv = NULL;
250 struct svc_rqst *rqstp;
251 int (*callback_svc)(void *vrqstp);
252 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
253 char svc_name[12];
254 int ret = 0;
255 int minorversion_setup;
256
257 mutex_lock(&nfs_callback_mutex);
258 if (cb_info->users++ || cb_info->task != NULL) {
259 nfs_callback_bc_serv(minorversion, xprt, cb_info);
260 goto out;
261 }
262 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
263 if (!serv) {
264 ret = -ENOMEM;
265 goto out_err;
266 }
267
268 minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion,
269 serv, xprt, &rqstp, &callback_svc);
270 if (!minorversion_setup) {
271 /* v4.0 callback setup */
272 rqstp = nfs4_callback_up(serv);
273 callback_svc = nfs4_callback_svc;
274 }
275
276 if (IS_ERR(rqstp)) {
277 ret = PTR_ERR(rqstp);
138 goto out_err; 278 goto out_err;
139 } 279 }
140 280
141 svc_sock_update_bufs(serv); 281 svc_sock_update_bufs(serv);
142 282
143 nfs_callback_info.task = kthread_run(nfs_callback_svc, 283 sprintf(svc_name, "nfsv4.%u-svc", minorversion);
144 nfs_callback_info.rqst, 284 cb_info->serv = serv;
145 "nfsv4-svc"); 285 cb_info->rqst = rqstp;
146 if (IS_ERR(nfs_callback_info.task)) { 286 cb_info->task = kthread_run(callback_svc, cb_info->rqst, svc_name);
147 ret = PTR_ERR(nfs_callback_info.task); 287 if (IS_ERR(cb_info->task)) {
148 svc_exit_thread(nfs_callback_info.rqst); 288 ret = PTR_ERR(cb_info->task);
149 nfs_callback_info.rqst = NULL; 289 svc_exit_thread(cb_info->rqst);
150 nfs_callback_info.task = NULL; 290 cb_info->rqst = NULL;
291 cb_info->task = NULL;
151 goto out_err; 292 goto out_err;
152 } 293 }
153out: 294out:
@@ -164,22 +305,25 @@ out:
164out_err: 305out_err:
165 dprintk("NFS: Couldn't create callback socket or server thread; " 306 dprintk("NFS: Couldn't create callback socket or server thread; "
166 "err = %d\n", ret); 307 "err = %d\n", ret);
167 nfs_callback_info.users--; 308 cb_info->users--;
168 goto out; 309 goto out;
169} 310}
170 311
171/* 312/*
172 * Kill the callback thread if it's no longer being used. 313 * Kill the callback thread if it's no longer being used.
173 */ 314 */
174void nfs_callback_down(void) 315void nfs_callback_down(int minorversion)
175{ 316{
317 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
318
176 mutex_lock(&nfs_callback_mutex); 319 mutex_lock(&nfs_callback_mutex);
177 nfs_callback_info.users--; 320 cb_info->users--;
178 if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL) { 321 if (cb_info->users == 0 && cb_info->task != NULL) {
179 kthread_stop(nfs_callback_info.task); 322 kthread_stop(cb_info->task);
180 svc_exit_thread(nfs_callback_info.rqst); 323 svc_exit_thread(cb_info->rqst);
181 nfs_callback_info.rqst = NULL; 324 cb_info->serv = NULL;
182 nfs_callback_info.task = NULL; 325 cb_info->rqst = NULL;
326 cb_info->task = NULL;
183 } 327 }
184 mutex_unlock(&nfs_callback_mutex); 328 mutex_unlock(&nfs_callback_mutex);
185} 329}
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index e110e286a262..07baa8254ca1 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -20,13 +20,24 @@ enum nfs4_callback_procnum {
20enum nfs4_callback_opnum { 20enum nfs4_callback_opnum {
21 OP_CB_GETATTR = 3, 21 OP_CB_GETATTR = 3,
22 OP_CB_RECALL = 4, 22 OP_CB_RECALL = 4,
23/* Callback operations new to NFSv4.1 */
24 OP_CB_LAYOUTRECALL = 5,
25 OP_CB_NOTIFY = 6,
26 OP_CB_PUSH_DELEG = 7,
27 OP_CB_RECALL_ANY = 8,
28 OP_CB_RECALLABLE_OBJ_AVAIL = 9,
29 OP_CB_RECALL_SLOT = 10,
30 OP_CB_SEQUENCE = 11,
31 OP_CB_WANTS_CANCELLED = 12,
32 OP_CB_NOTIFY_LOCK = 13,
33 OP_CB_NOTIFY_DEVICEID = 14,
23 OP_CB_ILLEGAL = 10044, 34 OP_CB_ILLEGAL = 10044,
24}; 35};
25 36
26struct cb_compound_hdr_arg { 37struct cb_compound_hdr_arg {
27 unsigned int taglen; 38 unsigned int taglen;
28 const char *tag; 39 const char *tag;
29 unsigned int callback_ident; 40 unsigned int minorversion;
30 unsigned nops; 41 unsigned nops;
31}; 42};
32 43
@@ -59,16 +70,59 @@ struct cb_recallargs {
59 uint32_t truncate; 70 uint32_t truncate;
60}; 71};
61 72
73#if defined(CONFIG_NFS_V4_1)
74
75struct referring_call {
76 uint32_t rc_sequenceid;
77 uint32_t rc_slotid;
78};
79
80struct referring_call_list {
81 struct nfs4_sessionid rcl_sessionid;
82 uint32_t rcl_nrefcalls;
83 struct referring_call *rcl_refcalls;
84};
85
86struct cb_sequenceargs {
87 struct sockaddr *csa_addr;
88 struct nfs4_sessionid csa_sessionid;
89 uint32_t csa_sequenceid;
90 uint32_t csa_slotid;
91 uint32_t csa_highestslotid;
92 uint32_t csa_cachethis;
93 uint32_t csa_nrclists;
94 struct referring_call_list *csa_rclists;
95};
96
97struct cb_sequenceres {
98 __be32 csr_status;
99 struct nfs4_sessionid csr_sessionid;
100 uint32_t csr_sequenceid;
101 uint32_t csr_slotid;
102 uint32_t csr_highestslotid;
103 uint32_t csr_target_highestslotid;
104};
105
106extern unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
107 struct cb_sequenceres *res);
108
109#endif /* CONFIG_NFS_V4_1 */
110
62extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); 111extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
63extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy); 112extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
64 113
65#ifdef CONFIG_NFS_V4 114#ifdef CONFIG_NFS_V4
66extern int nfs_callback_up(void); 115extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt);
67extern void nfs_callback_down(void); 116extern void nfs_callback_down(int minorversion);
68#else 117#endif /* CONFIG_NFS_V4 */
69#define nfs_callback_up() (0) 118
70#define nfs_callback_down() do {} while(0) 119/*
71#endif 120 * nfs41: Callbacks are expected to not cause substantial latency,
121 * so we limit their concurrency to 1 by setting up the maximum number
122 * of slots for the backchannel.
123 */
124#define NFS41_BC_MIN_CALLBACKS 1
125#define NFS41_BC_MAX_CALLBACKS 1
72 126
73extern unsigned int nfs_callback_set_tcpport; 127extern unsigned int nfs_callback_set_tcpport;
74extern unsigned short nfs_callback_tcpport; 128extern unsigned short nfs_callback_tcpport;
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index f7e83e23cf9f..b7da1f54da68 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -101,3 +101,130 @@ out:
101 dprintk("%s: exit with status = %d\n", __func__, ntohl(res)); 101 dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
102 return res; 102 return res;
103} 103}
104
105#if defined(CONFIG_NFS_V4_1)
106
107/*
108 * Validate the sequenceID sent by the server.
109 * Return success if the sequenceID is one more than what we last saw on
110 * this slot, accounting for wraparound. Increments the slot's sequence.
111 *
112 * We don't yet implement a duplicate request cache, so at this time
113 * we will log replays, and process them as if we had not seen them before,
114 * but we don't bump the sequence in the slot. Not too worried about it,
115 * since we only currently implement idempotent callbacks anyway.
116 *
117 * We have a single slot backchannel at this time, so we don't bother
118 * checking the used_slots bit array on the table. The lower layer guarantees
119 * a single outstanding callback request at a time.
120 */
121static int
122validate_seqid(struct nfs4_slot_table *tbl, u32 slotid, u32 seqid)
123{
124 struct nfs4_slot *slot;
125
126 dprintk("%s enter. slotid %d seqid %d\n",
127 __func__, slotid, seqid);
128
129 if (slotid > NFS41_BC_MAX_CALLBACKS)
130 return htonl(NFS4ERR_BADSLOT);
131
132 slot = tbl->slots + slotid;
133 dprintk("%s slot table seqid: %d\n", __func__, slot->seq_nr);
134
135 /* Normal */
136 if (likely(seqid == slot->seq_nr + 1)) {
137 slot->seq_nr++;
138 return htonl(NFS4_OK);
139 }
140
141 /* Replay */
142 if (seqid == slot->seq_nr) {
143 dprintk("%s seqid %d is a replay - no DRC available\n",
144 __func__, seqid);
145 return htonl(NFS4_OK);
146 }
147
148 /* Wraparound */
149 if (seqid == 1 && (slot->seq_nr + 1) == 0) {
150 slot->seq_nr = 1;
151 return htonl(NFS4_OK);
152 }
153
154 /* Misordered request */
155 return htonl(NFS4ERR_SEQ_MISORDERED);
156}
157
158/*
159 * Returns a pointer to a held 'struct nfs_client' that matches the server's
160 * address, major version number, and session ID. It is the caller's
161 * responsibility to release the returned reference.
162 *
163 * Returns NULL if there are no connections with sessions, or if no session
164 * matches the one of interest.
165 */
166 static struct nfs_client *find_client_with_session(
167 const struct sockaddr *addr, u32 nfsversion,
168 struct nfs4_sessionid *sessionid)
169{
170 struct nfs_client *clp;
171
172 clp = nfs_find_client(addr, 4);
173 if (clp == NULL)
174 return NULL;
175
176 do {
177 struct nfs_client *prev = clp;
178
179 if (clp->cl_session != NULL) {
180 if (memcmp(clp->cl_session->sess_id.data,
181 sessionid->data,
182 NFS4_MAX_SESSIONID_LEN) == 0) {
183 /* Returns a held reference to clp */
184 return clp;
185 }
186 }
187 clp = nfs_find_client_next(prev);
188 nfs_put_client(prev);
189 } while (clp != NULL);
190
191 return NULL;
192}
193
194/* FIXME: referring calls should be processed */
195unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
196 struct cb_sequenceres *res)
197{
198 struct nfs_client *clp;
199 int i, status;
200
201 for (i = 0; i < args->csa_nrclists; i++)
202 kfree(args->csa_rclists[i].rcl_refcalls);
203 kfree(args->csa_rclists);
204
205 status = htonl(NFS4ERR_BADSESSION);
206 clp = find_client_with_session(args->csa_addr, 4, &args->csa_sessionid);
207 if (clp == NULL)
208 goto out;
209
210 status = validate_seqid(&clp->cl_session->bc_slot_table,
211 args->csa_slotid, args->csa_sequenceid);
212 if (status)
213 goto out_putclient;
214
215 memcpy(&res->csr_sessionid, &args->csa_sessionid,
216 sizeof(res->csr_sessionid));
217 res->csr_sequenceid = args->csa_sequenceid;
218 res->csr_slotid = args->csa_slotid;
219 res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
220 res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
221
222out_putclient:
223 nfs_put_client(clp);
224out:
225 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
226 res->csr_status = status;
227 return res->csr_status;
228}
229
230#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index dd0ef34b5845..e5a2dac5f715 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -20,6 +20,11 @@
20 2 + 2 + 3 + 3) 20 2 + 2 + 3 + 3)
21#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) 21#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
22 22
23#if defined(CONFIG_NFS_V4_1)
24#define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
25 4 + 1 + 3)
26#endif /* CONFIG_NFS_V4_1 */
27
23#define NFSDBG_FACILITY NFSDBG_CALLBACK 28#define NFSDBG_FACILITY NFSDBG_CALLBACK
24 29
25typedef __be32 (*callback_process_op_t)(void *, void *); 30typedef __be32 (*callback_process_op_t)(void *, void *);
@@ -132,7 +137,6 @@ static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
132static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr) 137static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
133{ 138{
134 __be32 *p; 139 __be32 *p;
135 unsigned int minor_version;
136 __be32 status; 140 __be32 status;
137 141
138 status = decode_string(xdr, &hdr->taglen, &hdr->tag); 142 status = decode_string(xdr, &hdr->taglen, &hdr->tag);
@@ -147,15 +151,19 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound
147 p = read_buf(xdr, 12); 151 p = read_buf(xdr, 12);
148 if (unlikely(p == NULL)) 152 if (unlikely(p == NULL))
149 return htonl(NFS4ERR_RESOURCE); 153 return htonl(NFS4ERR_RESOURCE);
150 minor_version = ntohl(*p++); 154 hdr->minorversion = ntohl(*p++);
151 /* Check minor version is zero. */ 155 /* Check minor version is zero or one. */
152 if (minor_version != 0) { 156 if (hdr->minorversion <= 1) {
153 printk(KERN_WARNING "%s: NFSv4 server callback with illegal minor version %u!\n", 157 p++; /* skip callback_ident */
154 __func__, minor_version); 158 } else {
159 printk(KERN_WARNING "%s: NFSv4 server callback with "
160 "illegal minor version %u!\n",
161 __func__, hdr->minorversion);
155 return htonl(NFS4ERR_MINOR_VERS_MISMATCH); 162 return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
156 } 163 }
157 hdr->callback_ident = ntohl(*p++);
158 hdr->nops = ntohl(*p); 164 hdr->nops = ntohl(*p);
165 dprintk("%s: minorversion %d nops %d\n", __func__,
166 hdr->minorversion, hdr->nops);
159 return 0; 167 return 0;
160} 168}
161 169
@@ -204,6 +212,122 @@ out:
204 return status; 212 return status;
205} 213}
206 214
215#if defined(CONFIG_NFS_V4_1)
216
217static unsigned decode_sessionid(struct xdr_stream *xdr,
218 struct nfs4_sessionid *sid)
219{
220 uint32_t *p;
221 int len = NFS4_MAX_SESSIONID_LEN;
222
223 p = read_buf(xdr, len);
224 if (unlikely(p == NULL))
225 return htonl(NFS4ERR_RESOURCE);;
226
227 memcpy(sid->data, p, len);
228 return 0;
229}
230
231static unsigned decode_rc_list(struct xdr_stream *xdr,
232 struct referring_call_list *rc_list)
233{
234 uint32_t *p;
235 int i;
236 unsigned status;
237
238 status = decode_sessionid(xdr, &rc_list->rcl_sessionid);
239 if (status)
240 goto out;
241
242 status = htonl(NFS4ERR_RESOURCE);
243 p = read_buf(xdr, sizeof(uint32_t));
244 if (unlikely(p == NULL))
245 goto out;
246
247 rc_list->rcl_nrefcalls = ntohl(*p++);
248 if (rc_list->rcl_nrefcalls) {
249 p = read_buf(xdr,
250 rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
251 if (unlikely(p == NULL))
252 goto out;
253 rc_list->rcl_refcalls = kmalloc(rc_list->rcl_nrefcalls *
254 sizeof(*rc_list->rcl_refcalls),
255 GFP_KERNEL);
256 if (unlikely(rc_list->rcl_refcalls == NULL))
257 goto out;
258 for (i = 0; i < rc_list->rcl_nrefcalls; i++) {
259 rc_list->rcl_refcalls[i].rc_sequenceid = ntohl(*p++);
260 rc_list->rcl_refcalls[i].rc_slotid = ntohl(*p++);
261 }
262 }
263 status = 0;
264
265out:
266 return status;
267}
268
269static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp,
270 struct xdr_stream *xdr,
271 struct cb_sequenceargs *args)
272{
273 uint32_t *p;
274 int i;
275 unsigned status;
276
277 status = decode_sessionid(xdr, &args->csa_sessionid);
278 if (status)
279 goto out;
280
281 status = htonl(NFS4ERR_RESOURCE);
282 p = read_buf(xdr, 5 * sizeof(uint32_t));
283 if (unlikely(p == NULL))
284 goto out;
285
286 args->csa_addr = svc_addr(rqstp);
287 args->csa_sequenceid = ntohl(*p++);
288 args->csa_slotid = ntohl(*p++);
289 args->csa_highestslotid = ntohl(*p++);
290 args->csa_cachethis = ntohl(*p++);
291 args->csa_nrclists = ntohl(*p++);
292 args->csa_rclists = NULL;
293 if (args->csa_nrclists) {
294 args->csa_rclists = kmalloc(args->csa_nrclists *
295 sizeof(*args->csa_rclists),
296 GFP_KERNEL);
297 if (unlikely(args->csa_rclists == NULL))
298 goto out;
299
300 for (i = 0; i < args->csa_nrclists; i++) {
301 status = decode_rc_list(xdr, &args->csa_rclists[i]);
302 if (status)
303 goto out_free;
304 }
305 }
306 status = 0;
307
308 dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
309 "highestslotid %u cachethis %d nrclists %u\n",
310 __func__,
311 ((u32 *)&args->csa_sessionid)[0],
312 ((u32 *)&args->csa_sessionid)[1],
313 ((u32 *)&args->csa_sessionid)[2],
314 ((u32 *)&args->csa_sessionid)[3],
315 args->csa_sequenceid, args->csa_slotid,
316 args->csa_highestslotid, args->csa_cachethis,
317 args->csa_nrclists);
318out:
319 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
320 return status;
321
322out_free:
323 for (i = 0; i < args->csa_nrclists; i++)
324 kfree(args->csa_rclists[i].rcl_refcalls);
325 kfree(args->csa_rclists);
326 goto out;
327}
328
329#endif /* CONFIG_NFS_V4_1 */
330
207static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) 331static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
208{ 332{
209 __be32 *p; 333 __be32 *p;
@@ -353,31 +477,134 @@ out:
353 return status; 477 return status;
354} 478}
355 479
356static __be32 process_op(struct svc_rqst *rqstp, 480#if defined(CONFIG_NFS_V4_1)
481
482static unsigned encode_sessionid(struct xdr_stream *xdr,
483 const struct nfs4_sessionid *sid)
484{
485 uint32_t *p;
486 int len = NFS4_MAX_SESSIONID_LEN;
487
488 p = xdr_reserve_space(xdr, len);
489 if (unlikely(p == NULL))
490 return htonl(NFS4ERR_RESOURCE);
491
492 memcpy(p, sid, len);
493 return 0;
494}
495
496static unsigned encode_cb_sequence_res(struct svc_rqst *rqstp,
497 struct xdr_stream *xdr,
498 const struct cb_sequenceres *res)
499{
500 uint32_t *p;
501 unsigned status = res->csr_status;
502
503 if (unlikely(status != 0))
504 goto out;
505
506 encode_sessionid(xdr, &res->csr_sessionid);
507
508 p = xdr_reserve_space(xdr, 4 * sizeof(uint32_t));
509 if (unlikely(p == NULL))
510 return htonl(NFS4ERR_RESOURCE);
511
512 *p++ = htonl(res->csr_sequenceid);
513 *p++ = htonl(res->csr_slotid);
514 *p++ = htonl(res->csr_highestslotid);
515 *p++ = htonl(res->csr_target_highestslotid);
516out:
517 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
518 return status;
519}
520
521static __be32
522preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
523{
524 if (op_nr == OP_CB_SEQUENCE) {
525 if (nop != 0)
526 return htonl(NFS4ERR_SEQUENCE_POS);
527 } else {
528 if (nop == 0)
529 return htonl(NFS4ERR_OP_NOT_IN_SESSION);
530 }
531
532 switch (op_nr) {
533 case OP_CB_GETATTR:
534 case OP_CB_RECALL:
535 case OP_CB_SEQUENCE:
536 *op = &callback_ops[op_nr];
537 break;
538
539 case OP_CB_LAYOUTRECALL:
540 case OP_CB_NOTIFY_DEVICEID:
541 case OP_CB_NOTIFY:
542 case OP_CB_PUSH_DELEG:
543 case OP_CB_RECALL_ANY:
544 case OP_CB_RECALLABLE_OBJ_AVAIL:
545 case OP_CB_RECALL_SLOT:
546 case OP_CB_WANTS_CANCELLED:
547 case OP_CB_NOTIFY_LOCK:
548 return htonl(NFS4ERR_NOTSUPP);
549
550 default:
551 return htonl(NFS4ERR_OP_ILLEGAL);
552 }
553
554 return htonl(NFS_OK);
555}
556
557#else /* CONFIG_NFS_V4_1 */
558
559static __be32
560preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
561{
562 return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
563}
564
565#endif /* CONFIG_NFS_V4_1 */
566
567static __be32
568preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op)
569{
570 switch (op_nr) {
571 case OP_CB_GETATTR:
572 case OP_CB_RECALL:
573 *op = &callback_ops[op_nr];
574 break;
575 default:
576 return htonl(NFS4ERR_OP_ILLEGAL);
577 }
578
579 return htonl(NFS_OK);
580}
581
582static __be32 process_op(uint32_t minorversion, int nop,
583 struct svc_rqst *rqstp,
357 struct xdr_stream *xdr_in, void *argp, 584 struct xdr_stream *xdr_in, void *argp,
358 struct xdr_stream *xdr_out, void *resp) 585 struct xdr_stream *xdr_out, void *resp)
359{ 586{
360 struct callback_op *op = &callback_ops[0]; 587 struct callback_op *op = &callback_ops[0];
361 unsigned int op_nr = OP_CB_ILLEGAL; 588 unsigned int op_nr = OP_CB_ILLEGAL;
362 __be32 status = 0; 589 __be32 status;
363 long maxlen; 590 long maxlen;
364 __be32 res; 591 __be32 res;
365 592
366 dprintk("%s: start\n", __func__); 593 dprintk("%s: start\n", __func__);
367 status = decode_op_hdr(xdr_in, &op_nr); 594 status = decode_op_hdr(xdr_in, &op_nr);
368 if (likely(status == 0)) { 595 if (unlikely(status)) {
369 switch (op_nr) { 596 status = htonl(NFS4ERR_OP_ILLEGAL);
370 case OP_CB_GETATTR: 597 goto out;
371 case OP_CB_RECALL:
372 op = &callback_ops[op_nr];
373 break;
374 default:
375 op_nr = OP_CB_ILLEGAL;
376 op = &callback_ops[0];
377 status = htonl(NFS4ERR_OP_ILLEGAL);
378 }
379 } 598 }
380 599
600 dprintk("%s: minorversion=%d nop=%d op_nr=%u\n",
601 __func__, minorversion, nop, op_nr);
602
603 status = minorversion ? preprocess_nfs41_op(nop, op_nr, &op) :
604 preprocess_nfs4_op(op_nr, &op);
605 if (status == htonl(NFS4ERR_OP_ILLEGAL))
606 op_nr = OP_CB_ILLEGAL;
607out:
381 maxlen = xdr_out->end - xdr_out->p; 608 maxlen = xdr_out->end - xdr_out->p;
382 if (maxlen > 0 && maxlen < PAGE_SIZE) { 609 if (maxlen > 0 && maxlen < PAGE_SIZE) {
383 if (likely(status == 0 && op->decode_args != NULL)) 610 if (likely(status == 0 && op->decode_args != NULL))
@@ -425,7 +652,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
425 return rpc_system_err; 652 return rpc_system_err;
426 653
427 while (status == 0 && nops != hdr_arg.nops) { 654 while (status == 0 && nops != hdr_arg.nops) {
428 status = process_op(rqstp, &xdr_in, argp, &xdr_out, resp); 655 status = process_op(hdr_arg.minorversion, nops,
656 rqstp, &xdr_in, argp, &xdr_out, resp);
429 nops++; 657 nops++;
430 } 658 }
431 659
@@ -452,7 +680,15 @@ static struct callback_op callback_ops[] = {
452 .process_op = (callback_process_op_t)nfs4_callback_recall, 680 .process_op = (callback_process_op_t)nfs4_callback_recall,
453 .decode_args = (callback_decode_arg_t)decode_recall_args, 681 .decode_args = (callback_decode_arg_t)decode_recall_args,
454 .res_maxsize = CB_OP_RECALL_RES_MAXSZ, 682 .res_maxsize = CB_OP_RECALL_RES_MAXSZ,
455 } 683 },
684#if defined(CONFIG_NFS_V4_1)
685 [OP_CB_SEQUENCE] = {
686 .process_op = (callback_process_op_t)nfs4_callback_sequence,
687 .decode_args = (callback_decode_arg_t)decode_cb_sequence_args,
688 .encode_res = (callback_encode_res_t)encode_cb_sequence_res,
689 .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ,
690 },
691#endif /* CONFIG_NFS_V4_1 */
456}; 692};
457 693
458/* 694/*
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 75c9cd2aa119..4f75ec593be8 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -37,6 +37,7 @@
37#include <linux/in6.h> 37#include <linux/in6.h>
38#include <net/ipv6.h> 38#include <net/ipv6.h>
39#include <linux/nfs_xdr.h> 39#include <linux/nfs_xdr.h>
40#include <linux/sunrpc/bc_xprt.h>
40 41
41#include <asm/system.h> 42#include <asm/system.h>
42 43
@@ -102,6 +103,7 @@ struct nfs_client_initdata {
102 size_t addrlen; 103 size_t addrlen;
103 const struct nfs_rpc_ops *rpc_ops; 104 const struct nfs_rpc_ops *rpc_ops;
104 int proto; 105 int proto;
106 u32 minorversion;
105}; 107};
106 108
107/* 109/*
@@ -120,12 +122,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
120 122
121 clp->rpc_ops = cl_init->rpc_ops; 123 clp->rpc_ops = cl_init->rpc_ops;
122 124
123 if (cl_init->rpc_ops->version == 4) {
124 if (nfs_callback_up() < 0)
125 goto error_2;
126 __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
127 }
128
129 atomic_set(&clp->cl_count, 1); 125 atomic_set(&clp->cl_count, 1);
130 clp->cl_cons_state = NFS_CS_INITING; 126 clp->cl_cons_state = NFS_CS_INITING;
131 127
@@ -135,7 +131,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
135 if (cl_init->hostname) { 131 if (cl_init->hostname) {
136 clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL); 132 clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
137 if (!clp->cl_hostname) 133 if (!clp->cl_hostname)
138 goto error_3; 134 goto error_cleanup;
139 } 135 }
140 136
141 INIT_LIST_HEAD(&clp->cl_superblocks); 137 INIT_LIST_HEAD(&clp->cl_superblocks);
@@ -150,6 +146,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
150 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); 146 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
151 clp->cl_boot_time = CURRENT_TIME; 147 clp->cl_boot_time = CURRENT_TIME;
152 clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; 148 clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
149 clp->cl_minorversion = cl_init->minorversion;
153#endif 150#endif
154 cred = rpc_lookup_machine_cred(); 151 cred = rpc_lookup_machine_cred();
155 if (!IS_ERR(cred)) 152 if (!IS_ERR(cred))
@@ -159,10 +156,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
159 156
160 return clp; 157 return clp;
161 158
162error_3: 159error_cleanup:
163 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
164 nfs_callback_down();
165error_2:
166 kfree(clp); 160 kfree(clp);
167error_0: 161error_0:
168 return NULL; 162 return NULL;
@@ -182,12 +176,42 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
182} 176}
183 177
184/* 178/*
179 * Destroy the NFS4 callback service
180 */
181static void nfs4_destroy_callback(struct nfs_client *clp)
182{
183#ifdef CONFIG_NFS_V4
184 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
185 nfs_callback_down(clp->cl_minorversion);
186#endif /* CONFIG_NFS_V4 */
187}
188
189/*
190 * Clears/puts all minor version specific parts from an nfs_client struct
191 * reverting it to minorversion 0.
192 */
193static void nfs4_clear_client_minor_version(struct nfs_client *clp)
194{
195#ifdef CONFIG_NFS_V4_1
196 if (nfs4_has_session(clp)) {
197 nfs4_destroy_session(clp->cl_session);
198 clp->cl_session = NULL;
199 }
200
201 clp->cl_call_sync = _nfs4_call_sync;
202#endif /* CONFIG_NFS_V4_1 */
203
204 nfs4_destroy_callback(clp);
205}
206
207/*
185 * Destroy a shared client record 208 * Destroy a shared client record
186 */ 209 */
187static void nfs_free_client(struct nfs_client *clp) 210static void nfs_free_client(struct nfs_client *clp)
188{ 211{
189 dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); 212 dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
190 213
214 nfs4_clear_client_minor_version(clp);
191 nfs4_shutdown_client(clp); 215 nfs4_shutdown_client(clp);
192 216
193 nfs_fscache_release_client_cookie(clp); 217 nfs_fscache_release_client_cookie(clp);
@@ -196,9 +220,6 @@ static void nfs_free_client(struct nfs_client *clp)
196 if (!IS_ERR(clp->cl_rpcclient)) 220 if (!IS_ERR(clp->cl_rpcclient))
197 rpc_shutdown_client(clp->cl_rpcclient); 221 rpc_shutdown_client(clp->cl_rpcclient);
198 222
199 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
200 nfs_callback_down();
201
202 if (clp->cl_machine_cred != NULL) 223 if (clp->cl_machine_cred != NULL)
203 put_rpccred(clp->cl_machine_cred); 224 put_rpccred(clp->cl_machine_cred);
204 225
@@ -347,7 +368,8 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
347 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; 368 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
348 369
349 /* Don't match clients that failed to initialise properly */ 370 /* Don't match clients that failed to initialise properly */
350 if (clp->cl_cons_state != NFS_CS_READY) 371 if (!(clp->cl_cons_state == NFS_CS_READY ||
372 clp->cl_cons_state == NFS_CS_SESSION_INITING))
351 continue; 373 continue;
352 374
353 /* Different NFS versions cannot share the same nfs_client */ 375 /* Different NFS versions cannot share the same nfs_client */
@@ -420,7 +442,9 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
420 442
421 if (clp->cl_proto != data->proto) 443 if (clp->cl_proto != data->proto)
422 continue; 444 continue;
423 445 /* Match nfsv4 minorversion */
446 if (clp->cl_minorversion != data->minorversion)
447 continue;
424 /* Match the full socket address */ 448 /* Match the full socket address */
425 if (!nfs_sockaddr_cmp(sap, clap)) 449 if (!nfs_sockaddr_cmp(sap, clap))
426 continue; 450 continue;
@@ -478,7 +502,7 @@ found_client:
478 nfs_free_client(new); 502 nfs_free_client(new);
479 503
480 error = wait_event_killable(nfs_client_active_wq, 504 error = wait_event_killable(nfs_client_active_wq,
481 clp->cl_cons_state != NFS_CS_INITING); 505 clp->cl_cons_state < NFS_CS_INITING);
482 if (error < 0) { 506 if (error < 0) {
483 nfs_put_client(clp); 507 nfs_put_client(clp);
484 return ERR_PTR(-ERESTARTSYS); 508 return ERR_PTR(-ERESTARTSYS);
@@ -499,13 +523,29 @@ found_client:
499/* 523/*
500 * Mark a server as ready or failed 524 * Mark a server as ready or failed
501 */ 525 */
502static void nfs_mark_client_ready(struct nfs_client *clp, int state) 526void nfs_mark_client_ready(struct nfs_client *clp, int state)
503{ 527{
504 clp->cl_cons_state = state; 528 clp->cl_cons_state = state;
505 wake_up_all(&nfs_client_active_wq); 529 wake_up_all(&nfs_client_active_wq);
506} 530}
507 531
508/* 532/*
533 * With sessions, the client is not marked ready until after a
534 * successful EXCHANGE_ID and CREATE_SESSION.
535 *
536 * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate
537 * other versions of NFS can be tried.
538 */
539int nfs4_check_client_ready(struct nfs_client *clp)
540{
541 if (!nfs4_has_session(clp))
542 return 0;
543 if (clp->cl_cons_state < NFS_CS_READY)
544 return -EPROTONOSUPPORT;
545 return 0;
546}
547
548/*
509 * Initialise the timeout values for a connection 549 * Initialise the timeout values for a connection
510 */ 550 */
511static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, 551static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
@@ -1050,6 +1090,61 @@ error:
1050 1090
1051#ifdef CONFIG_NFS_V4 1091#ifdef CONFIG_NFS_V4
1052/* 1092/*
1093 * Initialize the NFS4 callback service
1094 */
1095static int nfs4_init_callback(struct nfs_client *clp)
1096{
1097 int error;
1098
1099 if (clp->rpc_ops->version == 4) {
1100 if (nfs4_has_session(clp)) {
1101 error = xprt_setup_backchannel(
1102 clp->cl_rpcclient->cl_xprt,
1103 NFS41_BC_MIN_CALLBACKS);
1104 if (error < 0)
1105 return error;
1106 }
1107
1108 error = nfs_callback_up(clp->cl_minorversion,
1109 clp->cl_rpcclient->cl_xprt);
1110 if (error < 0) {
1111 dprintk("%s: failed to start callback. Error = %d\n",
1112 __func__, error);
1113 return error;
1114 }
1115 __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
1116 }
1117 return 0;
1118}
1119
1120/*
1121 * Initialize the minor version specific parts of an NFS4 client record
1122 */
1123static int nfs4_init_client_minor_version(struct nfs_client *clp)
1124{
1125 clp->cl_call_sync = _nfs4_call_sync;
1126
1127#if defined(CONFIG_NFS_V4_1)
1128 if (clp->cl_minorversion) {
1129 struct nfs4_session *session = NULL;
1130 /*
1131 * Create the session and mark it expired.
1132 * When a SEQUENCE operation encounters the expired session
1133 * it will do session recovery to initialize it.
1134 */
1135 session = nfs4_alloc_session(clp);
1136 if (!session)
1137 return -ENOMEM;
1138
1139 clp->cl_session = session;
1140 clp->cl_call_sync = _nfs4_call_sync_session;
1141 }
1142#endif /* CONFIG_NFS_V4_1 */
1143
1144 return nfs4_init_callback(clp);
1145}
1146
1147/*
1053 * Initialise an NFS4 client record 1148 * Initialise an NFS4 client record
1054 */ 1149 */
1055static int nfs4_init_client(struct nfs_client *clp, 1150static int nfs4_init_client(struct nfs_client *clp,
@@ -1083,7 +1178,12 @@ static int nfs4_init_client(struct nfs_client *clp,
1083 } 1178 }
1084 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); 1179 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
1085 1180
1086 nfs_mark_client_ready(clp, NFS_CS_READY); 1181 error = nfs4_init_client_minor_version(clp);
1182 if (error < 0)
1183 goto error;
1184
1185 if (!nfs4_has_session(clp))
1186 nfs_mark_client_ready(clp, NFS_CS_READY);
1087 return 0; 1187 return 0;
1088 1188
1089error: 1189error:
@@ -1101,7 +1201,8 @@ static int nfs4_set_client(struct nfs_server *server,
1101 const size_t addrlen, 1201 const size_t addrlen,
1102 const char *ip_addr, 1202 const char *ip_addr,
1103 rpc_authflavor_t authflavour, 1203 rpc_authflavor_t authflavour,
1104 int proto, const struct rpc_timeout *timeparms) 1204 int proto, const struct rpc_timeout *timeparms,
1205 u32 minorversion)
1105{ 1206{
1106 struct nfs_client_initdata cl_init = { 1207 struct nfs_client_initdata cl_init = {
1107 .hostname = hostname, 1208 .hostname = hostname,
@@ -1109,6 +1210,7 @@ static int nfs4_set_client(struct nfs_server *server,
1109 .addrlen = addrlen, 1210 .addrlen = addrlen,
1110 .rpc_ops = &nfs_v4_clientops, 1211 .rpc_ops = &nfs_v4_clientops,
1111 .proto = proto, 1212 .proto = proto,
1213 .minorversion = minorversion,
1112 }; 1214 };
1113 struct nfs_client *clp; 1215 struct nfs_client *clp;
1114 int error; 1216 int error;
@@ -1138,6 +1240,36 @@ error:
1138} 1240}
1139 1241
1140/* 1242/*
1243 * Initialize a session.
1244 * Note: save the mount rsize and wsize for create_server negotiation.
1245 */
1246static void nfs4_init_session(struct nfs_client *clp,
1247 unsigned int wsize, unsigned int rsize)
1248{
1249#if defined(CONFIG_NFS_V4_1)
1250 if (nfs4_has_session(clp)) {
1251 clp->cl_session->fc_attrs.max_rqst_sz = wsize;
1252 clp->cl_session->fc_attrs.max_resp_sz = rsize;
1253 }
1254#endif /* CONFIG_NFS_V4_1 */
1255}
1256
1257/*
1258 * Session has been established, and the client marked ready.
1259 * Set the mount rsize and wsize with negotiated fore channel
1260 * attributes which will be bound checked in nfs_server_set_fsinfo.
1261 */
1262static void nfs4_session_set_rwsize(struct nfs_server *server)
1263{
1264#ifdef CONFIG_NFS_V4_1
1265 if (!nfs4_has_session(server->nfs_client))
1266 return;
1267 server->rsize = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
1268 server->wsize = server->nfs_client->cl_session->fc_attrs.max_rqst_sz;
1269#endif /* CONFIG_NFS_V4_1 */
1270}
1271
1272/*
1141 * Create a version 4 volume record 1273 * Create a version 4 volume record
1142 */ 1274 */
1143static int nfs4_init_server(struct nfs_server *server, 1275static int nfs4_init_server(struct nfs_server *server,
@@ -1164,7 +1296,8 @@ static int nfs4_init_server(struct nfs_server *server,
1164 data->client_address, 1296 data->client_address,
1165 data->auth_flavors[0], 1297 data->auth_flavors[0],
1166 data->nfs_server.protocol, 1298 data->nfs_server.protocol,
1167 &timeparms); 1299 &timeparms,
1300 data->minorversion);
1168 if (error < 0) 1301 if (error < 0)
1169 goto error; 1302 goto error;
1170 1303
@@ -1214,6 +1347,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
1214 BUG_ON(!server->nfs_client->rpc_ops); 1347 BUG_ON(!server->nfs_client->rpc_ops);
1215 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); 1348 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
1216 1349
1350 nfs4_init_session(server->nfs_client, server->wsize, server->rsize);
1351
1217 /* Probe the root fh to retrieve its FSID */ 1352 /* Probe the root fh to retrieve its FSID */
1218 error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); 1353 error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
1219 if (error < 0) 1354 if (error < 0)
@@ -1224,6 +1359,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
1224 (unsigned long long) server->fsid.minor); 1359 (unsigned long long) server->fsid.minor);
1225 dprintk("Mount FH: %d\n", mntfh->size); 1360 dprintk("Mount FH: %d\n", mntfh->size);
1226 1361
1362 nfs4_session_set_rwsize(server);
1363
1227 error = nfs_probe_fsinfo(server, mntfh, &fattr); 1364 error = nfs_probe_fsinfo(server, mntfh, &fattr);
1228 if (error < 0) 1365 if (error < 0)
1229 goto error; 1366 goto error;
@@ -1282,7 +1419,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
1282 parent_client->cl_ipaddr, 1419 parent_client->cl_ipaddr,
1283 data->authflavor, 1420 data->authflavor,
1284 parent_server->client->cl_xprt->prot, 1421 parent_server->client->cl_xprt->prot,
1285 parent_server->client->cl_timeout); 1422 parent_server->client->cl_timeout,
1423 parent_client->cl_minorversion);
1286 if (error < 0) 1424 if (error < 0)
1287 goto error; 1425 goto error;
1288 1426
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 08f6b040d289..489fc01a3204 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -259,6 +259,9 @@ static void nfs_direct_read_release(void *calldata)
259} 259}
260 260
261static const struct rpc_call_ops nfs_read_direct_ops = { 261static const struct rpc_call_ops nfs_read_direct_ops = {
262#if defined(CONFIG_NFS_V4_1)
263 .rpc_call_prepare = nfs_read_prepare,
264#endif /* CONFIG_NFS_V4_1 */
262 .rpc_call_done = nfs_direct_read_result, 265 .rpc_call_done = nfs_direct_read_result,
263 .rpc_release = nfs_direct_read_release, 266 .rpc_release = nfs_direct_read_release,
264}; 267};
@@ -535,6 +538,9 @@ static void nfs_direct_commit_release(void *calldata)
535} 538}
536 539
537static const struct rpc_call_ops nfs_commit_direct_ops = { 540static const struct rpc_call_ops nfs_commit_direct_ops = {
541#if defined(CONFIG_NFS_V4_1)
542 .rpc_call_prepare = nfs_write_prepare,
543#endif /* CONFIG_NFS_V4_1 */
538 .rpc_call_done = nfs_direct_commit_result, 544 .rpc_call_done = nfs_direct_commit_result,
539 .rpc_release = nfs_direct_commit_release, 545 .rpc_release = nfs_direct_commit_release,
540}; 546};
@@ -673,6 +679,9 @@ out_unlock:
673} 679}
674 680
675static const struct rpc_call_ops nfs_write_direct_ops = { 681static const struct rpc_call_ops nfs_write_direct_ops = {
682#if defined(CONFIG_NFS_V4_1)
683 .rpc_call_prepare = nfs_write_prepare,
684#endif /* CONFIG_NFS_V4_1 */
676 .rpc_call_done = nfs_direct_write_result, 685 .rpc_call_done = nfs_direct_write_result,
677 .rpc_release = nfs_direct_write_release, 686 .rpc_release = nfs_direct_write_release,
678}; 687};
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index e4d6a8348adf..acee3274d275 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -2,6 +2,7 @@
2 * NFS internal definitions 2 * NFS internal definitions
3 */ 3 */
4 4
5#include "nfs4_fs.h"
5#include <linux/mount.h> 6#include <linux/mount.h>
6#include <linux/security.h> 7#include <linux/security.h>
7 8
@@ -17,6 +18,18 @@ struct nfs_string;
17 */ 18 */
18#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) 19#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1)
19 20
21/*
22 * Determine if sessions are in use.
23 */
24static inline int nfs4_has_session(const struct nfs_client *clp)
25{
26#ifdef CONFIG_NFS_V4_1
27 if (clp->cl_session)
28 return 1;
29#endif /* CONFIG_NFS_V4_1 */
30 return 0;
31}
32
20struct nfs_clone_mount { 33struct nfs_clone_mount {
21 const struct super_block *sb; 34 const struct super_block *sb;
22 const struct dentry *dentry; 35 const struct dentry *dentry;
@@ -44,6 +57,7 @@ struct nfs_parsed_mount_data {
44 unsigned int auth_flavor_len; 57 unsigned int auth_flavor_len;
45 rpc_authflavor_t auth_flavors[1]; 58 rpc_authflavor_t auth_flavors[1];
46 char *client_address; 59 char *client_address;
60 unsigned int minorversion;
47 char *fscache_uniq; 61 char *fscache_uniq;
48 62
49 struct { 63 struct {
@@ -99,6 +113,8 @@ extern void nfs_free_server(struct nfs_server *server);
99extern struct nfs_server *nfs_clone_server(struct nfs_server *, 113extern struct nfs_server *nfs_clone_server(struct nfs_server *,
100 struct nfs_fh *, 114 struct nfs_fh *,
101 struct nfs_fattr *); 115 struct nfs_fattr *);
116extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
117extern int nfs4_check_client_ready(struct nfs_client *clp);
102#ifdef CONFIG_PROC_FS 118#ifdef CONFIG_PROC_FS
103extern int __init nfs_fs_proc_init(void); 119extern int __init nfs_fs_proc_init(void);
104extern void nfs_fs_proc_exit(void); 120extern void nfs_fs_proc_exit(void);
@@ -146,6 +162,20 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
146extern struct rpc_procinfo nfs3_procedures[]; 162extern struct rpc_procinfo nfs3_procedures[];
147extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int); 163extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
148 164
165/* nfs4proc.c */
166static inline void nfs4_restart_rpc(struct rpc_task *task,
167 const struct nfs_client *clp)
168{
169#ifdef CONFIG_NFS_V4_1
170 if (nfs4_has_session(clp) &&
171 test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) {
172 rpc_restart_call_prepare(task);
173 return;
174 }
175#endif /* CONFIG_NFS_V4_1 */
176 rpc_restart_call(task);
177}
178
149/* nfs4xdr.c */ 179/* nfs4xdr.c */
150#ifdef CONFIG_NFS_V4 180#ifdef CONFIG_NFS_V4
151extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); 181extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
@@ -205,6 +235,38 @@ extern int nfs4_path_walk(struct nfs_server *server,
205 const char *path); 235 const char *path);
206#endif 236#endif
207 237
238/* read.c */
239extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
240
241/* write.c */
242extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
243
244/* nfs4proc.c */
245extern int _nfs4_call_sync(struct nfs_server *server,
246 struct rpc_message *msg,
247 struct nfs4_sequence_args *args,
248 struct nfs4_sequence_res *res,
249 int cache_reply);
250extern int _nfs4_call_sync_session(struct nfs_server *server,
251 struct rpc_message *msg,
252 struct nfs4_sequence_args *args,
253 struct nfs4_sequence_res *res,
254 int cache_reply);
255
256#ifdef CONFIG_NFS_V4_1
257extern void nfs41_sequence_free_slot(const struct nfs_client *,
258 struct nfs4_sequence_res *res);
259#endif /* CONFIG_NFS_V4_1 */
260
261static inline void nfs4_sequence_free_slot(const struct nfs_client *clp,
262 struct nfs4_sequence_res *res)
263{
264#ifdef CONFIG_NFS_V4_1
265 if (nfs4_has_session(clp))
266 nfs41_sequence_free_slot(clp, res);
267#endif /* CONFIG_NFS_V4_1 */
268}
269
208/* 270/*
209 * Determine the device name as a string 271 * Determine the device name as a string
210 */ 272 */
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 84345deab26f..61bc3a32e1e2 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -44,6 +44,7 @@ enum nfs4_client_state {
44 NFS4CLNT_RECLAIM_REBOOT, 44 NFS4CLNT_RECLAIM_REBOOT,
45 NFS4CLNT_RECLAIM_NOGRACE, 45 NFS4CLNT_RECLAIM_NOGRACE,
46 NFS4CLNT_DELEGRETURN, 46 NFS4CLNT_DELEGRETURN,
47 NFS4CLNT_SESSION_SETUP,
47}; 48};
48 49
49/* 50/*
@@ -177,6 +178,14 @@ struct nfs4_state_recovery_ops {
177 int state_flag_bit; 178 int state_flag_bit;
178 int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *); 179 int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
179 int (*recover_lock)(struct nfs4_state *, struct file_lock *); 180 int (*recover_lock)(struct nfs4_state *, struct file_lock *);
181 int (*establish_clid)(struct nfs_client *, struct rpc_cred *);
182 struct rpc_cred * (*get_clid_cred)(struct nfs_client *);
183};
184
185struct nfs4_state_maintenance_ops {
186 int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *);
187 struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *);
188 int (*renew_lease)(struct nfs_client *, struct rpc_cred *);
180}; 189};
181 190
182extern const struct dentry_operations nfs4_dentry_operations; 191extern const struct dentry_operations nfs4_dentry_operations;
@@ -193,6 +202,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struc
193extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); 202extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
194extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); 203extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
195extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); 204extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
205extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
196extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait); 206extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait);
197extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); 207extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
198extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); 208extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
@@ -200,8 +210,26 @@ extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fh
200extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, 210extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
201 struct nfs4_fs_locations *fs_locations, struct page *page); 211 struct nfs4_fs_locations *fs_locations, struct page *page);
202 212
203extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; 213extern struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[];
204extern struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops; 214extern struct nfs4_state_recovery_ops *nfs4_nograce_recovery_ops[];
215#if defined(CONFIG_NFS_V4_1)
216extern int nfs4_setup_sequence(struct nfs_client *clp,
217 struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
218 int cache_reply, struct rpc_task *task);
219extern void nfs4_destroy_session(struct nfs4_session *session);
220extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
221extern int nfs4_proc_create_session(struct nfs_client *, int reset);
222extern int nfs4_proc_destroy_session(struct nfs4_session *);
223#else /* CONFIG_NFS_v4_1 */
224static inline int nfs4_setup_sequence(struct nfs_client *clp,
225 struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
226 int cache_reply, struct rpc_task *task)
227{
228 return 0;
229}
230#endif /* CONFIG_NFS_V4_1 */
231
232extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[];
205 233
206extern const u32 nfs4_fattr_bitmap[2]; 234extern const u32 nfs4_fattr_bitmap[2];
207extern const u32 nfs4_statfs_bitmap[2]; 235extern const u32 nfs4_statfs_bitmap[2];
@@ -216,7 +244,12 @@ extern void nfs4_kill_renewd(struct nfs_client *);
216extern void nfs4_renew_state(struct work_struct *); 244extern void nfs4_renew_state(struct work_struct *);
217 245
218/* nfs4state.c */ 246/* nfs4state.c */
247struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
219struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp); 248struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
249#if defined(CONFIG_NFS_V4_1)
250struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
251struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
252#endif /* CONFIG_NFS_V4_1 */
220 253
221extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); 254extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
222extern void nfs4_put_state_owner(struct nfs4_state_owner *); 255extern void nfs4_put_state_owner(struct nfs4_state_owner *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4674f8092da8..57dabb8a048e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -48,11 +48,14 @@
48#include <linux/smp_lock.h> 48#include <linux/smp_lock.h>
49#include <linux/namei.h> 49#include <linux/namei.h>
50#include <linux/mount.h> 50#include <linux/mount.h>
51#include <linux/module.h>
52#include <linux/sunrpc/bc_xprt.h>
51 53
52#include "nfs4_fs.h" 54#include "nfs4_fs.h"
53#include "delegation.h" 55#include "delegation.h"
54#include "internal.h" 56#include "internal.h"
55#include "iostat.h" 57#include "iostat.h"
58#include "callback.h"
56 59
57#define NFSDBG_FACILITY NFSDBG_PROC 60#define NFSDBG_FACILITY NFSDBG_PROC
58 61
@@ -247,7 +250,25 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
247 ret = nfs4_wait_clnt_recover(clp); 250 ret = nfs4_wait_clnt_recover(clp);
248 if (ret == 0) 251 if (ret == 0)
249 exception->retry = 1; 252 exception->retry = 1;
253#if !defined(CONFIG_NFS_V4_1)
250 break; 254 break;
255#else /* !defined(CONFIG_NFS_V4_1) */
256 if (!nfs4_has_session(server->nfs_client))
257 break;
258 /* FALLTHROUGH */
259 case -NFS4ERR_BADSESSION:
260 case -NFS4ERR_BADSLOT:
261 case -NFS4ERR_BAD_HIGH_SLOT:
262 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
263 case -NFS4ERR_DEADSESSION:
264 case -NFS4ERR_SEQ_FALSE_RETRY:
265 case -NFS4ERR_SEQ_MISORDERED:
266 dprintk("%s ERROR: %d Reset session\n", __func__,
267 errorcode);
268 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
269 exception->retry = 1;
270 /* FALLTHROUGH */
271#endif /* !defined(CONFIG_NFS_V4_1) */
251 case -NFS4ERR_FILE_OPEN: 272 case -NFS4ERR_FILE_OPEN:
252 case -NFS4ERR_GRACE: 273 case -NFS4ERR_GRACE:
253 case -NFS4ERR_DELAY: 274 case -NFS4ERR_DELAY:
@@ -271,6 +292,353 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
271 spin_unlock(&clp->cl_lock); 292 spin_unlock(&clp->cl_lock);
272} 293}
273 294
295#if defined(CONFIG_NFS_V4_1)
296
297/*
298 * nfs4_free_slot - free a slot and efficiently update slot table.
299 *
300 * freeing a slot is trivially done by clearing its respective bit
301 * in the bitmap.
302 * If the freed slotid equals highest_used_slotid we want to update it
303 * so that the server would be able to size down the slot table if needed,
304 * otherwise we know that the highest_used_slotid is still in use.
305 * When updating highest_used_slotid there may be "holes" in the bitmap
306 * so we need to scan down from highest_used_slotid to 0 looking for the now
307 * highest slotid in use.
308 * If none found, highest_used_slotid is set to -1.
309 */
310static void
311nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
312{
313 int slotid = free_slotid;
314
315 spin_lock(&tbl->slot_tbl_lock);
316 /* clear used bit in bitmap */
317 __clear_bit(slotid, tbl->used_slots);
318
319 /* update highest_used_slotid when it is freed */
320 if (slotid == tbl->highest_used_slotid) {
321 slotid = find_last_bit(tbl->used_slots, tbl->max_slots);
322 if (slotid >= 0 && slotid < tbl->max_slots)
323 tbl->highest_used_slotid = slotid;
324 else
325 tbl->highest_used_slotid = -1;
326 }
327 rpc_wake_up_next(&tbl->slot_tbl_waitq);
328 spin_unlock(&tbl->slot_tbl_lock);
329 dprintk("%s: free_slotid %u highest_used_slotid %d\n", __func__,
330 free_slotid, tbl->highest_used_slotid);
331}
332
333void nfs41_sequence_free_slot(const struct nfs_client *clp,
334 struct nfs4_sequence_res *res)
335{
336 struct nfs4_slot_table *tbl;
337
338 if (!nfs4_has_session(clp)) {
339 dprintk("%s: No session\n", __func__);
340 return;
341 }
342 tbl = &clp->cl_session->fc_slot_table;
343 if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) {
344 dprintk("%s: No slot\n", __func__);
345 /* just wake up the next guy waiting since
346 * we may have not consumed a slot after all */
347 rpc_wake_up_next(&tbl->slot_tbl_waitq);
348 return;
349 }
350 nfs4_free_slot(tbl, res->sr_slotid);
351 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
352}
353
354static void nfs41_sequence_done(struct nfs_client *clp,
355 struct nfs4_sequence_res *res,
356 int rpc_status)
357{
358 unsigned long timestamp;
359 struct nfs4_slot_table *tbl;
360 struct nfs4_slot *slot;
361
362 /*
363 * sr_status remains 1 if an RPC level error occurred. The server
364 * may or may not have processed the sequence operation..
365 * Proceed as if the server received and processed the sequence
366 * operation.
367 */
368 if (res->sr_status == 1)
369 res->sr_status = NFS_OK;
370
371 /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
372 if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
373 goto out;
374
375 tbl = &clp->cl_session->fc_slot_table;
376 slot = tbl->slots + res->sr_slotid;
377
378 if (res->sr_status == 0) {
379 /* Update the slot's sequence and clientid lease timer */
380 ++slot->seq_nr;
381 timestamp = res->sr_renewal_time;
382 spin_lock(&clp->cl_lock);
383 if (time_before(clp->cl_last_renewal, timestamp))
384 clp->cl_last_renewal = timestamp;
385 spin_unlock(&clp->cl_lock);
386 return;
387 }
388out:
389 /* The session may be reset by one of the error handlers. */
390 dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
391 nfs41_sequence_free_slot(clp, res);
392}
393
394/*
395 * nfs4_find_slot - efficiently look for a free slot
396 *
397 * nfs4_find_slot looks for an unset bit in the used_slots bitmap.
398 * If found, we mark the slot as used, update the highest_used_slotid,
399 * and respectively set up the sequence operation args.
400 * The slot number is returned if found, or NFS4_MAX_SLOT_TABLE otherwise.
401 *
402 * Note: must be called with under the slot_tbl_lock.
403 */
404static u8
405nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
406{
407 int slotid;
408 u8 ret_id = NFS4_MAX_SLOT_TABLE;
409 BUILD_BUG_ON((u8)NFS4_MAX_SLOT_TABLE != (int)NFS4_MAX_SLOT_TABLE);
410
411 dprintk("--> %s used_slots=%04lx highest_used=%d max_slots=%d\n",
412 __func__, tbl->used_slots[0], tbl->highest_used_slotid,
413 tbl->max_slots);
414 slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots);
415 if (slotid >= tbl->max_slots)
416 goto out;
417 __set_bit(slotid, tbl->used_slots);
418 if (slotid > tbl->highest_used_slotid)
419 tbl->highest_used_slotid = slotid;
420 ret_id = slotid;
421out:
422 dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n",
423 __func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id);
424 return ret_id;
425}
426
427static int nfs4_recover_session(struct nfs4_session *session)
428{
429 struct nfs_client *clp = session->clp;
430 int ret;
431
432 for (;;) {
433 ret = nfs4_wait_clnt_recover(clp);
434 if (ret != 0)
435 return ret;
436 if (!test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
437 break;
438 nfs4_schedule_state_manager(clp);
439 }
440 return 0;
441}
442
443static int nfs41_setup_sequence(struct nfs4_session *session,
444 struct nfs4_sequence_args *args,
445 struct nfs4_sequence_res *res,
446 int cache_reply,
447 struct rpc_task *task)
448{
449 struct nfs4_slot *slot;
450 struct nfs4_slot_table *tbl;
451 int status = 0;
452 u8 slotid;
453
454 dprintk("--> %s\n", __func__);
455 /* slot already allocated? */
456 if (res->sr_slotid != NFS4_MAX_SLOT_TABLE)
457 return 0;
458
459 memset(res, 0, sizeof(*res));
460 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
461 tbl = &session->fc_slot_table;
462
463 spin_lock(&tbl->slot_tbl_lock);
464 if (test_bit(NFS4CLNT_SESSION_SETUP, &session->clp->cl_state)) {
465 if (tbl->highest_used_slotid != -1) {
466 rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
467 spin_unlock(&tbl->slot_tbl_lock);
468 dprintk("<-- %s: Session reset: draining\n", __func__);
469 return -EAGAIN;
470 }
471
472 /* The slot table is empty; start the reset thread */
473 dprintk("%s Session Reset\n", __func__);
474 spin_unlock(&tbl->slot_tbl_lock);
475 status = nfs4_recover_session(session);
476 if (status)
477 return status;
478 spin_lock(&tbl->slot_tbl_lock);
479 }
480
481 slotid = nfs4_find_slot(tbl, task);
482 if (slotid == NFS4_MAX_SLOT_TABLE) {
483 rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
484 spin_unlock(&tbl->slot_tbl_lock);
485 dprintk("<-- %s: no free slots\n", __func__);
486 return -EAGAIN;
487 }
488 spin_unlock(&tbl->slot_tbl_lock);
489
490 slot = tbl->slots + slotid;
491 args->sa_session = session;
492 args->sa_slotid = slotid;
493 args->sa_cache_this = cache_reply;
494
495 dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
496
497 res->sr_session = session;
498 res->sr_slotid = slotid;
499 res->sr_renewal_time = jiffies;
500 /*
501 * sr_status is only set in decode_sequence, and so will remain
502 * set to 1 if an rpc level failure occurs.
503 */
504 res->sr_status = 1;
505 return 0;
506}
507
508int nfs4_setup_sequence(struct nfs_client *clp,
509 struct nfs4_sequence_args *args,
510 struct nfs4_sequence_res *res,
511 int cache_reply,
512 struct rpc_task *task)
513{
514 int ret = 0;
515
516 dprintk("--> %s clp %p session %p sr_slotid %d\n",
517 __func__, clp, clp->cl_session, res->sr_slotid);
518
519 if (!nfs4_has_session(clp))
520 goto out;
521 ret = nfs41_setup_sequence(clp->cl_session, args, res, cache_reply,
522 task);
523 if (ret != -EAGAIN) {
524 /* terminate rpc task */
525 task->tk_status = ret;
526 task->tk_action = NULL;
527 }
528out:
529 dprintk("<-- %s status=%d\n", __func__, ret);
530 return ret;
531}
532
533struct nfs41_call_sync_data {
534 struct nfs_client *clp;
535 struct nfs4_sequence_args *seq_args;
536 struct nfs4_sequence_res *seq_res;
537 int cache_reply;
538};
539
540static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
541{
542 struct nfs41_call_sync_data *data = calldata;
543
544 dprintk("--> %s data->clp->cl_session %p\n", __func__,
545 data->clp->cl_session);
546 if (nfs4_setup_sequence(data->clp, data->seq_args,
547 data->seq_res, data->cache_reply, task))
548 return;
549 rpc_call_start(task);
550}
551
552static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
553{
554 struct nfs41_call_sync_data *data = calldata;
555
556 nfs41_sequence_done(data->clp, data->seq_res, task->tk_status);
557 nfs41_sequence_free_slot(data->clp, data->seq_res);
558}
559
560struct rpc_call_ops nfs41_call_sync_ops = {
561 .rpc_call_prepare = nfs41_call_sync_prepare,
562 .rpc_call_done = nfs41_call_sync_done,
563};
564
565static int nfs4_call_sync_sequence(struct nfs_client *clp,
566 struct rpc_clnt *clnt,
567 struct rpc_message *msg,
568 struct nfs4_sequence_args *args,
569 struct nfs4_sequence_res *res,
570 int cache_reply)
571{
572 int ret;
573 struct rpc_task *task;
574 struct nfs41_call_sync_data data = {
575 .clp = clp,
576 .seq_args = args,
577 .seq_res = res,
578 .cache_reply = cache_reply,
579 };
580 struct rpc_task_setup task_setup = {
581 .rpc_client = clnt,
582 .rpc_message = msg,
583 .callback_ops = &nfs41_call_sync_ops,
584 .callback_data = &data
585 };
586
587 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
588 task = rpc_run_task(&task_setup);
589 if (IS_ERR(task))
590 ret = PTR_ERR(task);
591 else {
592 ret = task->tk_status;
593 rpc_put_task(task);
594 }
595 return ret;
596}
597
598int _nfs4_call_sync_session(struct nfs_server *server,
599 struct rpc_message *msg,
600 struct nfs4_sequence_args *args,
601 struct nfs4_sequence_res *res,
602 int cache_reply)
603{
604 return nfs4_call_sync_sequence(server->nfs_client, server->client,
605 msg, args, res, cache_reply);
606}
607
608#endif /* CONFIG_NFS_V4_1 */
609
610int _nfs4_call_sync(struct nfs_server *server,
611 struct rpc_message *msg,
612 struct nfs4_sequence_args *args,
613 struct nfs4_sequence_res *res,
614 int cache_reply)
615{
616 args->sa_session = res->sr_session = NULL;
617 return rpc_call_sync(server->client, msg, 0);
618}
619
620#define nfs4_call_sync(server, msg, args, res, cache_reply) \
621 (server)->nfs_client->cl_call_sync((server), (msg), &(args)->seq_args, \
622 &(res)->seq_res, (cache_reply))
623
624static void nfs4_sequence_done(const struct nfs_server *server,
625 struct nfs4_sequence_res *res, int rpc_status)
626{
627#ifdef CONFIG_NFS_V4_1
628 if (nfs4_has_session(server->nfs_client))
629 nfs41_sequence_done(server->nfs_client, res, rpc_status);
630#endif /* CONFIG_NFS_V4_1 */
631}
632
633/* no restart, therefore free slot here */
634static void nfs4_sequence_done_free_slot(const struct nfs_server *server,
635 struct nfs4_sequence_res *res,
636 int rpc_status)
637{
638 nfs4_sequence_done(server, res, rpc_status);
639 nfs4_sequence_free_slot(server->nfs_client, res);
640}
641
274static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) 642static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
275{ 643{
276 struct nfs_inode *nfsi = NFS_I(dir); 644 struct nfs_inode *nfsi = NFS_I(dir);
@@ -343,6 +711,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
343 p->o_arg.server = server; 711 p->o_arg.server = server;
344 p->o_arg.bitmask = server->attr_bitmask; 712 p->o_arg.bitmask = server->attr_bitmask;
345 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; 713 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
714 p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
346 if (flags & O_EXCL) { 715 if (flags & O_EXCL) {
347 u32 *s = (u32 *) p->o_arg.u.verifier.data; 716 u32 *s = (u32 *) p->o_arg.u.verifier.data;
348 s[0] = jiffies; 717 s[0] = jiffies;
@@ -929,6 +1298,10 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
929 nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); 1298 nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
930 } 1299 }
931 data->timestamp = jiffies; 1300 data->timestamp = jiffies;
1301 if (nfs4_setup_sequence(data->o_arg.server->nfs_client,
1302 &data->o_arg.seq_args,
1303 &data->o_res.seq_res, 1, task))
1304 return;
932 rpc_call_start(task); 1305 rpc_call_start(task);
933 return; 1306 return;
934out_no_action: 1307out_no_action:
@@ -941,6 +1314,10 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
941 struct nfs4_opendata *data = calldata; 1314 struct nfs4_opendata *data = calldata;
942 1315
943 data->rpc_status = task->tk_status; 1316 data->rpc_status = task->tk_status;
1317
1318 nfs4_sequence_done_free_slot(data->o_arg.server, &data->o_res.seq_res,
1319 task->tk_status);
1320
944 if (RPC_ASSASSINATED(task)) 1321 if (RPC_ASSASSINATED(task))
945 return; 1322 return;
946 if (task->tk_status == 0) { 1323 if (task->tk_status == 0) {
@@ -1269,7 +1646,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1269 } else 1646 } else
1270 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); 1647 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
1271 1648
1272 status = rpc_call_sync(server->client, &msg, 0); 1649 status = nfs4_call_sync(server, &msg, &arg, &res, 1);
1273 if (status == 0 && state != NULL) 1650 if (status == 0 && state != NULL)
1274 renew_lease(server, timestamp); 1651 renew_lease(server, timestamp);
1275 return status; 1652 return status;
@@ -1318,6 +1695,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
1318 struct nfs4_state *state = calldata->state; 1695 struct nfs4_state *state = calldata->state;
1319 struct nfs_server *server = NFS_SERVER(calldata->inode); 1696 struct nfs_server *server = NFS_SERVER(calldata->inode);
1320 1697
1698 nfs4_sequence_done(server, &calldata->res.seq_res, task->tk_status);
1321 if (RPC_ASSASSINATED(task)) 1699 if (RPC_ASSASSINATED(task))
1322 return; 1700 return;
1323 /* hmm. we are done with the inode, and in the process of freeing 1701 /* hmm. we are done with the inode, and in the process of freeing
@@ -1336,10 +1714,11 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
1336 break; 1714 break;
1337 default: 1715 default:
1338 if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { 1716 if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
1339 rpc_restart_call(task); 1717 nfs4_restart_rpc(task, server->nfs_client);
1340 return; 1718 return;
1341 } 1719 }
1342 } 1720 }
1721 nfs4_sequence_free_slot(server->nfs_client, &calldata->res.seq_res);
1343 nfs_refresh_inode(calldata->inode, calldata->res.fattr); 1722 nfs_refresh_inode(calldata->inode, calldata->res.fattr);
1344} 1723}
1345 1724
@@ -1380,6 +1759,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
1380 calldata->arg.fmode = FMODE_WRITE; 1759 calldata->arg.fmode = FMODE_WRITE;
1381 } 1760 }
1382 calldata->timestamp = jiffies; 1761 calldata->timestamp = jiffies;
1762 if (nfs4_setup_sequence((NFS_SERVER(calldata->inode))->nfs_client,
1763 &calldata->arg.seq_args, &calldata->res.seq_res,
1764 1, task))
1765 return;
1383 rpc_call_start(task); 1766 rpc_call_start(task);
1384} 1767}
1385 1768
@@ -1419,13 +1802,15 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
1419 }; 1802 };
1420 int status = -ENOMEM; 1803 int status = -ENOMEM;
1421 1804
1422 calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); 1805 calldata = kzalloc(sizeof(*calldata), GFP_KERNEL);
1423 if (calldata == NULL) 1806 if (calldata == NULL)
1424 goto out; 1807 goto out;
1425 calldata->inode = state->inode; 1808 calldata->inode = state->inode;
1426 calldata->state = state; 1809 calldata->state = state;
1427 calldata->arg.fh = NFS_FH(state->inode); 1810 calldata->arg.fh = NFS_FH(state->inode);
1428 calldata->arg.stateid = &state->open_stateid; 1811 calldata->arg.stateid = &state->open_stateid;
1812 if (nfs4_has_session(server->nfs_client))
1813 memset(calldata->arg.stateid->data, 0, 4); /* clear seqid */
1429 /* Serialization for the sequence id */ 1814 /* Serialization for the sequence id */
1430 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); 1815 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
1431 if (calldata->arg.seqid == NULL) 1816 if (calldata->arg.seqid == NULL)
@@ -1435,6 +1820,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
1435 calldata->res.fattr = &calldata->fattr; 1820 calldata->res.fattr = &calldata->fattr;
1436 calldata->res.seqid = calldata->arg.seqid; 1821 calldata->res.seqid = calldata->arg.seqid;
1437 calldata->res.server = server; 1822 calldata->res.server = server;
1823 calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
1438 calldata->path.mnt = mntget(path->mnt); 1824 calldata->path.mnt = mntget(path->mnt);
1439 calldata->path.dentry = dget(path->dentry); 1825 calldata->path.dentry = dget(path->dentry);
1440 1826
@@ -1584,15 +1970,18 @@ void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
1584 1970
1585static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) 1971static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
1586{ 1972{
1973 struct nfs4_server_caps_arg args = {
1974 .fhandle = fhandle,
1975 };
1587 struct nfs4_server_caps_res res = {}; 1976 struct nfs4_server_caps_res res = {};
1588 struct rpc_message msg = { 1977 struct rpc_message msg = {
1589 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS], 1978 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],
1590 .rpc_argp = fhandle, 1979 .rpc_argp = &args,
1591 .rpc_resp = &res, 1980 .rpc_resp = &res,
1592 }; 1981 };
1593 int status; 1982 int status;
1594 1983
1595 status = rpc_call_sync(server->client, &msg, 0); 1984 status = nfs4_call_sync(server, &msg, &args, &res, 0);
1596 if (status == 0) { 1985 if (status == 0) {
1597 memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); 1986 memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
1598 if (res.attr_bitmask[0] & FATTR4_WORD0_ACL) 1987 if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
@@ -1606,6 +1995,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
1606 server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; 1995 server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
1607 server->acl_bitmask = res.acl_bitmask; 1996 server->acl_bitmask = res.acl_bitmask;
1608 } 1997 }
1998
1609 return status; 1999 return status;
1610} 2000}
1611 2001
@@ -1637,8 +2027,15 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
1637 .rpc_argp = &args, 2027 .rpc_argp = &args,
1638 .rpc_resp = &res, 2028 .rpc_resp = &res,
1639 }; 2029 };
2030 int status;
2031
1640 nfs_fattr_init(info->fattr); 2032 nfs_fattr_init(info->fattr);
1641 return rpc_call_sync(server->client, &msg, 0); 2033 status = nfs4_recover_expired_lease(server);
2034 if (!status)
2035 status = nfs4_check_client_ready(server->nfs_client);
2036 if (!status)
2037 status = nfs4_call_sync(server, &msg, &args, &res, 0);
2038 return status;
1642} 2039}
1643 2040
1644static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, 2041static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -1728,7 +2125,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
1728 }; 2125 };
1729 2126
1730 nfs_fattr_init(fattr); 2127 nfs_fattr_init(fattr);
1731 return rpc_call_sync(server->client, &msg, 0); 2128 return nfs4_call_sync(server, &msg, &args, &res, 0);
1732} 2129}
1733 2130
1734static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) 2131static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
@@ -1812,7 +2209,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
1812 nfs_fattr_init(fattr); 2209 nfs_fattr_init(fattr);
1813 2210
1814 dprintk("NFS call lookupfh %s\n", name->name); 2211 dprintk("NFS call lookupfh %s\n", name->name);
1815 status = rpc_call_sync(server->client, &msg, 0); 2212 status = nfs4_call_sync(server, &msg, &args, &res, 0);
1816 dprintk("NFS reply lookupfh: %d\n", status); 2213 dprintk("NFS reply lookupfh: %d\n", status);
1817 return status; 2214 return status;
1818} 2215}
@@ -1898,7 +2295,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
1898 args.access |= NFS4_ACCESS_EXECUTE; 2295 args.access |= NFS4_ACCESS_EXECUTE;
1899 } 2296 }
1900 nfs_fattr_init(&fattr); 2297 nfs_fattr_init(&fattr);
1901 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 2298 status = nfs4_call_sync(server, &msg, &args, &res, 0);
1902 if (!status) { 2299 if (!status) {
1903 entry->mask = 0; 2300 entry->mask = 0;
1904 if (res.access & NFS4_ACCESS_READ) 2301 if (res.access & NFS4_ACCESS_READ)
@@ -1957,13 +2354,14 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
1957 .pglen = pglen, 2354 .pglen = pglen,
1958 .pages = &page, 2355 .pages = &page,
1959 }; 2356 };
2357 struct nfs4_readlink_res res;
1960 struct rpc_message msg = { 2358 struct rpc_message msg = {
1961 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK], 2359 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK],
1962 .rpc_argp = &args, 2360 .rpc_argp = &args,
1963 .rpc_resp = NULL, 2361 .rpc_resp = &res,
1964 }; 2362 };
1965 2363
1966 return rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 2364 return nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0);
1967} 2365}
1968 2366
1969static int nfs4_proc_readlink(struct inode *inode, struct page *page, 2367static int nfs4_proc_readlink(struct inode *inode, struct page *page,
@@ -2057,7 +2455,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
2057 int status; 2455 int status;
2058 2456
2059 nfs_fattr_init(&res.dir_attr); 2457 nfs_fattr_init(&res.dir_attr);
2060 status = rpc_call_sync(server->client, &msg, 0); 2458 status = nfs4_call_sync(server, &msg, &args, &res, 1);
2061 if (status == 0) { 2459 if (status == 0) {
2062 update_changeattr(dir, &res.cinfo); 2460 update_changeattr(dir, &res.cinfo);
2063 nfs_post_op_update_inode(dir, &res.dir_attr); 2461 nfs_post_op_update_inode(dir, &res.dir_attr);
@@ -2092,8 +2490,10 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
2092{ 2490{
2093 struct nfs_removeres *res = task->tk_msg.rpc_resp; 2491 struct nfs_removeres *res = task->tk_msg.rpc_resp;
2094 2492
2493 nfs4_sequence_done(res->server, &res->seq_res, task->tk_status);
2095 if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) 2494 if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
2096 return 0; 2495 return 0;
2496 nfs4_sequence_free_slot(res->server->nfs_client, &res->seq_res);
2097 update_changeattr(dir, &res->cinfo); 2497 update_changeattr(dir, &res->cinfo);
2098 nfs_post_op_update_inode(dir, &res->dir_attr); 2498 nfs_post_op_update_inode(dir, &res->dir_attr);
2099 return 1; 2499 return 1;
@@ -2125,7 +2525,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
2125 2525
2126 nfs_fattr_init(res.old_fattr); 2526 nfs_fattr_init(res.old_fattr);
2127 nfs_fattr_init(res.new_fattr); 2527 nfs_fattr_init(res.new_fattr);
2128 status = rpc_call_sync(server->client, &msg, 0); 2528 status = nfs4_call_sync(server, &msg, &arg, &res, 1);
2129 2529
2130 if (!status) { 2530 if (!status) {
2131 update_changeattr(old_dir, &res.old_cinfo); 2531 update_changeattr(old_dir, &res.old_cinfo);
@@ -2174,7 +2574,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
2174 2574
2175 nfs_fattr_init(res.fattr); 2575 nfs_fattr_init(res.fattr);
2176 nfs_fattr_init(res.dir_attr); 2576 nfs_fattr_init(res.dir_attr);
2177 status = rpc_call_sync(server->client, &msg, 0); 2577 status = nfs4_call_sync(server, &msg, &arg, &res, 1);
2178 if (!status) { 2578 if (!status) {
2179 update_changeattr(dir, &res.cinfo); 2579 update_changeattr(dir, &res.cinfo);
2180 nfs_post_op_update_inode(dir, res.dir_attr); 2580 nfs_post_op_update_inode(dir, res.dir_attr);
@@ -2235,7 +2635,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
2235 2635
2236static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) 2636static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
2237{ 2637{
2238 int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); 2638 int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg,
2639 &data->arg, &data->res, 1);
2239 if (status == 0) { 2640 if (status == 0) {
2240 update_changeattr(dir, &data->res.dir_cinfo); 2641 update_changeattr(dir, &data->res.dir_cinfo);
2241 nfs_post_op_update_inode(dir, data->res.dir_fattr); 2642 nfs_post_op_update_inode(dir, data->res.dir_fattr);
@@ -2344,7 +2745,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
2344 (unsigned long long)cookie); 2745 (unsigned long long)cookie);
2345 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); 2746 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
2346 res.pgbase = args.pgbase; 2747 res.pgbase = args.pgbase;
2347 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); 2748 status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0);
2348 if (status == 0) 2749 if (status == 0)
2349 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); 2750 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
2350 2751
@@ -2422,14 +2823,17 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
2422 .fh = fhandle, 2823 .fh = fhandle,
2423 .bitmask = server->attr_bitmask, 2824 .bitmask = server->attr_bitmask,
2424 }; 2825 };
2826 struct nfs4_statfs_res res = {
2827 .fsstat = fsstat,
2828 };
2425 struct rpc_message msg = { 2829 struct rpc_message msg = {
2426 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS], 2830 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS],
2427 .rpc_argp = &args, 2831 .rpc_argp = &args,
2428 .rpc_resp = fsstat, 2832 .rpc_resp = &res,
2429 }; 2833 };
2430 2834
2431 nfs_fattr_init(fsstat->fattr); 2835 nfs_fattr_init(fsstat->fattr);
2432 return rpc_call_sync(server->client, &msg, 0); 2836 return nfs4_call_sync(server, &msg, &args, &res, 0);
2433} 2837}
2434 2838
2435static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) 2839static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
@@ -2451,13 +2855,16 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
2451 .fh = fhandle, 2855 .fh = fhandle,
2452 .bitmask = server->attr_bitmask, 2856 .bitmask = server->attr_bitmask,
2453 }; 2857 };
2858 struct nfs4_fsinfo_res res = {
2859 .fsinfo = fsinfo,
2860 };
2454 struct rpc_message msg = { 2861 struct rpc_message msg = {
2455 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO], 2862 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
2456 .rpc_argp = &args, 2863 .rpc_argp = &args,
2457 .rpc_resp = fsinfo, 2864 .rpc_resp = &res,
2458 }; 2865 };
2459 2866
2460 return rpc_call_sync(server->client, &msg, 0); 2867 return nfs4_call_sync(server, &msg, &args, &res, 0);
2461} 2868}
2462 2869
2463static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) 2870static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
@@ -2486,10 +2893,13 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
2486 .fh = fhandle, 2893 .fh = fhandle,
2487 .bitmask = server->attr_bitmask, 2894 .bitmask = server->attr_bitmask,
2488 }; 2895 };
2896 struct nfs4_pathconf_res res = {
2897 .pathconf = pathconf,
2898 };
2489 struct rpc_message msg = { 2899 struct rpc_message msg = {
2490 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF], 2900 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF],
2491 .rpc_argp = &args, 2901 .rpc_argp = &args,
2492 .rpc_resp = pathconf, 2902 .rpc_resp = &res,
2493 }; 2903 };
2494 2904
2495 /* None of the pathconf attributes are mandatory to implement */ 2905 /* None of the pathconf attributes are mandatory to implement */
@@ -2499,7 +2909,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
2499 } 2909 }
2500 2910
2501 nfs_fattr_init(pathconf->fattr); 2911 nfs_fattr_init(pathconf->fattr);
2502 return rpc_call_sync(server->client, &msg, 0); 2912 return nfs4_call_sync(server, &msg, &args, &res, 0);
2503} 2913}
2504 2914
2505static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, 2915static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -2520,8 +2930,13 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
2520{ 2930{
2521 struct nfs_server *server = NFS_SERVER(data->inode); 2931 struct nfs_server *server = NFS_SERVER(data->inode);
2522 2932
2933 dprintk("--> %s\n", __func__);
2934
2935 /* nfs4_sequence_free_slot called in the read rpc_call_done */
2936 nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
2937
2523 if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { 2938 if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
2524 rpc_restart_call(task); 2939 nfs4_restart_rpc(task, server->nfs_client);
2525 return -EAGAIN; 2940 return -EAGAIN;
2526 } 2941 }
2527 2942
@@ -2541,8 +2956,12 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
2541{ 2956{
2542 struct inode *inode = data->inode; 2957 struct inode *inode = data->inode;
2543 2958
2959 /* slot is freed in nfs_writeback_done */
2960 nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
2961 task->tk_status);
2962
2544 if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { 2963 if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
2545 rpc_restart_call(task); 2964 nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
2546 return -EAGAIN; 2965 return -EAGAIN;
2547 } 2966 }
2548 if (task->tk_status >= 0) { 2967 if (task->tk_status >= 0) {
@@ -2567,10 +2986,14 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
2567{ 2986{
2568 struct inode *inode = data->inode; 2987 struct inode *inode = data->inode;
2569 2988
2989 nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
2990 task->tk_status);
2570 if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { 2991 if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
2571 rpc_restart_call(task); 2992 nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
2572 return -EAGAIN; 2993 return -EAGAIN;
2573 } 2994 }
2995 nfs4_sequence_free_slot(NFS_SERVER(inode)->nfs_client,
2996 &data->res.seq_res);
2574 nfs_refresh_inode(inode, data->res.fattr); 2997 nfs_refresh_inode(inode, data->res.fattr);
2575 return 0; 2998 return 0;
2576} 2999}
@@ -2603,6 +3026,9 @@ static void nfs4_renew_done(struct rpc_task *task, void *data)
2603 if (time_before(clp->cl_last_renewal,timestamp)) 3026 if (time_before(clp->cl_last_renewal,timestamp))
2604 clp->cl_last_renewal = timestamp; 3027 clp->cl_last_renewal = timestamp;
2605 spin_unlock(&clp->cl_lock); 3028 spin_unlock(&clp->cl_lock);
3029 dprintk("%s calling put_rpccred on rpc_cred %p\n", __func__,
3030 task->tk_msg.rpc_cred);
3031 put_rpccred(task->tk_msg.rpc_cred);
2606} 3032}
2607 3033
2608static const struct rpc_call_ops nfs4_renew_ops = { 3034static const struct rpc_call_ops nfs4_renew_ops = {
@@ -2742,12 +3168,14 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
2742 .acl_pages = pages, 3168 .acl_pages = pages,
2743 .acl_len = buflen, 3169 .acl_len = buflen,
2744 }; 3170 };
2745 size_t resp_len = buflen; 3171 struct nfs_getaclres res = {
3172 .acl_len = buflen,
3173 };
2746 void *resp_buf; 3174 void *resp_buf;
2747 struct rpc_message msg = { 3175 struct rpc_message msg = {
2748 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], 3176 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
2749 .rpc_argp = &args, 3177 .rpc_argp = &args,
2750 .rpc_resp = &resp_len, 3178 .rpc_resp = &res,
2751 }; 3179 };
2752 struct page *localpage = NULL; 3180 struct page *localpage = NULL;
2753 int ret; 3181 int ret;
@@ -2761,26 +3189,26 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
2761 return -ENOMEM; 3189 return -ENOMEM;
2762 args.acl_pages[0] = localpage; 3190 args.acl_pages[0] = localpage;
2763 args.acl_pgbase = 0; 3191 args.acl_pgbase = 0;
2764 resp_len = args.acl_len = PAGE_SIZE; 3192 args.acl_len = PAGE_SIZE;
2765 } else { 3193 } else {
2766 resp_buf = buf; 3194 resp_buf = buf;
2767 buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); 3195 buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
2768 } 3196 }
2769 ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 3197 ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0);
2770 if (ret) 3198 if (ret)
2771 goto out_free; 3199 goto out_free;
2772 if (resp_len > args.acl_len) 3200 if (res.acl_len > args.acl_len)
2773 nfs4_write_cached_acl(inode, NULL, resp_len); 3201 nfs4_write_cached_acl(inode, NULL, res.acl_len);
2774 else 3202 else
2775 nfs4_write_cached_acl(inode, resp_buf, resp_len); 3203 nfs4_write_cached_acl(inode, resp_buf, res.acl_len);
2776 if (buf) { 3204 if (buf) {
2777 ret = -ERANGE; 3205 ret = -ERANGE;
2778 if (resp_len > buflen) 3206 if (res.acl_len > buflen)
2779 goto out_free; 3207 goto out_free;
2780 if (localpage) 3208 if (localpage)
2781 memcpy(buf, resp_buf, resp_len); 3209 memcpy(buf, resp_buf, res.acl_len);
2782 } 3210 }
2783 ret = resp_len; 3211 ret = res.acl_len;
2784out_free: 3212out_free:
2785 if (localpage) 3213 if (localpage)
2786 __free_page(localpage); 3214 __free_page(localpage);
@@ -2827,10 +3255,11 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
2827 .acl_pages = pages, 3255 .acl_pages = pages,
2828 .acl_len = buflen, 3256 .acl_len = buflen,
2829 }; 3257 };
3258 struct nfs_setaclres res;
2830 struct rpc_message msg = { 3259 struct rpc_message msg = {
2831 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL], 3260 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL],
2832 .rpc_argp = &arg, 3261 .rpc_argp = &arg,
2833 .rpc_resp = NULL, 3262 .rpc_resp = &res,
2834 }; 3263 };
2835 int ret; 3264 int ret;
2836 3265
@@ -2838,7 +3267,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
2838 return -EOPNOTSUPP; 3267 return -EOPNOTSUPP;
2839 nfs_inode_return_delegation(inode); 3268 nfs_inode_return_delegation(inode);
2840 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); 3269 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
2841 ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 3270 ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
2842 nfs_access_zap_cache(inode); 3271 nfs_access_zap_cache(inode);
2843 nfs_zap_acl_cache(inode); 3272 nfs_zap_acl_cache(inode);
2844 return ret; 3273 return ret;
@@ -2857,10 +3286,8 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
2857} 3286}
2858 3287
2859static int 3288static int
2860nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) 3289_nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs_client *clp, struct nfs4_state *state)
2861{ 3290{
2862 struct nfs_client *clp = server->nfs_client;
2863
2864 if (!clp || task->tk_status >= 0) 3291 if (!clp || task->tk_status >= 0)
2865 return 0; 3292 return 0;
2866 switch(task->tk_status) { 3293 switch(task->tk_status) {
@@ -2879,8 +3306,23 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
2879 rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); 3306 rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
2880 task->tk_status = 0; 3307 task->tk_status = 0;
2881 return -EAGAIN; 3308 return -EAGAIN;
3309#if defined(CONFIG_NFS_V4_1)
3310 case -NFS4ERR_BADSESSION:
3311 case -NFS4ERR_BADSLOT:
3312 case -NFS4ERR_BAD_HIGH_SLOT:
3313 case -NFS4ERR_DEADSESSION:
3314 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
3315 case -NFS4ERR_SEQ_FALSE_RETRY:
3316 case -NFS4ERR_SEQ_MISORDERED:
3317 dprintk("%s ERROR %d, Reset session\n", __func__,
3318 task->tk_status);
3319 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
3320 task->tk_status = 0;
3321 return -EAGAIN;
3322#endif /* CONFIG_NFS_V4_1 */
2882 case -NFS4ERR_DELAY: 3323 case -NFS4ERR_DELAY:
2883 nfs_inc_server_stats(server, NFSIOS_DELAY); 3324 if (server)
3325 nfs_inc_server_stats(server, NFSIOS_DELAY);
2884 case -NFS4ERR_GRACE: 3326 case -NFS4ERR_GRACE:
2885 rpc_delay(task, NFS4_POLL_RETRY_MAX); 3327 rpc_delay(task, NFS4_POLL_RETRY_MAX);
2886 task->tk_status = 0; 3328 task->tk_status = 0;
@@ -2893,6 +3335,12 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
2893 return 0; 3335 return 0;
2894} 3336}
2895 3337
3338static int
3339nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
3340{
3341 return _nfs4_async_handle_error(task, server, server->nfs_client, state);
3342}
3343
2896int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) 3344int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred)
2897{ 3345{
2898 nfs4_verifier sc_verifier; 3346 nfs4_verifier sc_verifier;
@@ -3000,6 +3448,10 @@ struct nfs4_delegreturndata {
3000static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) 3448static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
3001{ 3449{
3002 struct nfs4_delegreturndata *data = calldata; 3450 struct nfs4_delegreturndata *data = calldata;
3451
3452 nfs4_sequence_done_free_slot(data->res.server, &data->res.seq_res,
3453 task->tk_status);
3454
3003 data->rpc_status = task->tk_status; 3455 data->rpc_status = task->tk_status;
3004 if (data->rpc_status == 0) 3456 if (data->rpc_status == 0)
3005 renew_lease(data->res.server, data->timestamp); 3457 renew_lease(data->res.server, data->timestamp);
@@ -3010,7 +3462,25 @@ static void nfs4_delegreturn_release(void *calldata)
3010 kfree(calldata); 3462 kfree(calldata);
3011} 3463}
3012 3464
3465#if defined(CONFIG_NFS_V4_1)
3466static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
3467{
3468 struct nfs4_delegreturndata *d_data;
3469
3470 d_data = (struct nfs4_delegreturndata *)data;
3471
3472 if (nfs4_setup_sequence(d_data->res.server->nfs_client,
3473 &d_data->args.seq_args,
3474 &d_data->res.seq_res, 1, task))
3475 return;
3476 rpc_call_start(task);
3477}
3478#endif /* CONFIG_NFS_V4_1 */
3479
3013static const struct rpc_call_ops nfs4_delegreturn_ops = { 3480static const struct rpc_call_ops nfs4_delegreturn_ops = {
3481#if defined(CONFIG_NFS_V4_1)
3482 .rpc_call_prepare = nfs4_delegreturn_prepare,
3483#endif /* CONFIG_NFS_V4_1 */
3014 .rpc_call_done = nfs4_delegreturn_done, 3484 .rpc_call_done = nfs4_delegreturn_done,
3015 .rpc_release = nfs4_delegreturn_release, 3485 .rpc_release = nfs4_delegreturn_release,
3016}; 3486};
@@ -3032,7 +3502,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
3032 }; 3502 };
3033 int status = 0; 3503 int status = 0;
3034 3504
3035 data = kmalloc(sizeof(*data), GFP_KERNEL); 3505 data = kzalloc(sizeof(*data), GFP_KERNEL);
3036 if (data == NULL) 3506 if (data == NULL)
3037 return -ENOMEM; 3507 return -ENOMEM;
3038 data->args.fhandle = &data->fh; 3508 data->args.fhandle = &data->fh;
@@ -3042,6 +3512,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
3042 memcpy(&data->stateid, stateid, sizeof(data->stateid)); 3512 memcpy(&data->stateid, stateid, sizeof(data->stateid));
3043 data->res.fattr = &data->fattr; 3513 data->res.fattr = &data->fattr;
3044 data->res.server = server; 3514 data->res.server = server;
3515 data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
3045 nfs_fattr_init(data->res.fattr); 3516 nfs_fattr_init(data->res.fattr);
3046 data->timestamp = jiffies; 3517 data->timestamp = jiffies;
3047 data->rpc_status = 0; 3518 data->rpc_status = 0;
@@ -3127,7 +3598,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
3127 goto out; 3598 goto out;
3128 lsp = request->fl_u.nfs4_fl.owner; 3599 lsp = request->fl_u.nfs4_fl.owner;
3129 arg.lock_owner.id = lsp->ls_id.id; 3600 arg.lock_owner.id = lsp->ls_id.id;
3130 status = rpc_call_sync(server->client, &msg, 0); 3601 status = nfs4_call_sync(server, &msg, &arg, &res, 1);
3131 switch (status) { 3602 switch (status) {
3132 case 0: 3603 case 0:
3133 request->fl_type = F_UNLCK; 3604 request->fl_type = F_UNLCK;
@@ -3187,13 +3658,14 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
3187 struct nfs4_unlockdata *p; 3658 struct nfs4_unlockdata *p;
3188 struct inode *inode = lsp->ls_state->inode; 3659 struct inode *inode = lsp->ls_state->inode;
3189 3660
3190 p = kmalloc(sizeof(*p), GFP_KERNEL); 3661 p = kzalloc(sizeof(*p), GFP_KERNEL);
3191 if (p == NULL) 3662 if (p == NULL)
3192 return NULL; 3663 return NULL;
3193 p->arg.fh = NFS_FH(inode); 3664 p->arg.fh = NFS_FH(inode);
3194 p->arg.fl = &p->fl; 3665 p->arg.fl = &p->fl;
3195 p->arg.seqid = seqid; 3666 p->arg.seqid = seqid;
3196 p->res.seqid = seqid; 3667 p->res.seqid = seqid;
3668 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
3197 p->arg.stateid = &lsp->ls_stateid; 3669 p->arg.stateid = &lsp->ls_stateid;
3198 p->lsp = lsp; 3670 p->lsp = lsp;
3199 atomic_inc(&lsp->ls_count); 3671 atomic_inc(&lsp->ls_count);
@@ -3217,6 +3689,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
3217{ 3689{
3218 struct nfs4_unlockdata *calldata = data; 3690 struct nfs4_unlockdata *calldata = data;
3219 3691
3692 nfs4_sequence_done(calldata->server, &calldata->res.seq_res,
3693 task->tk_status);
3220 if (RPC_ASSASSINATED(task)) 3694 if (RPC_ASSASSINATED(task))
3221 return; 3695 return;
3222 switch (task->tk_status) { 3696 switch (task->tk_status) {
@@ -3233,8 +3707,11 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
3233 break; 3707 break;
3234 default: 3708 default:
3235 if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) 3709 if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
3236 rpc_restart_call(task); 3710 nfs4_restart_rpc(task,
3711 calldata->server->nfs_client);
3237 } 3712 }
3713 nfs4_sequence_free_slot(calldata->server->nfs_client,
3714 &calldata->res.seq_res);
3238} 3715}
3239 3716
3240static void nfs4_locku_prepare(struct rpc_task *task, void *data) 3717static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -3249,6 +3726,10 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
3249 return; 3726 return;
3250 } 3727 }
3251 calldata->timestamp = jiffies; 3728 calldata->timestamp = jiffies;
3729 if (nfs4_setup_sequence(calldata->server->nfs_client,
3730 &calldata->arg.seq_args,
3731 &calldata->res.seq_res, 1, task))
3732 return;
3252 rpc_call_start(task); 3733 rpc_call_start(task);
3253} 3734}
3254 3735
@@ -3341,6 +3822,7 @@ struct nfs4_lockdata {
3341 unsigned long timestamp; 3822 unsigned long timestamp;
3342 int rpc_status; 3823 int rpc_status;
3343 int cancelled; 3824 int cancelled;
3825 struct nfs_server *server;
3344}; 3826};
3345 3827
3346static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, 3828static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
@@ -3366,7 +3848,9 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
3366 p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; 3848 p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
3367 p->arg.lock_owner.id = lsp->ls_id.id; 3849 p->arg.lock_owner.id = lsp->ls_id.id;
3368 p->res.lock_seqid = p->arg.lock_seqid; 3850 p->res.lock_seqid = p->arg.lock_seqid;
3851 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
3369 p->lsp = lsp; 3852 p->lsp = lsp;
3853 p->server = server;
3370 atomic_inc(&lsp->ls_count); 3854 atomic_inc(&lsp->ls_count);
3371 p->ctx = get_nfs_open_context(ctx); 3855 p->ctx = get_nfs_open_context(ctx);
3372 memcpy(&p->fl, fl, sizeof(p->fl)); 3856 memcpy(&p->fl, fl, sizeof(p->fl));
@@ -3396,6 +3880,9 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
3396 } else 3880 } else
3397 data->arg.new_lock_owner = 0; 3881 data->arg.new_lock_owner = 0;
3398 data->timestamp = jiffies; 3882 data->timestamp = jiffies;
3883 if (nfs4_setup_sequence(data->server->nfs_client, &data->arg.seq_args,
3884 &data->res.seq_res, 1, task))
3885 return;
3399 rpc_call_start(task); 3886 rpc_call_start(task);
3400 dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); 3887 dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
3401} 3888}
@@ -3406,6 +3893,9 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
3406 3893
3407 dprintk("%s: begin!\n", __func__); 3894 dprintk("%s: begin!\n", __func__);
3408 3895
3896 nfs4_sequence_done_free_slot(data->server, &data->res.seq_res,
3897 task->tk_status);
3898
3409 data->rpc_status = task->tk_status; 3899 data->rpc_status = task->tk_status;
3410 if (RPC_ASSASSINATED(task)) 3900 if (RPC_ASSASSINATED(task))
3411 goto out; 3901 goto out;
@@ -3706,10 +4196,13 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
3706 .page = page, 4196 .page = page,
3707 .bitmask = bitmask, 4197 .bitmask = bitmask,
3708 }; 4198 };
4199 struct nfs4_fs_locations_res res = {
4200 .fs_locations = fs_locations,
4201 };
3709 struct rpc_message msg = { 4202 struct rpc_message msg = {
3710 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], 4203 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
3711 .rpc_argp = &args, 4204 .rpc_argp = &args,
3712 .rpc_resp = fs_locations, 4205 .rpc_resp = &res,
3713 }; 4206 };
3714 int status; 4207 int status;
3715 4208
@@ -3717,24 +4210,720 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
3717 nfs_fattr_init(&fs_locations->fattr); 4210 nfs_fattr_init(&fs_locations->fattr);
3718 fs_locations->server = server; 4211 fs_locations->server = server;
3719 fs_locations->nlocations = 0; 4212 fs_locations->nlocations = 0;
3720 status = rpc_call_sync(server->client, &msg, 0); 4213 status = nfs4_call_sync(server, &msg, &args, &res, 0);
3721 nfs_fixup_referral_attributes(&fs_locations->fattr); 4214 nfs_fixup_referral_attributes(&fs_locations->fattr);
3722 dprintk("%s: returned status = %d\n", __func__, status); 4215 dprintk("%s: returned status = %d\n", __func__, status);
3723 return status; 4216 return status;
3724} 4217}
3725 4218
3726struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { 4219#ifdef CONFIG_NFS_V4_1
4220/*
4221 * nfs4_proc_exchange_id()
4222 *
4223 * Since the clientid has expired, all compounds using sessions
4224 * associated with the stale clientid will be returning
4225 * NFS4ERR_BADSESSION in the sequence operation, and will therefore
4226 * be in some phase of session reset.
4227 */
4228static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
4229{
4230 nfs4_verifier verifier;
4231 struct nfs41_exchange_id_args args = {
4232 .client = clp,
4233 .flags = clp->cl_exchange_flags,
4234 };
4235 struct nfs41_exchange_id_res res = {
4236 .client = clp,
4237 };
4238 int status;
4239 struct rpc_message msg = {
4240 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID],
4241 .rpc_argp = &args,
4242 .rpc_resp = &res,
4243 .rpc_cred = cred,
4244 };
4245 __be32 *p;
4246
4247 dprintk("--> %s\n", __func__);
4248 BUG_ON(clp == NULL);
4249
4250 p = (u32 *)verifier.data;
4251 *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
4252 *p = htonl((u32)clp->cl_boot_time.tv_nsec);
4253 args.verifier = &verifier;
4254
4255 while (1) {
4256 args.id_len = scnprintf(args.id, sizeof(args.id),
4257 "%s/%s %u",
4258 clp->cl_ipaddr,
4259 rpc_peeraddr2str(clp->cl_rpcclient,
4260 RPC_DISPLAY_ADDR),
4261 clp->cl_id_uniquifier);
4262
4263 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
4264
4265 if (status != NFS4ERR_CLID_INUSE)
4266 break;
4267
4268 if (signalled())
4269 break;
4270
4271 if (++clp->cl_id_uniquifier == 0)
4272 break;
4273 }
4274
4275 dprintk("<-- %s status= %d\n", __func__, status);
4276 return status;
4277}
4278
4279struct nfs4_get_lease_time_data {
4280 struct nfs4_get_lease_time_args *args;
4281 struct nfs4_get_lease_time_res *res;
4282 struct nfs_client *clp;
4283};
4284
4285static void nfs4_get_lease_time_prepare(struct rpc_task *task,
4286 void *calldata)
4287{
4288 int ret;
4289 struct nfs4_get_lease_time_data *data =
4290 (struct nfs4_get_lease_time_data *)calldata;
4291
4292 dprintk("--> %s\n", __func__);
4293 /* just setup sequence, do not trigger session recovery
4294 since we're invoked within one */
4295 ret = nfs41_setup_sequence(data->clp->cl_session,
4296 &data->args->la_seq_args,
4297 &data->res->lr_seq_res, 0, task);
4298
4299 BUG_ON(ret == -EAGAIN);
4300 rpc_call_start(task);
4301 dprintk("<-- %s\n", __func__);
4302}
4303
4304/*
4305 * Called from nfs4_state_manager thread for session setup, so don't recover
4306 * from sequence operation or clientid errors.
4307 */
4308static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
4309{
4310 struct nfs4_get_lease_time_data *data =
4311 (struct nfs4_get_lease_time_data *)calldata;
4312
4313 dprintk("--> %s\n", __func__);
4314 nfs41_sequence_done(data->clp, &data->res->lr_seq_res, task->tk_status);
4315 switch (task->tk_status) {
4316 case -NFS4ERR_DELAY:
4317 case -NFS4ERR_GRACE:
4318 dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
4319 rpc_delay(task, NFS4_POLL_RETRY_MIN);
4320 task->tk_status = 0;
4321 nfs4_restart_rpc(task, data->clp);
4322 return;
4323 }
4324 nfs41_sequence_free_slot(data->clp, &data->res->lr_seq_res);
4325 dprintk("<-- %s\n", __func__);
4326}
4327
4328struct rpc_call_ops nfs4_get_lease_time_ops = {
4329 .rpc_call_prepare = nfs4_get_lease_time_prepare,
4330 .rpc_call_done = nfs4_get_lease_time_done,
4331};
4332
4333int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
4334{
4335 struct rpc_task *task;
4336 struct nfs4_get_lease_time_args args;
4337 struct nfs4_get_lease_time_res res = {
4338 .lr_fsinfo = fsinfo,
4339 };
4340 struct nfs4_get_lease_time_data data = {
4341 .args = &args,
4342 .res = &res,
4343 .clp = clp,
4344 };
4345 struct rpc_message msg = {
4346 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GET_LEASE_TIME],
4347 .rpc_argp = &args,
4348 .rpc_resp = &res,
4349 };
4350 struct rpc_task_setup task_setup = {
4351 .rpc_client = clp->cl_rpcclient,
4352 .rpc_message = &msg,
4353 .callback_ops = &nfs4_get_lease_time_ops,
4354 .callback_data = &data
4355 };
4356 int status;
4357
4358 res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
4359 dprintk("--> %s\n", __func__);
4360 task = rpc_run_task(&task_setup);
4361
4362 if (IS_ERR(task))
4363 status = PTR_ERR(task);
4364 else {
4365 status = task->tk_status;
4366 rpc_put_task(task);
4367 }
4368 dprintk("<-- %s return %d\n", __func__, status);
4369
4370 return status;
4371}
4372
4373/*
4374 * Reset a slot table
4375 */
4376static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots,
4377 int old_max_slots, int ivalue)
4378{
4379 int i;
4380 int ret = 0;
4381
4382 dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__, max_slots, tbl);
4383
4384 /*
4385 * Until we have dynamic slot table adjustment, insist
4386 * upon the same slot table size
4387 */
4388 if (max_slots != old_max_slots) {
4389 dprintk("%s reset slot table does't match old\n",
4390 __func__);
4391 ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */
4392 goto out;
4393 }
4394 spin_lock(&tbl->slot_tbl_lock);
4395 for (i = 0; i < max_slots; ++i)
4396 tbl->slots[i].seq_nr = ivalue;
4397 tbl->highest_used_slotid = -1;
4398 spin_unlock(&tbl->slot_tbl_lock);
4399 dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
4400 tbl, tbl->slots, tbl->max_slots);
4401out:
4402 dprintk("<-- %s: return %d\n", __func__, ret);
4403 return ret;
4404}
4405
4406/*
4407 * Reset the forechannel and backchannel slot tables
4408 */
4409static int nfs4_reset_slot_tables(struct nfs4_session *session)
4410{
4411 int status;
4412
4413 status = nfs4_reset_slot_table(&session->fc_slot_table,
4414 session->fc_attrs.max_reqs,
4415 session->fc_slot_table.max_slots,
4416 1);
4417 if (status)
4418 return status;
4419
4420 status = nfs4_reset_slot_table(&session->bc_slot_table,
4421 session->bc_attrs.max_reqs,
4422 session->bc_slot_table.max_slots,
4423 0);
4424 return status;
4425}
4426
4427/* Destroy the slot table */
4428static void nfs4_destroy_slot_tables(struct nfs4_session *session)
4429{
4430 if (session->fc_slot_table.slots != NULL) {
4431 kfree(session->fc_slot_table.slots);
4432 session->fc_slot_table.slots = NULL;
4433 }
4434 if (session->bc_slot_table.slots != NULL) {
4435 kfree(session->bc_slot_table.slots);
4436 session->bc_slot_table.slots = NULL;
4437 }
4438 return;
4439}
4440
4441/*
4442 * Initialize slot table
4443 */
4444static int nfs4_init_slot_table(struct nfs4_slot_table *tbl,
4445 int max_slots, int ivalue)
4446{
4447 int i;
4448 struct nfs4_slot *slot;
4449 int ret = -ENOMEM;
4450
4451 BUG_ON(max_slots > NFS4_MAX_SLOT_TABLE);
4452
4453 dprintk("--> %s: max_reqs=%u\n", __func__, max_slots);
4454
4455 slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_KERNEL);
4456 if (!slot)
4457 goto out;
4458 for (i = 0; i < max_slots; ++i)
4459 slot[i].seq_nr = ivalue;
4460 ret = 0;
4461
4462 spin_lock(&tbl->slot_tbl_lock);
4463 if (tbl->slots != NULL) {
4464 spin_unlock(&tbl->slot_tbl_lock);
4465 dprintk("%s: slot table already initialized. tbl=%p slots=%p\n",
4466 __func__, tbl, tbl->slots);
4467 WARN_ON(1);
4468 goto out_free;
4469 }
4470 tbl->max_slots = max_slots;
4471 tbl->slots = slot;
4472 tbl->highest_used_slotid = -1; /* no slot is currently used */
4473 spin_unlock(&tbl->slot_tbl_lock);
4474 dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
4475 tbl, tbl->slots, tbl->max_slots);
4476out:
4477 dprintk("<-- %s: return %d\n", __func__, ret);
4478 return ret;
4479
4480out_free:
4481 kfree(slot);
4482 goto out;
4483}
4484
4485/*
4486 * Initialize the forechannel and backchannel tables
4487 */
4488static int nfs4_init_slot_tables(struct nfs4_session *session)
4489{
4490 int status;
4491
4492 status = nfs4_init_slot_table(&session->fc_slot_table,
4493 session->fc_attrs.max_reqs, 1);
4494 if (status)
4495 return status;
4496
4497 status = nfs4_init_slot_table(&session->bc_slot_table,
4498 session->bc_attrs.max_reqs, 0);
4499 if (status)
4500 nfs4_destroy_slot_tables(session);
4501
4502 return status;
4503}
4504
4505struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
4506{
4507 struct nfs4_session *session;
4508 struct nfs4_slot_table *tbl;
4509
4510 session = kzalloc(sizeof(struct nfs4_session), GFP_KERNEL);
4511 if (!session)
4512 return NULL;
4513
4514 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
4515 /*
4516 * The create session reply races with the server back
4517 * channel probe. Mark the client NFS_CS_SESSION_INITING
4518 * so that the client back channel can find the
4519 * nfs_client struct
4520 */
4521 clp->cl_cons_state = NFS_CS_SESSION_INITING;
4522
4523 tbl = &session->fc_slot_table;
4524 spin_lock_init(&tbl->slot_tbl_lock);
4525 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
4526
4527 tbl = &session->bc_slot_table;
4528 spin_lock_init(&tbl->slot_tbl_lock);
4529 rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table");
4530
4531 session->clp = clp;
4532 return session;
4533}
4534
4535void nfs4_destroy_session(struct nfs4_session *session)
4536{
4537 nfs4_proc_destroy_session(session);
4538 dprintk("%s Destroy backchannel for xprt %p\n",
4539 __func__, session->clp->cl_rpcclient->cl_xprt);
4540 xprt_destroy_backchannel(session->clp->cl_rpcclient->cl_xprt,
4541 NFS41_BC_MIN_CALLBACKS);
4542 nfs4_destroy_slot_tables(session);
4543 kfree(session);
4544}
4545
4546/*
4547 * Initialize the values to be used by the client in CREATE_SESSION
4548 * If nfs4_init_session set the fore channel request and response sizes,
4549 * use them.
4550 *
4551 * Set the back channel max_resp_sz_cached to zero to force the client to
4552 * always set csa_cachethis to FALSE because the current implementation
4553 * of the back channel DRC only supports caching the CB_SEQUENCE operation.
4554 */
4555static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
4556{
4557 struct nfs4_session *session = args->client->cl_session;
4558 unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz,
4559 mxresp_sz = session->fc_attrs.max_resp_sz;
4560
4561 if (mxrqst_sz == 0)
4562 mxrqst_sz = NFS_MAX_FILE_IO_SIZE;
4563 if (mxresp_sz == 0)
4564 mxresp_sz = NFS_MAX_FILE_IO_SIZE;
4565 /* Fore channel attributes */
4566 args->fc_attrs.headerpadsz = 0;
4567 args->fc_attrs.max_rqst_sz = mxrqst_sz;
4568 args->fc_attrs.max_resp_sz = mxresp_sz;
4569 args->fc_attrs.max_resp_sz_cached = mxresp_sz;
4570 args->fc_attrs.max_ops = NFS4_MAX_OPS;
4571 args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs;
4572
4573 dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
4574 "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
4575 __func__,
4576 args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
4577 args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops,
4578 args->fc_attrs.max_reqs);
4579
4580 /* Back channel attributes */
4581 args->bc_attrs.headerpadsz = 0;
4582 args->bc_attrs.max_rqst_sz = PAGE_SIZE;
4583 args->bc_attrs.max_resp_sz = PAGE_SIZE;
4584 args->bc_attrs.max_resp_sz_cached = 0;
4585 args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS;
4586 args->bc_attrs.max_reqs = 1;
4587
4588 dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u "
4589 "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
4590 __func__,
4591 args->bc_attrs.max_rqst_sz, args->bc_attrs.max_resp_sz,
4592 args->bc_attrs.max_resp_sz_cached, args->bc_attrs.max_ops,
4593 args->bc_attrs.max_reqs);
4594}
4595
4596static int _verify_channel_attr(char *chan, char *attr_name, u32 sent, u32 rcvd)
4597{
4598 if (rcvd <= sent)
4599 return 0;
4600 printk(KERN_WARNING "%s: Session INVALID: %s channel %s increased. "
4601 "sent=%u rcvd=%u\n", __func__, chan, attr_name, sent, rcvd);
4602 return -EINVAL;
4603}
4604
4605#define _verify_fore_channel_attr(_name_) \
4606 _verify_channel_attr("fore", #_name_, \
4607 args->fc_attrs._name_, \
4608 session->fc_attrs._name_)
4609
4610#define _verify_back_channel_attr(_name_) \
4611 _verify_channel_attr("back", #_name_, \
4612 args->bc_attrs._name_, \
4613 session->bc_attrs._name_)
4614
4615/*
4616 * The server is not allowed to increase the fore channel header pad size,
4617 * maximum response size, or maximum number of operations.
4618 *
4619 * The back channel attributes are only negotiatied down: We send what the
4620 * (back channel) server insists upon.
4621 */
4622static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
4623 struct nfs4_session *session)
4624{
4625 int ret = 0;
4626
4627 ret |= _verify_fore_channel_attr(headerpadsz);
4628 ret |= _verify_fore_channel_attr(max_resp_sz);
4629 ret |= _verify_fore_channel_attr(max_ops);
4630
4631 ret |= _verify_back_channel_attr(headerpadsz);
4632 ret |= _verify_back_channel_attr(max_rqst_sz);
4633 ret |= _verify_back_channel_attr(max_resp_sz);
4634 ret |= _verify_back_channel_attr(max_resp_sz_cached);
4635 ret |= _verify_back_channel_attr(max_ops);
4636 ret |= _verify_back_channel_attr(max_reqs);
4637
4638 return ret;
4639}
4640
4641static int _nfs4_proc_create_session(struct nfs_client *clp)
4642{
4643 struct nfs4_session *session = clp->cl_session;
4644 struct nfs41_create_session_args args = {
4645 .client = clp,
4646 .cb_program = NFS4_CALLBACK,
4647 };
4648 struct nfs41_create_session_res res = {
4649 .client = clp,
4650 };
4651 struct rpc_message msg = {
4652 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
4653 .rpc_argp = &args,
4654 .rpc_resp = &res,
4655 };
4656 int status;
4657
4658 nfs4_init_channel_attrs(&args);
4659 args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
4660
4661 status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
4662
4663 if (!status)
4664 /* Verify the session's negotiated channel_attrs values */
4665 status = nfs4_verify_channel_attrs(&args, session);
4666 if (!status) {
4667 /* Increment the clientid slot sequence id */
4668 clp->cl_seqid++;
4669 }
4670
4671 return status;
4672}
4673
4674/*
4675 * Issues a CREATE_SESSION operation to the server.
4676 * It is the responsibility of the caller to verify the session is
4677 * expired before calling this routine.
4678 */
4679int nfs4_proc_create_session(struct nfs_client *clp, int reset)
4680{
4681 int status;
4682 unsigned *ptr;
4683 struct nfs_fsinfo fsinfo;
4684 struct nfs4_session *session = clp->cl_session;
4685
4686 dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
4687
4688 status = _nfs4_proc_create_session(clp);
4689 if (status)
4690 goto out;
4691
4692 /* Init or reset the fore channel */
4693 if (reset)
4694 status = nfs4_reset_slot_tables(session);
4695 else
4696 status = nfs4_init_slot_tables(session);
4697 dprintk("fore channel slot table initialization returned %d\n", status);
4698 if (status)
4699 goto out;
4700
4701 ptr = (unsigned *)&session->sess_id.data[0];
4702 dprintk("%s client>seqid %d sessionid %u:%u:%u:%u\n", __func__,
4703 clp->cl_seqid, ptr[0], ptr[1], ptr[2], ptr[3]);
4704
4705 if (reset)
4706 /* Lease time is aleady set */
4707 goto out;
4708
4709 /* Get the lease time */
4710 status = nfs4_proc_get_lease_time(clp, &fsinfo);
4711 if (status == 0) {
4712 /* Update lease time and schedule renewal */
4713 spin_lock(&clp->cl_lock);
4714 clp->cl_lease_time = fsinfo.lease_time * HZ;
4715 clp->cl_last_renewal = jiffies;
4716 clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
4717 spin_unlock(&clp->cl_lock);
4718
4719 nfs4_schedule_state_renewal(clp);
4720 }
4721out:
4722 dprintk("<-- %s\n", __func__);
4723 return status;
4724}
4725
4726/*
4727 * Issue the over-the-wire RPC DESTROY_SESSION.
4728 * The caller must serialize access to this routine.
4729 */
4730int nfs4_proc_destroy_session(struct nfs4_session *session)
4731{
4732 int status = 0;
4733 struct rpc_message msg;
4734
4735 dprintk("--> nfs4_proc_destroy_session\n");
4736
4737 /* session is still being setup */
4738 if (session->clp->cl_cons_state != NFS_CS_READY)
4739 return status;
4740
4741 msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION];
4742 msg.rpc_argp = session;
4743 msg.rpc_resp = NULL;
4744 msg.rpc_cred = NULL;
4745 status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
4746
4747 if (status)
4748 printk(KERN_WARNING
4749 "Got error %d from the server on DESTROY_SESSION. "
4750 "Session has been destroyed regardless...\n", status);
4751
4752 dprintk("<-- nfs4_proc_destroy_session\n");
4753 return status;
4754}
4755
4756/*
4757 * Renew the cl_session lease.
4758 */
4759static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
4760{
4761 struct nfs4_sequence_args args;
4762 struct nfs4_sequence_res res;
4763
4764 struct rpc_message msg = {
4765 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE],
4766 .rpc_argp = &args,
4767 .rpc_resp = &res,
4768 .rpc_cred = cred,
4769 };
4770
4771 args.sa_cache_this = 0;
4772
4773 return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args,
4774 &res, 0);
4775}
4776
4777void nfs41_sequence_call_done(struct rpc_task *task, void *data)
4778{
4779 struct nfs_client *clp = (struct nfs_client *)data;
4780
4781 nfs41_sequence_done(clp, task->tk_msg.rpc_resp, task->tk_status);
4782
4783 if (task->tk_status < 0) {
4784 dprintk("%s ERROR %d\n", __func__, task->tk_status);
4785
4786 if (_nfs4_async_handle_error(task, NULL, clp, NULL)
4787 == -EAGAIN) {
4788 nfs4_restart_rpc(task, clp);
4789 return;
4790 }
4791 }
4792 nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp);
4793 dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
4794
4795 put_rpccred(task->tk_msg.rpc_cred);
4796 kfree(task->tk_msg.rpc_argp);
4797 kfree(task->tk_msg.rpc_resp);
4798
4799 dprintk("<-- %s\n", __func__);
4800}
4801
4802static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
4803{
4804 struct nfs_client *clp;
4805 struct nfs4_sequence_args *args;
4806 struct nfs4_sequence_res *res;
4807
4808 clp = (struct nfs_client *)data;
4809 args = task->tk_msg.rpc_argp;
4810 res = task->tk_msg.rpc_resp;
4811
4812 if (nfs4_setup_sequence(clp, args, res, 0, task))
4813 return;
4814 rpc_call_start(task);
4815}
4816
4817static const struct rpc_call_ops nfs41_sequence_ops = {
4818 .rpc_call_done = nfs41_sequence_call_done,
4819 .rpc_call_prepare = nfs41_sequence_prepare,
4820};
4821
4822static int nfs41_proc_async_sequence(struct nfs_client *clp,
4823 struct rpc_cred *cred)
4824{
4825 struct nfs4_sequence_args *args;
4826 struct nfs4_sequence_res *res;
4827 struct rpc_message msg = {
4828 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE],
4829 .rpc_cred = cred,
4830 };
4831
4832 args = kzalloc(sizeof(*args), GFP_KERNEL);
4833 if (!args)
4834 return -ENOMEM;
4835 res = kzalloc(sizeof(*res), GFP_KERNEL);
4836 if (!res) {
4837 kfree(args);
4838 return -ENOMEM;
4839 }
4840 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
4841 msg.rpc_argp = args;
4842 msg.rpc_resp = res;
4843
4844 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
4845 &nfs41_sequence_ops, (void *)clp);
4846}
4847
4848#endif /* CONFIG_NFS_V4_1 */
4849
4850struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
3727 .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, 4851 .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
3728 .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, 4852 .state_flag_bit = NFS_STATE_RECLAIM_REBOOT,
3729 .recover_open = nfs4_open_reclaim, 4853 .recover_open = nfs4_open_reclaim,
3730 .recover_lock = nfs4_lock_reclaim, 4854 .recover_lock = nfs4_lock_reclaim,
4855 .establish_clid = nfs4_init_clientid,
4856 .get_clid_cred = nfs4_get_setclientid_cred,
3731}; 4857};
3732 4858
3733struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops = { 4859#if defined(CONFIG_NFS_V4_1)
4860struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
4861 .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
4862 .state_flag_bit = NFS_STATE_RECLAIM_REBOOT,
4863 .recover_open = nfs4_open_reclaim,
4864 .recover_lock = nfs4_lock_reclaim,
4865 .establish_clid = nfs4_proc_exchange_id,
4866 .get_clid_cred = nfs4_get_exchange_id_cred,
4867};
4868#endif /* CONFIG_NFS_V4_1 */
4869
4870struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
3734 .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, 4871 .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
3735 .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, 4872 .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
3736 .recover_open = nfs4_open_expired, 4873 .recover_open = nfs4_open_expired,
3737 .recover_lock = nfs4_lock_expired, 4874 .recover_lock = nfs4_lock_expired,
4875 .establish_clid = nfs4_init_clientid,
4876 .get_clid_cred = nfs4_get_setclientid_cred,
4877};
4878
4879#if defined(CONFIG_NFS_V4_1)
4880struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = {
4881 .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
4882 .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
4883 .recover_open = nfs4_open_expired,
4884 .recover_lock = nfs4_lock_expired,
4885 .establish_clid = nfs4_proc_exchange_id,
4886 .get_clid_cred = nfs4_get_exchange_id_cred,
4887};
4888#endif /* CONFIG_NFS_V4_1 */
4889
4890struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
4891 .sched_state_renewal = nfs4_proc_async_renew,
4892 .get_state_renewal_cred_locked = nfs4_get_renew_cred_locked,
4893 .renew_lease = nfs4_proc_renew,
4894};
4895
4896#if defined(CONFIG_NFS_V4_1)
4897struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
4898 .sched_state_renewal = nfs41_proc_async_sequence,
4899 .get_state_renewal_cred_locked = nfs4_get_machine_cred_locked,
4900 .renew_lease = nfs4_proc_sequence,
4901};
4902#endif
4903
4904/*
4905 * Per minor version reboot and network partition recovery ops
4906 */
4907
4908struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[] = {
4909 &nfs40_reboot_recovery_ops,
4910#if defined(CONFIG_NFS_V4_1)
4911 &nfs41_reboot_recovery_ops,
4912#endif
4913};
4914
4915struct nfs4_state_recovery_ops *nfs4_nograce_recovery_ops[] = {
4916 &nfs40_nograce_recovery_ops,
4917#if defined(CONFIG_NFS_V4_1)
4918 &nfs41_nograce_recovery_ops,
4919#endif
4920};
4921
4922struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[] = {
4923 &nfs40_state_renewal_ops,
4924#if defined(CONFIG_NFS_V4_1)
4925 &nfs41_state_renewal_ops,
4926#endif
3738}; 4927};
3739 4928
3740static const struct inode_operations nfs4_file_inode_operations = { 4929static const struct inode_operations nfs4_file_inode_operations = {
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index f524e932ff7b..e27c6cef18f2 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -59,12 +59,14 @@
59void 59void
60nfs4_renew_state(struct work_struct *work) 60nfs4_renew_state(struct work_struct *work)
61{ 61{
62 struct nfs4_state_maintenance_ops *ops;
62 struct nfs_client *clp = 63 struct nfs_client *clp =
63 container_of(work, struct nfs_client, cl_renewd.work); 64 container_of(work, struct nfs_client, cl_renewd.work);
64 struct rpc_cred *cred; 65 struct rpc_cred *cred;
65 long lease, timeout; 66 long lease, timeout;
66 unsigned long last, now; 67 unsigned long last, now;
67 68
69 ops = nfs4_state_renewal_ops[clp->cl_minorversion];
68 dprintk("%s: start\n", __func__); 70 dprintk("%s: start\n", __func__);
69 /* Are there any active superblocks? */ 71 /* Are there any active superblocks? */
70 if (list_empty(&clp->cl_superblocks)) 72 if (list_empty(&clp->cl_superblocks))
@@ -76,7 +78,7 @@ nfs4_renew_state(struct work_struct *work)
76 timeout = (2 * lease) / 3 + (long)last - (long)now; 78 timeout = (2 * lease) / 3 + (long)last - (long)now;
77 /* Are we close to a lease timeout? */ 79 /* Are we close to a lease timeout? */
78 if (time_after(now, last + lease/3)) { 80 if (time_after(now, last + lease/3)) {
79 cred = nfs4_get_renew_cred_locked(clp); 81 cred = ops->get_state_renewal_cred_locked(clp);
80 spin_unlock(&clp->cl_lock); 82 spin_unlock(&clp->cl_lock);
81 if (cred == NULL) { 83 if (cred == NULL) {
82 if (list_empty(&clp->cl_delegations)) { 84 if (list_empty(&clp->cl_delegations)) {
@@ -86,7 +88,7 @@ nfs4_renew_state(struct work_struct *work)
86 nfs_expire_all_delegations(clp); 88 nfs_expire_all_delegations(clp);
87 } else { 89 } else {
88 /* Queue an asynchronous RENEW. */ 90 /* Queue an asynchronous RENEW. */
89 nfs4_proc_async_renew(clp, cred); 91 ops->sched_state_renewal(clp, cred);
90 put_rpccred(cred); 92 put_rpccred(cred);
91 } 93 }
92 timeout = (2 * lease) / 3; 94 timeout = (2 * lease) / 3;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 0298e909559f..2cfca9929c9a 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -60,7 +60,7 @@ const nfs4_stateid zero_stateid;
60 60
61static LIST_HEAD(nfs4_clientid_list); 61static LIST_HEAD(nfs4_clientid_list);
62 62
63static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred) 63int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
64{ 64{
65 unsigned short port; 65 unsigned short port;
66 int status; 66 int status;
@@ -77,7 +77,7 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
77 return status; 77 return status;
78} 78}
79 79
80static struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp) 80struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp)
81{ 81{
82 struct rpc_cred *cred = NULL; 82 struct rpc_cred *cred = NULL;
83 83
@@ -114,17 +114,21 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp)
114 return cred; 114 return cred;
115} 115}
116 116
117static struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp) 117#if defined(CONFIG_NFS_V4_1)
118
119struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp)
118{ 120{
119 struct rpc_cred *cred; 121 struct rpc_cred *cred;
120 122
121 spin_lock(&clp->cl_lock); 123 spin_lock(&clp->cl_lock);
122 cred = nfs4_get_renew_cred_locked(clp); 124 cred = nfs4_get_machine_cred_locked(clp);
123 spin_unlock(&clp->cl_lock); 125 spin_unlock(&clp->cl_lock);
124 return cred; 126 return cred;
125} 127}
126 128
127static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) 129#endif /* CONFIG_NFS_V4_1 */
130
131struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
128{ 132{
129 struct nfs4_state_owner *sp; 133 struct nfs4_state_owner *sp;
130 struct rb_node *pos; 134 struct rb_node *pos;
@@ -738,12 +742,14 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
738 742
739void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid) 743void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
740{ 744{
741 if (status == -NFS4ERR_BAD_SEQID) { 745 struct nfs4_state_owner *sp = container_of(seqid->sequence,
742 struct nfs4_state_owner *sp = container_of(seqid->sequence, 746 struct nfs4_state_owner, so_seqid);
743 struct nfs4_state_owner, so_seqid); 747 struct nfs_server *server = sp->so_server;
748
749 if (status == -NFS4ERR_BAD_SEQID)
744 nfs4_drop_state_owner(sp); 750 nfs4_drop_state_owner(sp);
745 } 751 if (!nfs4_has_session(server->nfs_client))
746 nfs_increment_seqid(status, seqid); 752 nfs_increment_seqid(status, seqid);
747} 753}
748 754
749/* 755/*
@@ -1042,6 +1048,14 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1042 case -NFS4ERR_EXPIRED: 1048 case -NFS4ERR_EXPIRED:
1043 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1049 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1044 nfs4_state_start_reclaim_nograce(clp); 1050 nfs4_state_start_reclaim_nograce(clp);
1051 case -NFS4ERR_BADSESSION:
1052 case -NFS4ERR_BADSLOT:
1053 case -NFS4ERR_BAD_HIGH_SLOT:
1054 case -NFS4ERR_DEADSESSION:
1055 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
1056 case -NFS4ERR_SEQ_FALSE_RETRY:
1057 case -NFS4ERR_SEQ_MISORDERED:
1058 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
1045 } 1059 }
1046} 1060}
1047 1061
@@ -1075,18 +1089,22 @@ restart:
1075static int nfs4_check_lease(struct nfs_client *clp) 1089static int nfs4_check_lease(struct nfs_client *clp)
1076{ 1090{
1077 struct rpc_cred *cred; 1091 struct rpc_cred *cred;
1092 struct nfs4_state_maintenance_ops *ops =
1093 nfs4_state_renewal_ops[clp->cl_minorversion];
1078 int status = -NFS4ERR_EXPIRED; 1094 int status = -NFS4ERR_EXPIRED;
1079 1095
1080 /* Is the client already known to have an expired lease? */ 1096 /* Is the client already known to have an expired lease? */
1081 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) 1097 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1082 return 0; 1098 return 0;
1083 cred = nfs4_get_renew_cred(clp); 1099 spin_lock(&clp->cl_lock);
1100 cred = ops->get_state_renewal_cred_locked(clp);
1101 spin_unlock(&clp->cl_lock);
1084 if (cred == NULL) { 1102 if (cred == NULL) {
1085 cred = nfs4_get_setclientid_cred(clp); 1103 cred = nfs4_get_setclientid_cred(clp);
1086 if (cred == NULL) 1104 if (cred == NULL)
1087 goto out; 1105 goto out;
1088 } 1106 }
1089 status = nfs4_proc_renew(clp, cred); 1107 status = ops->renew_lease(clp, cred);
1090 put_rpccred(cred); 1108 put_rpccred(cred);
1091out: 1109out:
1092 nfs4_recovery_handle_error(clp, status); 1110 nfs4_recovery_handle_error(clp, status);
@@ -1096,21 +1114,98 @@ out:
1096static int nfs4_reclaim_lease(struct nfs_client *clp) 1114static int nfs4_reclaim_lease(struct nfs_client *clp)
1097{ 1115{
1098 struct rpc_cred *cred; 1116 struct rpc_cred *cred;
1117 struct nfs4_state_recovery_ops *ops =
1118 nfs4_reboot_recovery_ops[clp->cl_minorversion];
1099 int status = -ENOENT; 1119 int status = -ENOENT;
1100 1120
1101 cred = nfs4_get_setclientid_cred(clp); 1121 cred = ops->get_clid_cred(clp);
1102 if (cred != NULL) { 1122 if (cred != NULL) {
1103 status = nfs4_init_client(clp, cred); 1123 status = ops->establish_clid(clp, cred);
1104 put_rpccred(cred); 1124 put_rpccred(cred);
1105 /* Handle case where the user hasn't set up machine creds */ 1125 /* Handle case where the user hasn't set up machine creds */
1106 if (status == -EACCES && cred == clp->cl_machine_cred) { 1126 if (status == -EACCES && cred == clp->cl_machine_cred) {
1107 nfs4_clear_machine_cred(clp); 1127 nfs4_clear_machine_cred(clp);
1108 status = -EAGAIN; 1128 status = -EAGAIN;
1109 } 1129 }
1130 if (status == -NFS4ERR_MINOR_VERS_MISMATCH)
1131 status = -EPROTONOSUPPORT;
1110 } 1132 }
1111 return status; 1133 return status;
1112} 1134}
1113 1135
1136#ifdef CONFIG_NFS_V4_1
1137static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err)
1138{
1139 switch (err) {
1140 case -NFS4ERR_STALE_CLIENTID:
1141 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1142 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
1143 }
1144}
1145
1146static int nfs4_reset_session(struct nfs_client *clp)
1147{
1148 int status;
1149
1150 status = nfs4_proc_destroy_session(clp->cl_session);
1151 if (status && status != -NFS4ERR_BADSESSION &&
1152 status != -NFS4ERR_DEADSESSION) {
1153 nfs4_session_recovery_handle_error(clp, status);
1154 goto out;
1155 }
1156
1157 memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN);
1158 status = nfs4_proc_create_session(clp, 1);
1159 if (status)
1160 nfs4_session_recovery_handle_error(clp, status);
1161 /* fall through*/
1162out:
1163 /* Wake up the next rpc task even on error */
1164 rpc_wake_up_next(&clp->cl_session->fc_slot_table.slot_tbl_waitq);
1165 return status;
1166}
1167
1168static int nfs4_initialize_session(struct nfs_client *clp)
1169{
1170 int status;
1171
1172 status = nfs4_proc_create_session(clp, 0);
1173 if (!status) {
1174 nfs_mark_client_ready(clp, NFS_CS_READY);
1175 } else if (status == -NFS4ERR_STALE_CLIENTID) {
1176 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1177 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
1178 } else {
1179 nfs_mark_client_ready(clp, status);
1180 }
1181 return status;
1182}
1183#else /* CONFIG_NFS_V4_1 */
1184static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
1185static int nfs4_initialize_session(struct nfs_client *clp) { return 0; }
1186#endif /* CONFIG_NFS_V4_1 */
1187
1188/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors
1189 * on EXCHANGE_ID for v4.1
1190 */
1191static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
1192{
1193 if (nfs4_has_session(clp)) {
1194 switch (status) {
1195 case -NFS4ERR_DELAY:
1196 case -NFS4ERR_CLID_INUSE:
1197 case -EAGAIN:
1198 break;
1199
1200 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
1201 * in nfs4_exchange_id */
1202 default:
1203 return;
1204 }
1205 }
1206 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1207}
1208
1114static void nfs4_state_manager(struct nfs_client *clp) 1209static void nfs4_state_manager(struct nfs_client *clp)
1115{ 1210{
1116 int status = 0; 1211 int status = 0;
@@ -1121,9 +1216,12 @@ static void nfs4_state_manager(struct nfs_client *clp)
1121 /* We're going to have to re-establish a clientid */ 1216 /* We're going to have to re-establish a clientid */
1122 status = nfs4_reclaim_lease(clp); 1217 status = nfs4_reclaim_lease(clp);
1123 if (status) { 1218 if (status) {
1124 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1219 nfs4_set_lease_expired(clp, status);
1125 if (status == -EAGAIN) 1220 if (status == -EAGAIN)
1126 continue; 1221 continue;
1222 if (clp->cl_cons_state ==
1223 NFS_CS_SESSION_INITING)
1224 nfs_mark_client_ready(clp, status);
1127 goto out_error; 1225 goto out_error;
1128 } 1226 }
1129 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); 1227 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
@@ -1134,25 +1232,44 @@ static void nfs4_state_manager(struct nfs_client *clp)
1134 if (status != 0) 1232 if (status != 0)
1135 continue; 1233 continue;
1136 } 1234 }
1137 1235 /* Initialize or reset the session */
1236 if (nfs4_has_session(clp) &&
1237 test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) {
1238 if (clp->cl_cons_state == NFS_CS_SESSION_INITING)
1239 status = nfs4_initialize_session(clp);
1240 else
1241 status = nfs4_reset_session(clp);
1242 if (status) {
1243 if (status == -NFS4ERR_STALE_CLIENTID)
1244 continue;
1245 goto out_error;
1246 }
1247 }
1138 /* First recover reboot state... */ 1248 /* First recover reboot state... */
1139 if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { 1249 if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
1140 status = nfs4_do_reclaim(clp, &nfs4_reboot_recovery_ops); 1250 status = nfs4_do_reclaim(clp,
1251 nfs4_reboot_recovery_ops[clp->cl_minorversion]);
1141 if (status == -NFS4ERR_STALE_CLIENTID) 1252 if (status == -NFS4ERR_STALE_CLIENTID)
1142 continue; 1253 continue;
1254 if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
1255 continue;
1143 nfs4_state_end_reclaim_reboot(clp); 1256 nfs4_state_end_reclaim_reboot(clp);
1144 continue; 1257 continue;
1145 } 1258 }
1146 1259
1147 /* Now recover expired state... */ 1260 /* Now recover expired state... */
1148 if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { 1261 if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
1149 status = nfs4_do_reclaim(clp, &nfs4_nograce_recovery_ops); 1262 status = nfs4_do_reclaim(clp,
1263 nfs4_nograce_recovery_ops[clp->cl_minorversion]);
1150 if (status < 0) { 1264 if (status < 0) {
1151 set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); 1265 set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
1152 if (status == -NFS4ERR_STALE_CLIENTID) 1266 if (status == -NFS4ERR_STALE_CLIENTID)
1153 continue; 1267 continue;
1154 if (status == -NFS4ERR_EXPIRED) 1268 if (status == -NFS4ERR_EXPIRED)
1155 continue; 1269 continue;
1270 if (test_bit(NFS4CLNT_SESSION_SETUP,
1271 &clp->cl_state))
1272 continue;
1156 goto out_error; 1273 goto out_error;
1157 } else 1274 } else
1158 nfs4_state_end_reclaim_nograce(clp); 1275 nfs4_state_end_reclaim_nograce(clp);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1690f0e44b91..617273e7d47f 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -192,12 +192,16 @@ static int nfs4_stat_to_errno(int);
192 decode_verifier_maxsz) 192 decode_verifier_maxsz)
193#define encode_remove_maxsz (op_encode_hdr_maxsz + \ 193#define encode_remove_maxsz (op_encode_hdr_maxsz + \
194 nfs4_name_maxsz) 194 nfs4_name_maxsz)
195#define decode_remove_maxsz (op_decode_hdr_maxsz + \
196 decode_change_info_maxsz)
195#define encode_rename_maxsz (op_encode_hdr_maxsz + \ 197#define encode_rename_maxsz (op_encode_hdr_maxsz + \
196 2 * nfs4_name_maxsz) 198 2 * nfs4_name_maxsz)
197#define decode_rename_maxsz (op_decode_hdr_maxsz + 5 + 5) 199#define decode_rename_maxsz (op_decode_hdr_maxsz + \
200 decode_change_info_maxsz + \
201 decode_change_info_maxsz)
198#define encode_link_maxsz (op_encode_hdr_maxsz + \ 202#define encode_link_maxsz (op_encode_hdr_maxsz + \
199 nfs4_name_maxsz) 203 nfs4_name_maxsz)
200#define decode_link_maxsz (op_decode_hdr_maxsz + 5) 204#define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
201#define encode_lock_maxsz (op_encode_hdr_maxsz + \ 205#define encode_lock_maxsz (op_encode_hdr_maxsz + \
202 7 + \ 206 7 + \
203 1 + encode_stateid_maxsz + 8) 207 1 + encode_stateid_maxsz + 8)
@@ -240,43 +244,115 @@ static int nfs4_stat_to_errno(int);
240 (encode_getattr_maxsz) 244 (encode_getattr_maxsz)
241#define decode_fs_locations_maxsz \ 245#define decode_fs_locations_maxsz \
242 (0) 246 (0)
247
248#if defined(CONFIG_NFS_V4_1)
249#define NFS4_MAX_MACHINE_NAME_LEN (64)
250
251#define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
252 encode_verifier_maxsz + \
253 1 /* co_ownerid.len */ + \
254 XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \
255 1 /* flags */ + \
256 1 /* spa_how */ + \
257 0 /* SP4_NONE (for now) */ + \
258 1 /* zero implemetation id array */)
259#define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
260 2 /* eir_clientid */ + \
261 1 /* eir_sequenceid */ + \
262 1 /* eir_flags */ + \
263 1 /* spr_how */ + \
264 0 /* SP4_NONE (for now) */ + \
265 2 /* eir_server_owner.so_minor_id */ + \
266 /* eir_server_owner.so_major_id<> */ \
267 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
268 /* eir_server_scope<> */ \
269 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
270 1 /* eir_server_impl_id array length */ + \
271 0 /* ignored eir_server_impl_id contents */)
272#define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */)
273#define decode_channel_attrs_maxsz (6 + \
274 1 /* ca_rdma_ird.len */ + \
275 1 /* ca_rdma_ird */)
276#define encode_create_session_maxsz (op_encode_hdr_maxsz + \
277 2 /* csa_clientid */ + \
278 1 /* csa_sequence */ + \
279 1 /* csa_flags */ + \
280 encode_channel_attrs_maxsz + \
281 encode_channel_attrs_maxsz + \
282 1 /* csa_cb_program */ + \
283 1 /* csa_sec_parms.len (1) */ + \
284 1 /* cb_secflavor (AUTH_SYS) */ + \
285 1 /* stamp */ + \
286 1 /* machinename.len */ + \
287 XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \
288 1 /* uid */ + \
289 1 /* gid */ + \
290 1 /* gids.len (0) */)
291#define decode_create_session_maxsz (op_decode_hdr_maxsz + \
292 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
293 1 /* csr_sequence */ + \
294 1 /* csr_flags */ + \
295 decode_channel_attrs_maxsz + \
296 decode_channel_attrs_maxsz)
297#define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4)
298#define decode_destroy_session_maxsz (op_decode_hdr_maxsz)
299#define encode_sequence_maxsz (op_encode_hdr_maxsz + \
300 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
301#define decode_sequence_maxsz (op_decode_hdr_maxsz + \
302 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
303#else /* CONFIG_NFS_V4_1 */
304#define encode_sequence_maxsz 0
305#define decode_sequence_maxsz 0
306#endif /* CONFIG_NFS_V4_1 */
307
243#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ 308#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
244#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ 309#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
245#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ 310#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
311 encode_sequence_maxsz + \
246 encode_putfh_maxsz + \ 312 encode_putfh_maxsz + \
247 encode_read_maxsz) 313 encode_read_maxsz)
248#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ 314#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
315 decode_sequence_maxsz + \
249 decode_putfh_maxsz + \ 316 decode_putfh_maxsz + \
250 decode_read_maxsz) 317 decode_read_maxsz)
251#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ 318#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
319 encode_sequence_maxsz + \
252 encode_putfh_maxsz + \ 320 encode_putfh_maxsz + \
253 encode_readlink_maxsz) 321 encode_readlink_maxsz)
254#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ 322#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
323 decode_sequence_maxsz + \
255 decode_putfh_maxsz + \ 324 decode_putfh_maxsz + \
256 decode_readlink_maxsz) 325 decode_readlink_maxsz)
257#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ 326#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
327 encode_sequence_maxsz + \
258 encode_putfh_maxsz + \ 328 encode_putfh_maxsz + \
259 encode_readdir_maxsz) 329 encode_readdir_maxsz)
260#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ 330#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
331 decode_sequence_maxsz + \
261 decode_putfh_maxsz + \ 332 decode_putfh_maxsz + \
262 decode_readdir_maxsz) 333 decode_readdir_maxsz)
263#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ 334#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
335 encode_sequence_maxsz + \
264 encode_putfh_maxsz + \ 336 encode_putfh_maxsz + \
265 encode_write_maxsz + \ 337 encode_write_maxsz + \
266 encode_getattr_maxsz) 338 encode_getattr_maxsz)
267#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ 339#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
340 decode_sequence_maxsz + \
268 decode_putfh_maxsz + \ 341 decode_putfh_maxsz + \
269 decode_write_maxsz + \ 342 decode_write_maxsz + \
270 decode_getattr_maxsz) 343 decode_getattr_maxsz)
271#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ 344#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
345 encode_sequence_maxsz + \
272 encode_putfh_maxsz + \ 346 encode_putfh_maxsz + \
273 encode_commit_maxsz + \ 347 encode_commit_maxsz + \
274 encode_getattr_maxsz) 348 encode_getattr_maxsz)
275#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ 349#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
350 decode_sequence_maxsz + \
276 decode_putfh_maxsz + \ 351 decode_putfh_maxsz + \
277 decode_commit_maxsz + \ 352 decode_commit_maxsz + \
278 decode_getattr_maxsz) 353 decode_getattr_maxsz)
279#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ 354#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
355 encode_sequence_maxsz + \
280 encode_putfh_maxsz + \ 356 encode_putfh_maxsz + \
281 encode_savefh_maxsz + \ 357 encode_savefh_maxsz + \
282 encode_open_maxsz + \ 358 encode_open_maxsz + \
@@ -285,6 +361,7 @@ static int nfs4_stat_to_errno(int);
285 encode_restorefh_maxsz + \ 361 encode_restorefh_maxsz + \
286 encode_getattr_maxsz) 362 encode_getattr_maxsz)
287#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ 363#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
364 decode_sequence_maxsz + \
288 decode_putfh_maxsz + \ 365 decode_putfh_maxsz + \
289 decode_savefh_maxsz + \ 366 decode_savefh_maxsz + \
290 decode_open_maxsz + \ 367 decode_open_maxsz + \
@@ -301,43 +378,53 @@ static int nfs4_stat_to_errno(int);
301 decode_putfh_maxsz + \ 378 decode_putfh_maxsz + \
302 decode_open_confirm_maxsz) 379 decode_open_confirm_maxsz)
303#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ 380#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
381 encode_sequence_maxsz + \
304 encode_putfh_maxsz + \ 382 encode_putfh_maxsz + \
305 encode_open_maxsz + \ 383 encode_open_maxsz + \
306 encode_getattr_maxsz) 384 encode_getattr_maxsz)
307#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ 385#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
386 decode_sequence_maxsz + \
308 decode_putfh_maxsz + \ 387 decode_putfh_maxsz + \
309 decode_open_maxsz + \ 388 decode_open_maxsz + \
310 decode_getattr_maxsz) 389 decode_getattr_maxsz)
311#define NFS4_enc_open_downgrade_sz \ 390#define NFS4_enc_open_downgrade_sz \
312 (compound_encode_hdr_maxsz + \ 391 (compound_encode_hdr_maxsz + \
392 encode_sequence_maxsz + \
313 encode_putfh_maxsz + \ 393 encode_putfh_maxsz + \
314 encode_open_downgrade_maxsz + \ 394 encode_open_downgrade_maxsz + \
315 encode_getattr_maxsz) 395 encode_getattr_maxsz)
316#define NFS4_dec_open_downgrade_sz \ 396#define NFS4_dec_open_downgrade_sz \
317 (compound_decode_hdr_maxsz + \ 397 (compound_decode_hdr_maxsz + \
398 decode_sequence_maxsz + \
318 decode_putfh_maxsz + \ 399 decode_putfh_maxsz + \
319 decode_open_downgrade_maxsz + \ 400 decode_open_downgrade_maxsz + \
320 decode_getattr_maxsz) 401 decode_getattr_maxsz)
321#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ 402#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
403 encode_sequence_maxsz + \
322 encode_putfh_maxsz + \ 404 encode_putfh_maxsz + \
323 encode_close_maxsz + \ 405 encode_close_maxsz + \
324 encode_getattr_maxsz) 406 encode_getattr_maxsz)
325#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ 407#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
408 decode_sequence_maxsz + \
326 decode_putfh_maxsz + \ 409 decode_putfh_maxsz + \
327 decode_close_maxsz + \ 410 decode_close_maxsz + \
328 decode_getattr_maxsz) 411 decode_getattr_maxsz)
329#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ 412#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
413 encode_sequence_maxsz + \
330 encode_putfh_maxsz + \ 414 encode_putfh_maxsz + \
331 encode_setattr_maxsz + \ 415 encode_setattr_maxsz + \
332 encode_getattr_maxsz) 416 encode_getattr_maxsz)
333#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ 417#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
418 decode_sequence_maxsz + \
334 decode_putfh_maxsz + \ 419 decode_putfh_maxsz + \
335 decode_setattr_maxsz + \ 420 decode_setattr_maxsz + \
336 decode_getattr_maxsz) 421 decode_getattr_maxsz)
337#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ 422#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
423 encode_sequence_maxsz + \
338 encode_putfh_maxsz + \ 424 encode_putfh_maxsz + \
339 encode_fsinfo_maxsz) 425 encode_fsinfo_maxsz)
340#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ 426#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
427 decode_sequence_maxsz + \
341 decode_putfh_maxsz + \ 428 decode_putfh_maxsz + \
342 decode_fsinfo_maxsz) 429 decode_fsinfo_maxsz)
343#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \ 430#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
@@ -359,64 +446,81 @@ static int nfs4_stat_to_errno(int);
359 decode_putrootfh_maxsz + \ 446 decode_putrootfh_maxsz + \
360 decode_fsinfo_maxsz) 447 decode_fsinfo_maxsz)
361#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ 448#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
449 encode_sequence_maxsz + \
362 encode_putfh_maxsz + \ 450 encode_putfh_maxsz + \
363 encode_lock_maxsz) 451 encode_lock_maxsz)
364#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ 452#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
453 decode_sequence_maxsz + \
365 decode_putfh_maxsz + \ 454 decode_putfh_maxsz + \
366 decode_lock_maxsz) 455 decode_lock_maxsz)
367#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ 456#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
457 encode_sequence_maxsz + \
368 encode_putfh_maxsz + \ 458 encode_putfh_maxsz + \
369 encode_lockt_maxsz) 459 encode_lockt_maxsz)
370#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ 460#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
461 decode_sequence_maxsz + \
371 decode_putfh_maxsz + \ 462 decode_putfh_maxsz + \
372 decode_lockt_maxsz) 463 decode_lockt_maxsz)
373#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ 464#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
465 encode_sequence_maxsz + \
374 encode_putfh_maxsz + \ 466 encode_putfh_maxsz + \
375 encode_locku_maxsz) 467 encode_locku_maxsz)
376#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ 468#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
469 decode_sequence_maxsz + \
377 decode_putfh_maxsz + \ 470 decode_putfh_maxsz + \
378 decode_locku_maxsz) 471 decode_locku_maxsz)
379#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ 472#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
473 encode_sequence_maxsz + \
380 encode_putfh_maxsz + \ 474 encode_putfh_maxsz + \
381 encode_access_maxsz + \ 475 encode_access_maxsz + \
382 encode_getattr_maxsz) 476 encode_getattr_maxsz)
383#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ 477#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
478 decode_sequence_maxsz + \
384 decode_putfh_maxsz + \ 479 decode_putfh_maxsz + \
385 decode_access_maxsz + \ 480 decode_access_maxsz + \
386 decode_getattr_maxsz) 481 decode_getattr_maxsz)
387#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ 482#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
483 encode_sequence_maxsz + \
388 encode_putfh_maxsz + \ 484 encode_putfh_maxsz + \
389 encode_getattr_maxsz) 485 encode_getattr_maxsz)
390#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ 486#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
487 decode_sequence_maxsz + \
391 decode_putfh_maxsz + \ 488 decode_putfh_maxsz + \
392 decode_getattr_maxsz) 489 decode_getattr_maxsz)
393#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ 490#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
491 encode_sequence_maxsz + \
394 encode_putfh_maxsz + \ 492 encode_putfh_maxsz + \
395 encode_lookup_maxsz + \ 493 encode_lookup_maxsz + \
396 encode_getattr_maxsz + \ 494 encode_getattr_maxsz + \
397 encode_getfh_maxsz) 495 encode_getfh_maxsz)
398#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ 496#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
497 decode_sequence_maxsz + \
399 decode_putfh_maxsz + \ 498 decode_putfh_maxsz + \
400 decode_lookup_maxsz + \ 499 decode_lookup_maxsz + \
401 decode_getattr_maxsz + \ 500 decode_getattr_maxsz + \
402 decode_getfh_maxsz) 501 decode_getfh_maxsz)
403#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ 502#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
503 encode_sequence_maxsz + \
404 encode_putrootfh_maxsz + \ 504 encode_putrootfh_maxsz + \
405 encode_getattr_maxsz + \ 505 encode_getattr_maxsz + \
406 encode_getfh_maxsz) 506 encode_getfh_maxsz)
407#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ 507#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
508 decode_sequence_maxsz + \
408 decode_putrootfh_maxsz + \ 509 decode_putrootfh_maxsz + \
409 decode_getattr_maxsz + \ 510 decode_getattr_maxsz + \
410 decode_getfh_maxsz) 511 decode_getfh_maxsz)
411#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ 512#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
513 encode_sequence_maxsz + \
412 encode_putfh_maxsz + \ 514 encode_putfh_maxsz + \
413 encode_remove_maxsz + \ 515 encode_remove_maxsz + \
414 encode_getattr_maxsz) 516 encode_getattr_maxsz)
415#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ 517#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
518 decode_sequence_maxsz + \
416 decode_putfh_maxsz + \ 519 decode_putfh_maxsz + \
417 op_decode_hdr_maxsz + 5 + \ 520 decode_remove_maxsz + \
418 decode_getattr_maxsz) 521 decode_getattr_maxsz)
419#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ 522#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
523 encode_sequence_maxsz + \
420 encode_putfh_maxsz + \ 524 encode_putfh_maxsz + \
421 encode_savefh_maxsz + \ 525 encode_savefh_maxsz + \
422 encode_putfh_maxsz + \ 526 encode_putfh_maxsz + \
@@ -425,6 +529,7 @@ static int nfs4_stat_to_errno(int);
425 encode_restorefh_maxsz + \ 529 encode_restorefh_maxsz + \
426 encode_getattr_maxsz) 530 encode_getattr_maxsz)
427#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ 531#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
532 decode_sequence_maxsz + \
428 decode_putfh_maxsz + \ 533 decode_putfh_maxsz + \
429 decode_savefh_maxsz + \ 534 decode_savefh_maxsz + \
430 decode_putfh_maxsz + \ 535 decode_putfh_maxsz + \
@@ -433,6 +538,7 @@ static int nfs4_stat_to_errno(int);
433 decode_restorefh_maxsz + \ 538 decode_restorefh_maxsz + \
434 decode_getattr_maxsz) 539 decode_getattr_maxsz)
435#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ 540#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
541 encode_sequence_maxsz + \
436 encode_putfh_maxsz + \ 542 encode_putfh_maxsz + \
437 encode_savefh_maxsz + \ 543 encode_savefh_maxsz + \
438 encode_putfh_maxsz + \ 544 encode_putfh_maxsz + \
@@ -441,6 +547,7 @@ static int nfs4_stat_to_errno(int);
441 encode_restorefh_maxsz + \ 547 encode_restorefh_maxsz + \
442 decode_getattr_maxsz) 548 decode_getattr_maxsz)
443#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ 549#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
550 decode_sequence_maxsz + \
444 decode_putfh_maxsz + \ 551 decode_putfh_maxsz + \
445 decode_savefh_maxsz + \ 552 decode_savefh_maxsz + \
446 decode_putfh_maxsz + \ 553 decode_putfh_maxsz + \
@@ -449,16 +556,19 @@ static int nfs4_stat_to_errno(int);
449 decode_restorefh_maxsz + \ 556 decode_restorefh_maxsz + \
450 decode_getattr_maxsz) 557 decode_getattr_maxsz)
451#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ 558#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
559 encode_sequence_maxsz + \
452 encode_putfh_maxsz + \ 560 encode_putfh_maxsz + \
453 encode_symlink_maxsz + \ 561 encode_symlink_maxsz + \
454 encode_getattr_maxsz + \ 562 encode_getattr_maxsz + \
455 encode_getfh_maxsz) 563 encode_getfh_maxsz)
456#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ 564#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
565 decode_sequence_maxsz + \
457 decode_putfh_maxsz + \ 566 decode_putfh_maxsz + \
458 decode_symlink_maxsz + \ 567 decode_symlink_maxsz + \
459 decode_getattr_maxsz + \ 568 decode_getattr_maxsz + \
460 decode_getfh_maxsz) 569 decode_getfh_maxsz)
461#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ 570#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
571 encode_sequence_maxsz + \
462 encode_putfh_maxsz + \ 572 encode_putfh_maxsz + \
463 encode_savefh_maxsz + \ 573 encode_savefh_maxsz + \
464 encode_create_maxsz + \ 574 encode_create_maxsz + \
@@ -467,6 +577,7 @@ static int nfs4_stat_to_errno(int);
467 encode_restorefh_maxsz + \ 577 encode_restorefh_maxsz + \
468 encode_getattr_maxsz) 578 encode_getattr_maxsz)
469#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ 579#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
580 decode_sequence_maxsz + \
470 decode_putfh_maxsz + \ 581 decode_putfh_maxsz + \
471 decode_savefh_maxsz + \ 582 decode_savefh_maxsz + \
472 decode_create_maxsz + \ 583 decode_create_maxsz + \
@@ -475,52 +586,98 @@ static int nfs4_stat_to_errno(int);
475 decode_restorefh_maxsz + \ 586 decode_restorefh_maxsz + \
476 decode_getattr_maxsz) 587 decode_getattr_maxsz)
477#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ 588#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
589 encode_sequence_maxsz + \
478 encode_putfh_maxsz + \ 590 encode_putfh_maxsz + \
479 encode_getattr_maxsz) 591 encode_getattr_maxsz)
480#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ 592#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
593 decode_sequence_maxsz + \
481 decode_putfh_maxsz + \ 594 decode_putfh_maxsz + \
482 decode_getattr_maxsz) 595 decode_getattr_maxsz)
483#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ 596#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
597 encode_sequence_maxsz + \
484 encode_putfh_maxsz + \ 598 encode_putfh_maxsz + \
485 encode_statfs_maxsz) 599 encode_statfs_maxsz)
486#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ 600#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
601 decode_sequence_maxsz + \
487 decode_putfh_maxsz + \ 602 decode_putfh_maxsz + \
488 decode_statfs_maxsz) 603 decode_statfs_maxsz)
489#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ 604#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
605 encode_sequence_maxsz + \
490 encode_putfh_maxsz + \ 606 encode_putfh_maxsz + \
491 encode_getattr_maxsz) 607 encode_getattr_maxsz)
492#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ 608#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
609 decode_sequence_maxsz + \
493 decode_putfh_maxsz + \ 610 decode_putfh_maxsz + \
494 decode_getattr_maxsz) 611 decode_getattr_maxsz)
495#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ 612#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
613 encode_sequence_maxsz + \
496 encode_putfh_maxsz + \ 614 encode_putfh_maxsz + \
497 encode_delegreturn_maxsz + \ 615 encode_delegreturn_maxsz + \
498 encode_getattr_maxsz) 616 encode_getattr_maxsz)
499#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ 617#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
618 decode_sequence_maxsz + \
500 decode_delegreturn_maxsz + \ 619 decode_delegreturn_maxsz + \
501 decode_getattr_maxsz) 620 decode_getattr_maxsz)
502#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ 621#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
622 encode_sequence_maxsz + \
503 encode_putfh_maxsz + \ 623 encode_putfh_maxsz + \
504 encode_getacl_maxsz) 624 encode_getacl_maxsz)
505#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ 625#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
626 decode_sequence_maxsz + \
506 decode_putfh_maxsz + \ 627 decode_putfh_maxsz + \
507 decode_getacl_maxsz) 628 decode_getacl_maxsz)
508#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ 629#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
630 encode_sequence_maxsz + \
509 encode_putfh_maxsz + \ 631 encode_putfh_maxsz + \
510 encode_setacl_maxsz) 632 encode_setacl_maxsz)
511#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ 633#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
634 decode_sequence_maxsz + \
512 decode_putfh_maxsz + \ 635 decode_putfh_maxsz + \
513 decode_setacl_maxsz) 636 decode_setacl_maxsz)
514#define NFS4_enc_fs_locations_sz \ 637#define NFS4_enc_fs_locations_sz \
515 (compound_encode_hdr_maxsz + \ 638 (compound_encode_hdr_maxsz + \
639 encode_sequence_maxsz + \
516 encode_putfh_maxsz + \ 640 encode_putfh_maxsz + \
517 encode_lookup_maxsz + \ 641 encode_lookup_maxsz + \
518 encode_fs_locations_maxsz) 642 encode_fs_locations_maxsz)
519#define NFS4_dec_fs_locations_sz \ 643#define NFS4_dec_fs_locations_sz \
520 (compound_decode_hdr_maxsz + \ 644 (compound_decode_hdr_maxsz + \
645 decode_sequence_maxsz + \
521 decode_putfh_maxsz + \ 646 decode_putfh_maxsz + \
522 decode_lookup_maxsz + \ 647 decode_lookup_maxsz + \
523 decode_fs_locations_maxsz) 648 decode_fs_locations_maxsz)
649#if defined(CONFIG_NFS_V4_1)
650#define NFS4_enc_exchange_id_sz \
651 (compound_encode_hdr_maxsz + \
652 encode_exchange_id_maxsz)
653#define NFS4_dec_exchange_id_sz \
654 (compound_decode_hdr_maxsz + \
655 decode_exchange_id_maxsz)
656#define NFS4_enc_create_session_sz \
657 (compound_encode_hdr_maxsz + \
658 encode_create_session_maxsz)
659#define NFS4_dec_create_session_sz \
660 (compound_decode_hdr_maxsz + \
661 decode_create_session_maxsz)
662#define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \
663 encode_destroy_session_maxsz)
664#define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \
665 decode_destroy_session_maxsz)
666#define NFS4_enc_sequence_sz \
667 (compound_decode_hdr_maxsz + \
668 encode_sequence_maxsz)
669#define NFS4_dec_sequence_sz \
670 (compound_decode_hdr_maxsz + \
671 decode_sequence_maxsz)
672#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
673 encode_sequence_maxsz + \
674 encode_putrootfh_maxsz + \
675 encode_fsinfo_maxsz)
676#define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \
677 decode_sequence_maxsz + \
678 decode_putrootfh_maxsz + \
679 decode_fsinfo_maxsz)
680#endif /* CONFIG_NFS_V4_1 */
524 681
525static const umode_t nfs_type2fmt[] = { 682static const umode_t nfs_type2fmt[] = {
526 [NF4BAD] = 0, 683 [NF4BAD] = 0,
@@ -541,6 +698,8 @@ struct compound_hdr {
541 __be32 * nops_p; 698 __be32 * nops_p;
542 uint32_t taglen; 699 uint32_t taglen;
543 char * tag; 700 char * tag;
701 uint32_t replen; /* expected reply words */
702 u32 minorversion;
544}; 703};
545 704
546/* 705/*
@@ -576,22 +735,31 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *
576 xdr_encode_opaque(p, str, len); 735 xdr_encode_opaque(p, str, len);
577} 736}
578 737
579static void encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) 738static void encode_compound_hdr(struct xdr_stream *xdr,
739 struct rpc_rqst *req,
740 struct compound_hdr *hdr)
580{ 741{
581 __be32 *p; 742 __be32 *p;
743 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
744
745 /* initialize running count of expected bytes in reply.
746 * NOTE: the replied tag SHOULD be the same is the one sent,
747 * but this is not required as a MUST for the server to do so. */
748 hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
582 749
583 dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag); 750 dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
584 BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); 751 BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
585 RESERVE_SPACE(12+(XDR_QUADLEN(hdr->taglen)<<2)); 752 RESERVE_SPACE(12+(XDR_QUADLEN(hdr->taglen)<<2));
586 WRITE32(hdr->taglen); 753 WRITE32(hdr->taglen);
587 WRITEMEM(hdr->tag, hdr->taglen); 754 WRITEMEM(hdr->tag, hdr->taglen);
588 WRITE32(NFS4_MINOR_VERSION); 755 WRITE32(hdr->minorversion);
589 hdr->nops_p = p; 756 hdr->nops_p = p;
590 WRITE32(hdr->nops); 757 WRITE32(hdr->nops);
591} 758}
592 759
593static void encode_nops(struct compound_hdr *hdr) 760static void encode_nops(struct compound_hdr *hdr)
594{ 761{
762 BUG_ON(hdr->nops > NFS4_MAX_OPS);
595 *hdr->nops_p = htonl(hdr->nops); 763 *hdr->nops_p = htonl(hdr->nops);
596} 764}
597 765
@@ -736,6 +904,7 @@ static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hd
736 WRITE32(OP_ACCESS); 904 WRITE32(OP_ACCESS);
737 WRITE32(access); 905 WRITE32(access);
738 hdr->nops++; 906 hdr->nops++;
907 hdr->replen += decode_access_maxsz;
739} 908}
740 909
741static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 910static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
@@ -747,6 +916,7 @@ static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg
747 WRITE32(arg->seqid->sequence->counter); 916 WRITE32(arg->seqid->sequence->counter);
748 WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE); 917 WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
749 hdr->nops++; 918 hdr->nops++;
919 hdr->replen += decode_close_maxsz;
750} 920}
751 921
752static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) 922static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
@@ -758,6 +928,7 @@ static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *ar
758 WRITE64(args->offset); 928 WRITE64(args->offset);
759 WRITE32(args->count); 929 WRITE32(args->count);
760 hdr->nops++; 930 hdr->nops++;
931 hdr->replen += decode_commit_maxsz;
761} 932}
762 933
763static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr) 934static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr)
@@ -789,6 +960,7 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
789 WRITE32(create->name->len); 960 WRITE32(create->name->len);
790 WRITEMEM(create->name->name, create->name->len); 961 WRITEMEM(create->name->name, create->name->len);
791 hdr->nops++; 962 hdr->nops++;
963 hdr->replen += decode_create_maxsz;
792 964
793 encode_attrs(xdr, create->attrs, create->server); 965 encode_attrs(xdr, create->attrs, create->server);
794} 966}
@@ -802,6 +974,7 @@ static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct c
802 WRITE32(1); 974 WRITE32(1);
803 WRITE32(bitmap); 975 WRITE32(bitmap);
804 hdr->nops++; 976 hdr->nops++;
977 hdr->replen += decode_getattr_maxsz;
805} 978}
806 979
807static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr) 980static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr)
@@ -814,6 +987,7 @@ static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm
814 WRITE32(bm0); 987 WRITE32(bm0);
815 WRITE32(bm1); 988 WRITE32(bm1);
816 hdr->nops++; 989 hdr->nops++;
990 hdr->replen += decode_getattr_maxsz;
817} 991}
818 992
819static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) 993static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
@@ -841,6 +1015,7 @@ static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
841 RESERVE_SPACE(4); 1015 RESERVE_SPACE(4);
842 WRITE32(OP_GETFH); 1016 WRITE32(OP_GETFH);
843 hdr->nops++; 1017 hdr->nops++;
1018 hdr->replen += decode_getfh_maxsz;
844} 1019}
845 1020
846static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 1021static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
@@ -852,6 +1027,7 @@ static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct
852 WRITE32(name->len); 1027 WRITE32(name->len);
853 WRITEMEM(name->name, name->len); 1028 WRITEMEM(name->name, name->len);
854 hdr->nops++; 1029 hdr->nops++;
1030 hdr->replen += decode_link_maxsz;
855} 1031}
856 1032
857static inline int nfs4_lock_type(struct file_lock *fl, int block) 1033static inline int nfs4_lock_type(struct file_lock *fl, int block)
@@ -899,6 +1075,7 @@ static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args
899 WRITE32(args->lock_seqid->sequence->counter); 1075 WRITE32(args->lock_seqid->sequence->counter);
900 } 1076 }
901 hdr->nops++; 1077 hdr->nops++;
1078 hdr->replen += decode_lock_maxsz;
902} 1079}
903 1080
904static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr) 1081static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr)
@@ -915,6 +1092,7 @@ static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *ar
915 WRITEMEM("lock id:", 8); 1092 WRITEMEM("lock id:", 8);
916 WRITE64(args->lock_owner.id); 1093 WRITE64(args->lock_owner.id);
917 hdr->nops++; 1094 hdr->nops++;
1095 hdr->replen += decode_lockt_maxsz;
918} 1096}
919 1097
920static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr) 1098static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr)
@@ -929,6 +1107,7 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar
929 WRITE64(args->fl->fl_start); 1107 WRITE64(args->fl->fl_start);
930 WRITE64(nfs4_lock_length(args->fl)); 1108 WRITE64(nfs4_lock_length(args->fl));
931 hdr->nops++; 1109 hdr->nops++;
1110 hdr->replen += decode_locku_maxsz;
932} 1111}
933 1112
934static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 1113static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
@@ -941,6 +1120,7 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc
941 WRITE32(len); 1120 WRITE32(len);
942 WRITEMEM(name->name, len); 1121 WRITEMEM(name->name, len);
943 hdr->nops++; 1122 hdr->nops++;
1123 hdr->replen += decode_lookup_maxsz;
944} 1124}
945 1125
946static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode) 1126static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode)
@@ -1080,6 +1260,7 @@ static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg,
1080 BUG(); 1260 BUG();
1081 } 1261 }
1082 hdr->nops++; 1262 hdr->nops++;
1263 hdr->replen += decode_open_maxsz;
1083} 1264}
1084 1265
1085static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr) 1266static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr)
@@ -1091,6 +1272,7 @@ static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_co
1091 WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE); 1272 WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
1092 WRITE32(arg->seqid->sequence->counter); 1273 WRITE32(arg->seqid->sequence->counter);
1093 hdr->nops++; 1274 hdr->nops++;
1275 hdr->replen += decode_open_confirm_maxsz;
1094} 1276}
1095 1277
1096static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr) 1278static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
@@ -1103,6 +1285,7 @@ static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_close
1103 WRITE32(arg->seqid->sequence->counter); 1285 WRITE32(arg->seqid->sequence->counter);
1104 encode_share_access(xdr, arg->fmode); 1286 encode_share_access(xdr, arg->fmode);
1105 hdr->nops++; 1287 hdr->nops++;
1288 hdr->replen += decode_open_downgrade_maxsz;
1106} 1289}
1107 1290
1108static void 1291static void
@@ -1116,6 +1299,7 @@ encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hd
1116 WRITE32(len); 1299 WRITE32(len);
1117 WRITEMEM(fh->data, len); 1300 WRITEMEM(fh->data, len);
1118 hdr->nops++; 1301 hdr->nops++;
1302 hdr->replen += decode_putfh_maxsz;
1119} 1303}
1120 1304
1121static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) 1305static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
@@ -1125,6 +1309,7 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
1125 RESERVE_SPACE(4); 1309 RESERVE_SPACE(4);
1126 WRITE32(OP_PUTROOTFH); 1310 WRITE32(OP_PUTROOTFH);
1127 hdr->nops++; 1311 hdr->nops++;
1312 hdr->replen += decode_putrootfh_maxsz;
1128} 1313}
1129 1314
1130static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx) 1315static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
@@ -1153,6 +1338,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
1153 WRITE64(args->offset); 1338 WRITE64(args->offset);
1154 WRITE32(args->count); 1339 WRITE32(args->count);
1155 hdr->nops++; 1340 hdr->nops++;
1341 hdr->replen += decode_read_maxsz;
1156} 1342}
1157 1343
1158static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) 1344static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
@@ -1178,6 +1364,7 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1178 WRITE32(attrs[0] & readdir->bitmask[0]); 1364 WRITE32(attrs[0] & readdir->bitmask[0]);
1179 WRITE32(attrs[1] & readdir->bitmask[1]); 1365 WRITE32(attrs[1] & readdir->bitmask[1]);
1180 hdr->nops++; 1366 hdr->nops++;
1367 hdr->replen += decode_readdir_maxsz;
1181 dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", 1368 dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
1182 __func__, 1369 __func__,
1183 (unsigned long long)readdir->cookie, 1370 (unsigned long long)readdir->cookie,
@@ -1194,6 +1381,7 @@ static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *
1194 RESERVE_SPACE(4); 1381 RESERVE_SPACE(4);
1195 WRITE32(OP_READLINK); 1382 WRITE32(OP_READLINK);
1196 hdr->nops++; 1383 hdr->nops++;
1384 hdr->replen += decode_readlink_maxsz;
1197} 1385}
1198 1386
1199static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 1387static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
@@ -1205,6 +1393,7 @@ static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struc
1205 WRITE32(name->len); 1393 WRITE32(name->len);
1206 WRITEMEM(name->name, name->len); 1394 WRITEMEM(name->name, name->len);
1207 hdr->nops++; 1395 hdr->nops++;
1396 hdr->replen += decode_remove_maxsz;
1208} 1397}
1209 1398
1210static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr) 1399static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr)
@@ -1220,6 +1409,7 @@ static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, co
1220 WRITE32(newname->len); 1409 WRITE32(newname->len);
1221 WRITEMEM(newname->name, newname->len); 1410 WRITEMEM(newname->name, newname->len);
1222 hdr->nops++; 1411 hdr->nops++;
1412 hdr->replen += decode_rename_maxsz;
1223} 1413}
1224 1414
1225static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr) 1415static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr)
@@ -1230,6 +1420,7 @@ static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client
1230 WRITE32(OP_RENEW); 1420 WRITE32(OP_RENEW);
1231 WRITE64(client_stateid->cl_clientid); 1421 WRITE64(client_stateid->cl_clientid);
1232 hdr->nops++; 1422 hdr->nops++;
1423 hdr->replen += decode_renew_maxsz;
1233} 1424}
1234 1425
1235static void 1426static void
@@ -1240,6 +1431,7 @@ encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
1240 RESERVE_SPACE(4); 1431 RESERVE_SPACE(4);
1241 WRITE32(OP_RESTOREFH); 1432 WRITE32(OP_RESTOREFH);
1242 hdr->nops++; 1433 hdr->nops++;
1434 hdr->replen += decode_restorefh_maxsz;
1243} 1435}
1244 1436
1245static int 1437static int
@@ -1259,6 +1451,7 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compoun
1259 WRITE32(arg->acl_len); 1451 WRITE32(arg->acl_len);
1260 xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); 1452 xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
1261 hdr->nops++; 1453 hdr->nops++;
1454 hdr->replen += decode_setacl_maxsz;
1262 return 0; 1455 return 0;
1263} 1456}
1264 1457
@@ -1270,6 +1463,7 @@ encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
1270 RESERVE_SPACE(4); 1463 RESERVE_SPACE(4);
1271 WRITE32(OP_SAVEFH); 1464 WRITE32(OP_SAVEFH);
1272 hdr->nops++; 1465 hdr->nops++;
1466 hdr->replen += decode_savefh_maxsz;
1273} 1467}
1274 1468
1275static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr) 1469static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr)
@@ -1280,6 +1474,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
1280 WRITE32(OP_SETATTR); 1474 WRITE32(OP_SETATTR);
1281 WRITEMEM(arg->stateid.data, NFS4_STATEID_SIZE); 1475 WRITEMEM(arg->stateid.data, NFS4_STATEID_SIZE);
1282 hdr->nops++; 1476 hdr->nops++;
1477 hdr->replen += decode_setattr_maxsz;
1283 encode_attrs(xdr, arg->iap, server); 1478 encode_attrs(xdr, arg->iap, server);
1284} 1479}
1285 1480
@@ -1299,6 +1494,7 @@ static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclie
1299 RESERVE_SPACE(4); 1494 RESERVE_SPACE(4);
1300 WRITE32(setclientid->sc_cb_ident); 1495 WRITE32(setclientid->sc_cb_ident);
1301 hdr->nops++; 1496 hdr->nops++;
1497 hdr->replen += decode_setclientid_maxsz;
1302} 1498}
1303 1499
1304static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state, struct compound_hdr *hdr) 1500static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state, struct compound_hdr *hdr)
@@ -1310,6 +1506,7 @@ static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_
1310 WRITE64(client_state->cl_clientid); 1506 WRITE64(client_state->cl_clientid);
1311 WRITEMEM(client_state->cl_confirm.data, NFS4_VERIFIER_SIZE); 1507 WRITEMEM(client_state->cl_confirm.data, NFS4_VERIFIER_SIZE);
1312 hdr->nops++; 1508 hdr->nops++;
1509 hdr->replen += decode_setclientid_confirm_maxsz;
1313} 1510}
1314 1511
1315static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr) 1512static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
@@ -1328,6 +1525,7 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg
1328 1525
1329 xdr_write_pages(xdr, args->pages, args->pgbase, args->count); 1526 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1330 hdr->nops++; 1527 hdr->nops++;
1528 hdr->replen += decode_write_maxsz;
1331} 1529}
1332 1530
1333static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr) 1531static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
@@ -1339,11 +1537,163 @@ static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *state
1339 WRITE32(OP_DELEGRETURN); 1537 WRITE32(OP_DELEGRETURN);
1340 WRITEMEM(stateid->data, NFS4_STATEID_SIZE); 1538 WRITEMEM(stateid->data, NFS4_STATEID_SIZE);
1341 hdr->nops++; 1539 hdr->nops++;
1540 hdr->replen += decode_delegreturn_maxsz;
1541}
1542
1543#if defined(CONFIG_NFS_V4_1)
1544/* NFSv4.1 operations */
1545static void encode_exchange_id(struct xdr_stream *xdr,
1546 struct nfs41_exchange_id_args *args,
1547 struct compound_hdr *hdr)
1548{
1549 __be32 *p;
1550
1551 RESERVE_SPACE(4 + sizeof(args->verifier->data));
1552 WRITE32(OP_EXCHANGE_ID);
1553 WRITEMEM(args->verifier->data, sizeof(args->verifier->data));
1554
1555 encode_string(xdr, args->id_len, args->id);
1556
1557 RESERVE_SPACE(12);
1558 WRITE32(args->flags);
1559 WRITE32(0); /* zero length state_protect4_a */
1560 WRITE32(0); /* zero length implementation id array */
1561 hdr->nops++;
1562 hdr->replen += decode_exchange_id_maxsz;
1563}
1564
1565static void encode_create_session(struct xdr_stream *xdr,
1566 struct nfs41_create_session_args *args,
1567 struct compound_hdr *hdr)
1568{
1569 __be32 *p;
1570 char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
1571 uint32_t len;
1572 struct nfs_client *clp = args->client;
1573
1574 RESERVE_SPACE(4);
1575 WRITE32(OP_CREATE_SESSION);
1576
1577 RESERVE_SPACE(8);
1578 WRITE64(clp->cl_ex_clid);
1579
1580 RESERVE_SPACE(8);
1581 WRITE32(clp->cl_seqid); /*Sequence id */
1582 WRITE32(args->flags); /*flags */
1583
1584 RESERVE_SPACE(2*28); /* 2 channel_attrs */
1585 /* Fore Channel */
1586 WRITE32(args->fc_attrs.headerpadsz); /* header padding size */
1587 WRITE32(args->fc_attrs.max_rqst_sz); /* max req size */
1588 WRITE32(args->fc_attrs.max_resp_sz); /* max resp size */
1589 WRITE32(args->fc_attrs.max_resp_sz_cached); /* Max resp sz cached */
1590 WRITE32(args->fc_attrs.max_ops); /* max operations */
1591 WRITE32(args->fc_attrs.max_reqs); /* max requests */
1592 WRITE32(0); /* rdmachannel_attrs */
1593
1594 /* Back Channel */
1595 WRITE32(args->fc_attrs.headerpadsz); /* header padding size */
1596 WRITE32(args->bc_attrs.max_rqst_sz); /* max req size */
1597 WRITE32(args->bc_attrs.max_resp_sz); /* max resp size */
1598 WRITE32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
1599 WRITE32(args->bc_attrs.max_ops); /* max operations */
1600 WRITE32(args->bc_attrs.max_reqs); /* max requests */
1601 WRITE32(0); /* rdmachannel_attrs */
1602
1603 RESERVE_SPACE(4);
1604 WRITE32(args->cb_program); /* cb_program */
1605
1606 RESERVE_SPACE(4); /* # of security flavors */
1607 WRITE32(1);
1608
1609 RESERVE_SPACE(4);
1610 WRITE32(RPC_AUTH_UNIX); /* auth_sys */
1611
1612 /* authsys_parms rfc1831 */
1613 RESERVE_SPACE(4);
1614 WRITE32((u32)clp->cl_boot_time.tv_nsec); /* stamp */
1615 len = scnprintf(machine_name, sizeof(machine_name), "%s",
1616 clp->cl_ipaddr);
1617 RESERVE_SPACE(16 + len);
1618 WRITE32(len);
1619 WRITEMEM(machine_name, len);
1620 WRITE32(0); /* UID */
1621 WRITE32(0); /* GID */
1622 WRITE32(0); /* No more gids */
1623 hdr->nops++;
1624 hdr->replen += decode_create_session_maxsz;
1625}
1626
1627static void encode_destroy_session(struct xdr_stream *xdr,
1628 struct nfs4_session *session,
1629 struct compound_hdr *hdr)
1630{
1631 __be32 *p;
1632 RESERVE_SPACE(4 + NFS4_MAX_SESSIONID_LEN);
1633 WRITE32(OP_DESTROY_SESSION);
1634 WRITEMEM(session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
1635 hdr->nops++;
1636 hdr->replen += decode_destroy_session_maxsz;
1342} 1637}
1638#endif /* CONFIG_NFS_V4_1 */
1639
1640static void encode_sequence(struct xdr_stream *xdr,
1641 const struct nfs4_sequence_args *args,
1642 struct compound_hdr *hdr)
1643{
1644#if defined(CONFIG_NFS_V4_1)
1645 struct nfs4_session *session = args->sa_session;
1646 struct nfs4_slot_table *tp;
1647 struct nfs4_slot *slot;
1648 __be32 *p;
1649
1650 if (!session)
1651 return;
1652
1653 tp = &session->fc_slot_table;
1654
1655 WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
1656 slot = tp->slots + args->sa_slotid;
1657
1658 RESERVE_SPACE(4);
1659 WRITE32(OP_SEQUENCE);
1660
1661 /*
1662 * Sessionid + seqid + slotid + max slotid + cache_this
1663 */
1664 dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
1665 "max_slotid=%d cache_this=%d\n",
1666 __func__,
1667 ((u32 *)session->sess_id.data)[0],
1668 ((u32 *)session->sess_id.data)[1],
1669 ((u32 *)session->sess_id.data)[2],
1670 ((u32 *)session->sess_id.data)[3],
1671 slot->seq_nr, args->sa_slotid,
1672 tp->highest_used_slotid, args->sa_cache_this);
1673 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 16);
1674 WRITEMEM(session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
1675 WRITE32(slot->seq_nr);
1676 WRITE32(args->sa_slotid);
1677 WRITE32(tp->highest_used_slotid);
1678 WRITE32(args->sa_cache_this);
1679 hdr->nops++;
1680 hdr->replen += decode_sequence_maxsz;
1681#endif /* CONFIG_NFS_V4_1 */
1682}
1683
1343/* 1684/*
1344 * END OF "GENERIC" ENCODE ROUTINES. 1685 * END OF "GENERIC" ENCODE ROUTINES.
1345 */ 1686 */
1346 1687
1688static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
1689{
1690#if defined(CONFIG_NFS_V4_1)
1691 if (args->sa_session)
1692 return args->sa_session->clp->cl_minorversion;
1693#endif /* CONFIG_NFS_V4_1 */
1694 return 0;
1695}
1696
1347/* 1697/*
1348 * Encode an ACCESS request 1698 * Encode an ACCESS request
1349 */ 1699 */
@@ -1351,11 +1701,12 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs
1351{ 1701{
1352 struct xdr_stream xdr; 1702 struct xdr_stream xdr;
1353 struct compound_hdr hdr = { 1703 struct compound_hdr hdr = {
1354 .nops = 0, 1704 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1355 }; 1705 };
1356 1706
1357 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1707 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1358 encode_compound_hdr(&xdr, &hdr); 1708 encode_compound_hdr(&xdr, req, &hdr);
1709 encode_sequence(&xdr, &args->seq_args, &hdr);
1359 encode_putfh(&xdr, args->fh, &hdr); 1710 encode_putfh(&xdr, args->fh, &hdr);
1360 encode_access(&xdr, args->access, &hdr); 1711 encode_access(&xdr, args->access, &hdr);
1361 encode_getfattr(&xdr, args->bitmask, &hdr); 1712 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1370,11 +1721,12 @@ static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs
1370{ 1721{
1371 struct xdr_stream xdr; 1722 struct xdr_stream xdr;
1372 struct compound_hdr hdr = { 1723 struct compound_hdr hdr = {
1373 .nops = 0, 1724 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1374 }; 1725 };
1375 1726
1376 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1727 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1377 encode_compound_hdr(&xdr, &hdr); 1728 encode_compound_hdr(&xdr, req, &hdr);
1729 encode_sequence(&xdr, &args->seq_args, &hdr);
1378 encode_putfh(&xdr, args->dir_fh, &hdr); 1730 encode_putfh(&xdr, args->dir_fh, &hdr);
1379 encode_lookup(&xdr, args->name, &hdr); 1731 encode_lookup(&xdr, args->name, &hdr);
1380 encode_getfh(&xdr, &hdr); 1732 encode_getfh(&xdr, &hdr);
@@ -1390,11 +1742,12 @@ static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struc
1390{ 1742{
1391 struct xdr_stream xdr; 1743 struct xdr_stream xdr;
1392 struct compound_hdr hdr = { 1744 struct compound_hdr hdr = {
1393 .nops = 0, 1745 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1394 }; 1746 };
1395 1747
1396 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1748 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1397 encode_compound_hdr(&xdr, &hdr); 1749 encode_compound_hdr(&xdr, req, &hdr);
1750 encode_sequence(&xdr, &args->seq_args, &hdr);
1398 encode_putrootfh(&xdr, &hdr); 1751 encode_putrootfh(&xdr, &hdr);
1399 encode_getfh(&xdr, &hdr); 1752 encode_getfh(&xdr, &hdr);
1400 encode_getfattr(&xdr, args->bitmask, &hdr); 1753 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1409,11 +1762,12 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs
1409{ 1762{
1410 struct xdr_stream xdr; 1763 struct xdr_stream xdr;
1411 struct compound_hdr hdr = { 1764 struct compound_hdr hdr = {
1412 .nops = 0, 1765 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1413 }; 1766 };
1414 1767
1415 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1768 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1416 encode_compound_hdr(&xdr, &hdr); 1769 encode_compound_hdr(&xdr, req, &hdr);
1770 encode_sequence(&xdr, &args->seq_args, &hdr);
1417 encode_putfh(&xdr, args->fh, &hdr); 1771 encode_putfh(&xdr, args->fh, &hdr);
1418 encode_remove(&xdr, &args->name, &hdr); 1772 encode_remove(&xdr, &args->name, &hdr);
1419 encode_getfattr(&xdr, args->bitmask, &hdr); 1773 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1428,11 +1782,12 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs
1428{ 1782{
1429 struct xdr_stream xdr; 1783 struct xdr_stream xdr;
1430 struct compound_hdr hdr = { 1784 struct compound_hdr hdr = {
1431 .nops = 0, 1785 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1432 }; 1786 };
1433 1787
1434 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1788 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1435 encode_compound_hdr(&xdr, &hdr); 1789 encode_compound_hdr(&xdr, req, &hdr);
1790 encode_sequence(&xdr, &args->seq_args, &hdr);
1436 encode_putfh(&xdr, args->old_dir, &hdr); 1791 encode_putfh(&xdr, args->old_dir, &hdr);
1437 encode_savefh(&xdr, &hdr); 1792 encode_savefh(&xdr, &hdr);
1438 encode_putfh(&xdr, args->new_dir, &hdr); 1793 encode_putfh(&xdr, args->new_dir, &hdr);
@@ -1451,11 +1806,12 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_
1451{ 1806{
1452 struct xdr_stream xdr; 1807 struct xdr_stream xdr;
1453 struct compound_hdr hdr = { 1808 struct compound_hdr hdr = {
1454 .nops = 0, 1809 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1455 }; 1810 };
1456 1811
1457 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1812 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1458 encode_compound_hdr(&xdr, &hdr); 1813 encode_compound_hdr(&xdr, req, &hdr);
1814 encode_sequence(&xdr, &args->seq_args, &hdr);
1459 encode_putfh(&xdr, args->fh, &hdr); 1815 encode_putfh(&xdr, args->fh, &hdr);
1460 encode_savefh(&xdr, &hdr); 1816 encode_savefh(&xdr, &hdr);
1461 encode_putfh(&xdr, args->dir_fh, &hdr); 1817 encode_putfh(&xdr, args->dir_fh, &hdr);
@@ -1474,11 +1830,12 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs
1474{ 1830{
1475 struct xdr_stream xdr; 1831 struct xdr_stream xdr;
1476 struct compound_hdr hdr = { 1832 struct compound_hdr hdr = {
1477 .nops = 0, 1833 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1478 }; 1834 };
1479 1835
1480 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1836 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1481 encode_compound_hdr(&xdr, &hdr); 1837 encode_compound_hdr(&xdr, req, &hdr);
1838 encode_sequence(&xdr, &args->seq_args, &hdr);
1482 encode_putfh(&xdr, args->dir_fh, &hdr); 1839 encode_putfh(&xdr, args->dir_fh, &hdr);
1483 encode_savefh(&xdr, &hdr); 1840 encode_savefh(&xdr, &hdr);
1484 encode_create(&xdr, args, &hdr); 1841 encode_create(&xdr, args, &hdr);
@@ -1505,11 +1862,12 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf
1505{ 1862{
1506 struct xdr_stream xdr; 1863 struct xdr_stream xdr;
1507 struct compound_hdr hdr = { 1864 struct compound_hdr hdr = {
1508 .nops = 0, 1865 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1509 }; 1866 };
1510 1867
1511 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1868 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1512 encode_compound_hdr(&xdr, &hdr); 1869 encode_compound_hdr(&xdr, req, &hdr);
1870 encode_sequence(&xdr, &args->seq_args, &hdr);
1513 encode_putfh(&xdr, args->fh, &hdr); 1871 encode_putfh(&xdr, args->fh, &hdr);
1514 encode_getfattr(&xdr, args->bitmask, &hdr); 1872 encode_getfattr(&xdr, args->bitmask, &hdr);
1515 encode_nops(&hdr); 1873 encode_nops(&hdr);
@@ -1523,11 +1881,12 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closea
1523{ 1881{
1524 struct xdr_stream xdr; 1882 struct xdr_stream xdr;
1525 struct compound_hdr hdr = { 1883 struct compound_hdr hdr = {
1526 .nops = 0, 1884 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1527 }; 1885 };
1528 1886
1529 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1887 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1530 encode_compound_hdr(&xdr, &hdr); 1888 encode_compound_hdr(&xdr, req, &hdr);
1889 encode_sequence(&xdr, &args->seq_args, &hdr);
1531 encode_putfh(&xdr, args->fh, &hdr); 1890 encode_putfh(&xdr, args->fh, &hdr);
1532 encode_close(&xdr, args, &hdr); 1891 encode_close(&xdr, args, &hdr);
1533 encode_getfattr(&xdr, args->bitmask, &hdr); 1892 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1542,11 +1901,12 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openarg
1542{ 1901{
1543 struct xdr_stream xdr; 1902 struct xdr_stream xdr;
1544 struct compound_hdr hdr = { 1903 struct compound_hdr hdr = {
1545 .nops = 0, 1904 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1546 }; 1905 };
1547 1906
1548 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1907 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1549 encode_compound_hdr(&xdr, &hdr); 1908 encode_compound_hdr(&xdr, req, &hdr);
1909 encode_sequence(&xdr, &args->seq_args, &hdr);
1550 encode_putfh(&xdr, args->fh, &hdr); 1910 encode_putfh(&xdr, args->fh, &hdr);
1551 encode_savefh(&xdr, &hdr); 1911 encode_savefh(&xdr, &hdr);
1552 encode_open(&xdr, args, &hdr); 1912 encode_open(&xdr, args, &hdr);
@@ -1569,7 +1929,7 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs
1569 }; 1929 };
1570 1930
1571 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1931 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1572 encode_compound_hdr(&xdr, &hdr); 1932 encode_compound_hdr(&xdr, req, &hdr);
1573 encode_putfh(&xdr, args->fh, &hdr); 1933 encode_putfh(&xdr, args->fh, &hdr);
1574 encode_open_confirm(&xdr, args, &hdr); 1934 encode_open_confirm(&xdr, args, &hdr);
1575 encode_nops(&hdr); 1935 encode_nops(&hdr);
@@ -1583,11 +1943,12 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_
1583{ 1943{
1584 struct xdr_stream xdr; 1944 struct xdr_stream xdr;
1585 struct compound_hdr hdr = { 1945 struct compound_hdr hdr = {
1586 .nops = 0, 1946 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1587 }; 1947 };
1588 1948
1589 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1949 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1590 encode_compound_hdr(&xdr, &hdr); 1950 encode_compound_hdr(&xdr, req, &hdr);
1951 encode_sequence(&xdr, &args->seq_args, &hdr);
1591 encode_putfh(&xdr, args->fh, &hdr); 1952 encode_putfh(&xdr, args->fh, &hdr);
1592 encode_open(&xdr, args, &hdr); 1953 encode_open(&xdr, args, &hdr);
1593 encode_getfattr(&xdr, args->bitmask, &hdr); 1954 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1602,11 +1963,12 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct n
1602{ 1963{
1603 struct xdr_stream xdr; 1964 struct xdr_stream xdr;
1604 struct compound_hdr hdr = { 1965 struct compound_hdr hdr = {
1605 .nops = 0, 1966 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1606 }; 1967 };
1607 1968
1608 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1969 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1609 encode_compound_hdr(&xdr, &hdr); 1970 encode_compound_hdr(&xdr, req, &hdr);
1971 encode_sequence(&xdr, &args->seq_args, &hdr);
1610 encode_putfh(&xdr, args->fh, &hdr); 1972 encode_putfh(&xdr, args->fh, &hdr);
1611 encode_open_downgrade(&xdr, args, &hdr); 1973 encode_open_downgrade(&xdr, args, &hdr);
1612 encode_getfattr(&xdr, args->bitmask, &hdr); 1974 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1621,11 +1983,12 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_ar
1621{ 1983{
1622 struct xdr_stream xdr; 1984 struct xdr_stream xdr;
1623 struct compound_hdr hdr = { 1985 struct compound_hdr hdr = {
1624 .nops = 0, 1986 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1625 }; 1987 };
1626 1988
1627 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1989 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1628 encode_compound_hdr(&xdr, &hdr); 1990 encode_compound_hdr(&xdr, req, &hdr);
1991 encode_sequence(&xdr, &args->seq_args, &hdr);
1629 encode_putfh(&xdr, args->fh, &hdr); 1992 encode_putfh(&xdr, args->fh, &hdr);
1630 encode_lock(&xdr, args, &hdr); 1993 encode_lock(&xdr, args, &hdr);
1631 encode_nops(&hdr); 1994 encode_nops(&hdr);
@@ -1639,11 +2002,12 @@ static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_
1639{ 2002{
1640 struct xdr_stream xdr; 2003 struct xdr_stream xdr;
1641 struct compound_hdr hdr = { 2004 struct compound_hdr hdr = {
1642 .nops = 0, 2005 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1643 }; 2006 };
1644 2007
1645 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2008 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1646 encode_compound_hdr(&xdr, &hdr); 2009 encode_compound_hdr(&xdr, req, &hdr);
2010 encode_sequence(&xdr, &args->seq_args, &hdr);
1647 encode_putfh(&xdr, args->fh, &hdr); 2011 encode_putfh(&xdr, args->fh, &hdr);
1648 encode_lockt(&xdr, args, &hdr); 2012 encode_lockt(&xdr, args, &hdr);
1649 encode_nops(&hdr); 2013 encode_nops(&hdr);
@@ -1657,11 +2021,12 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_
1657{ 2021{
1658 struct xdr_stream xdr; 2022 struct xdr_stream xdr;
1659 struct compound_hdr hdr = { 2023 struct compound_hdr hdr = {
1660 .nops = 0, 2024 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1661 }; 2025 };
1662 2026
1663 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2027 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1664 encode_compound_hdr(&xdr, &hdr); 2028 encode_compound_hdr(&xdr, req, &hdr);
2029 encode_sequence(&xdr, &args->seq_args, &hdr);
1665 encode_putfh(&xdr, args->fh, &hdr); 2030 encode_putfh(&xdr, args->fh, &hdr);
1666 encode_locku(&xdr, args, &hdr); 2031 encode_locku(&xdr, args, &hdr);
1667 encode_nops(&hdr); 2032 encode_nops(&hdr);
@@ -1675,22 +2040,16 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
1675{ 2040{
1676 struct xdr_stream xdr; 2041 struct xdr_stream xdr;
1677 struct compound_hdr hdr = { 2042 struct compound_hdr hdr = {
1678 .nops = 0, 2043 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1679 }; 2044 };
1680 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1681 unsigned int replen;
1682 2045
1683 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2046 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1684 encode_compound_hdr(&xdr, &hdr); 2047 encode_compound_hdr(&xdr, req, &hdr);
2048 encode_sequence(&xdr, &args->seq_args, &hdr);
1685 encode_putfh(&xdr, args->fh, &hdr); 2049 encode_putfh(&xdr, args->fh, &hdr);
1686 encode_readlink(&xdr, args, req, &hdr); 2050 encode_readlink(&xdr, args, req, &hdr);
1687 2051
1688 /* set up reply kvec 2052 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
1689 * toplevel_status + taglen + rescount + OP_PUTFH + status
1690 * + OP_READLINK + status + string length = 8
1691 */
1692 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_readlink_sz) << 2;
1693 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages,
1694 args->pgbase, args->pglen); 2053 args->pgbase, args->pglen);
1695 encode_nops(&hdr); 2054 encode_nops(&hdr);
1696 return 0; 2055 return 0;
@@ -1703,25 +2062,19 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
1703{ 2062{
1704 struct xdr_stream xdr; 2063 struct xdr_stream xdr;
1705 struct compound_hdr hdr = { 2064 struct compound_hdr hdr = {
1706 .nops = 0, 2065 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1707 }; 2066 };
1708 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1709 int replen;
1710 2067
1711 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2068 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1712 encode_compound_hdr(&xdr, &hdr); 2069 encode_compound_hdr(&xdr, req, &hdr);
2070 encode_sequence(&xdr, &args->seq_args, &hdr);
1713 encode_putfh(&xdr, args->fh, &hdr); 2071 encode_putfh(&xdr, args->fh, &hdr);
1714 encode_readdir(&xdr, args, req, &hdr); 2072 encode_readdir(&xdr, args, req, &hdr);
1715 2073
1716 /* set up reply kvec 2074 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
1717 * toplevel_status + taglen + rescount + OP_PUTFH + status
1718 * + OP_READDIR + status + verifer(2) = 9
1719 */
1720 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_readdir_sz) << 2;
1721 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages,
1722 args->pgbase, args->count); 2075 args->pgbase, args->count);
1723 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n", 2076 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
1724 __func__, replen, args->pages, 2077 __func__, hdr.replen << 2, args->pages,
1725 args->pgbase, args->count); 2078 args->pgbase, args->count);
1726 encode_nops(&hdr); 2079 encode_nops(&hdr);
1727 return 0; 2080 return 0;
@@ -1732,24 +2085,18 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
1732 */ 2085 */
1733static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) 2086static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
1734{ 2087{
1735 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1736 struct xdr_stream xdr; 2088 struct xdr_stream xdr;
1737 struct compound_hdr hdr = { 2089 struct compound_hdr hdr = {
1738 .nops = 0, 2090 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1739 }; 2091 };
1740 int replen;
1741 2092
1742 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2093 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1743 encode_compound_hdr(&xdr, &hdr); 2094 encode_compound_hdr(&xdr, req, &hdr);
2095 encode_sequence(&xdr, &args->seq_args, &hdr);
1744 encode_putfh(&xdr, args->fh, &hdr); 2096 encode_putfh(&xdr, args->fh, &hdr);
1745 encode_read(&xdr, args, &hdr); 2097 encode_read(&xdr, args, &hdr);
1746 2098
1747 /* set up reply kvec 2099 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
1748 * toplevel status + taglen=0 + rescount + OP_PUTFH + status
1749 * + OP_READ + status + eof + datalen = 9
1750 */
1751 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_read_sz) << 2;
1752 xdr_inline_pages(&req->rq_rcv_buf, replen,
1753 args->pages, args->pgbase, args->count); 2100 args->pages, args->pgbase, args->count);
1754 req->rq_rcv_buf.flags |= XDRBUF_READ; 2101 req->rq_rcv_buf.flags |= XDRBUF_READ;
1755 encode_nops(&hdr); 2102 encode_nops(&hdr);
@@ -1763,11 +2110,12 @@ static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_seta
1763{ 2110{
1764 struct xdr_stream xdr; 2111 struct xdr_stream xdr;
1765 struct compound_hdr hdr = { 2112 struct compound_hdr hdr = {
1766 .nops = 0, 2113 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1767 }; 2114 };
1768 2115
1769 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2116 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1770 encode_compound_hdr(&xdr, &hdr); 2117 encode_compound_hdr(&xdr, req, &hdr);
2118 encode_sequence(&xdr, &args->seq_args, &hdr);
1771 encode_putfh(&xdr, args->fh, &hdr); 2119 encode_putfh(&xdr, args->fh, &hdr);
1772 encode_setattr(&xdr, args, args->server, &hdr); 2120 encode_setattr(&xdr, args, args->server, &hdr);
1773 encode_getfattr(&xdr, args->bitmask, &hdr); 2121 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1783,20 +2131,19 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
1783 struct nfs_getaclargs *args) 2131 struct nfs_getaclargs *args)
1784{ 2132{
1785 struct xdr_stream xdr; 2133 struct xdr_stream xdr;
1786 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1787 struct compound_hdr hdr = { 2134 struct compound_hdr hdr = {
1788 .nops = 0, 2135 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1789 }; 2136 };
1790 int replen; 2137 uint32_t replen;
1791 2138
1792 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2139 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1793 encode_compound_hdr(&xdr, &hdr); 2140 encode_compound_hdr(&xdr, req, &hdr);
2141 encode_sequence(&xdr, &args->seq_args, &hdr);
1794 encode_putfh(&xdr, args->fh, &hdr); 2142 encode_putfh(&xdr, args->fh, &hdr);
2143 replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1;
1795 encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr); 2144 encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
1796 2145
1797 /* set up reply buffer: */ 2146 xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
1798 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
1799 xdr_inline_pages(&req->rq_rcv_buf, replen,
1800 args->acl_pages, args->acl_pgbase, args->acl_len); 2147 args->acl_pages, args->acl_pgbase, args->acl_len);
1801 encode_nops(&hdr); 2148 encode_nops(&hdr);
1802 return 0; 2149 return 0;
@@ -1809,11 +2156,12 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writea
1809{ 2156{
1810 struct xdr_stream xdr; 2157 struct xdr_stream xdr;
1811 struct compound_hdr hdr = { 2158 struct compound_hdr hdr = {
1812 .nops = 0, 2159 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1813 }; 2160 };
1814 2161
1815 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2162 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1816 encode_compound_hdr(&xdr, &hdr); 2163 encode_compound_hdr(&xdr, req, &hdr);
2164 encode_sequence(&xdr, &args->seq_args, &hdr);
1817 encode_putfh(&xdr, args->fh, &hdr); 2165 encode_putfh(&xdr, args->fh, &hdr);
1818 encode_write(&xdr, args, &hdr); 2166 encode_write(&xdr, args, &hdr);
1819 req->rq_snd_buf.flags |= XDRBUF_WRITE; 2167 req->rq_snd_buf.flags |= XDRBUF_WRITE;
@@ -1829,11 +2177,12 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_write
1829{ 2177{
1830 struct xdr_stream xdr; 2178 struct xdr_stream xdr;
1831 struct compound_hdr hdr = { 2179 struct compound_hdr hdr = {
1832 .nops = 0, 2180 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1833 }; 2181 };
1834 2182
1835 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2183 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1836 encode_compound_hdr(&xdr, &hdr); 2184 encode_compound_hdr(&xdr, req, &hdr);
2185 encode_sequence(&xdr, &args->seq_args, &hdr);
1837 encode_putfh(&xdr, args->fh, &hdr); 2186 encode_putfh(&xdr, args->fh, &hdr);
1838 encode_commit(&xdr, args, &hdr); 2187 encode_commit(&xdr, args, &hdr);
1839 encode_getfattr(&xdr, args->bitmask, &hdr); 2188 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1848,11 +2197,12 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin
1848{ 2197{
1849 struct xdr_stream xdr; 2198 struct xdr_stream xdr;
1850 struct compound_hdr hdr = { 2199 struct compound_hdr hdr = {
1851 .nops = 0, 2200 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1852 }; 2201 };
1853 2202
1854 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2203 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1855 encode_compound_hdr(&xdr, &hdr); 2204 encode_compound_hdr(&xdr, req, &hdr);
2205 encode_sequence(&xdr, &args->seq_args, &hdr);
1856 encode_putfh(&xdr, args->fh, &hdr); 2206 encode_putfh(&xdr, args->fh, &hdr);
1857 encode_fsinfo(&xdr, args->bitmask, &hdr); 2207 encode_fsinfo(&xdr, args->bitmask, &hdr);
1858 encode_nops(&hdr); 2208 encode_nops(&hdr);
@@ -1866,11 +2216,12 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n
1866{ 2216{
1867 struct xdr_stream xdr; 2217 struct xdr_stream xdr;
1868 struct compound_hdr hdr = { 2218 struct compound_hdr hdr = {
1869 .nops = 0, 2219 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1870 }; 2220 };
1871 2221
1872 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2222 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1873 encode_compound_hdr(&xdr, &hdr); 2223 encode_compound_hdr(&xdr, req, &hdr);
2224 encode_sequence(&xdr, &args->seq_args, &hdr);
1874 encode_putfh(&xdr, args->fh, &hdr); 2225 encode_putfh(&xdr, args->fh, &hdr);
1875 encode_getattr_one(&xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0], 2226 encode_getattr_one(&xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0],
1876 &hdr); 2227 &hdr);
@@ -1885,11 +2236,12 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs
1885{ 2236{
1886 struct xdr_stream xdr; 2237 struct xdr_stream xdr;
1887 struct compound_hdr hdr = { 2238 struct compound_hdr hdr = {
1888 .nops = 0, 2239 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1889 }; 2240 };
1890 2241
1891 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2242 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1892 encode_compound_hdr(&xdr, &hdr); 2243 encode_compound_hdr(&xdr, req, &hdr);
2244 encode_sequence(&xdr, &args->seq_args, &hdr);
1893 encode_putfh(&xdr, args->fh, &hdr); 2245 encode_putfh(&xdr, args->fh, &hdr);
1894 encode_getattr_two(&xdr, args->bitmask[0] & nfs4_statfs_bitmap[0], 2246 encode_getattr_two(&xdr, args->bitmask[0] & nfs4_statfs_bitmap[0],
1895 args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr); 2247 args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
@@ -1900,16 +2252,18 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs
1900/* 2252/*
1901 * GETATTR_BITMAP request 2253 * GETATTR_BITMAP request
1902 */ 2254 */
1903static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struct nfs_fh *fhandle) 2255static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p,
2256 struct nfs4_server_caps_arg *args)
1904{ 2257{
1905 struct xdr_stream xdr; 2258 struct xdr_stream xdr;
1906 struct compound_hdr hdr = { 2259 struct compound_hdr hdr = {
1907 .nops = 0, 2260 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1908 }; 2261 };
1909 2262
1910 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2263 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1911 encode_compound_hdr(&xdr, &hdr); 2264 encode_compound_hdr(&xdr, req, &hdr);
1912 encode_putfh(&xdr, fhandle, &hdr); 2265 encode_sequence(&xdr, &args->seq_args, &hdr);
2266 encode_putfh(&xdr, args->fhandle, &hdr);
1913 encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS| 2267 encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
1914 FATTR4_WORD0_LINK_SUPPORT| 2268 FATTR4_WORD0_LINK_SUPPORT|
1915 FATTR4_WORD0_SYMLINK_SUPPORT| 2269 FATTR4_WORD0_SYMLINK_SUPPORT|
@@ -1929,7 +2283,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client
1929 }; 2283 };
1930 2284
1931 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2285 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1932 encode_compound_hdr(&xdr, &hdr); 2286 encode_compound_hdr(&xdr, req, &hdr);
1933 encode_renew(&xdr, clp, &hdr); 2287 encode_renew(&xdr, clp, &hdr);
1934 encode_nops(&hdr); 2288 encode_nops(&hdr);
1935 return 0; 2289 return 0;
@@ -1946,7 +2300,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4
1946 }; 2300 };
1947 2301
1948 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2302 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1949 encode_compound_hdr(&xdr, &hdr); 2303 encode_compound_hdr(&xdr, req, &hdr);
1950 encode_setclientid(&xdr, sc, &hdr); 2304 encode_setclientid(&xdr, sc, &hdr);
1951 encode_nops(&hdr); 2305 encode_nops(&hdr);
1952 return 0; 2306 return 0;
@@ -1964,7 +2318,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
1964 const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 }; 2318 const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
1965 2319
1966 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2320 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1967 encode_compound_hdr(&xdr, &hdr); 2321 encode_compound_hdr(&xdr, req, &hdr);
1968 encode_setclientid_confirm(&xdr, clp, &hdr); 2322 encode_setclientid_confirm(&xdr, clp, &hdr);
1969 encode_putrootfh(&xdr, &hdr); 2323 encode_putrootfh(&xdr, &hdr);
1970 encode_fsinfo(&xdr, lease_bitmap, &hdr); 2324 encode_fsinfo(&xdr, lease_bitmap, &hdr);
@@ -1979,11 +2333,12 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struc
1979{ 2333{
1980 struct xdr_stream xdr; 2334 struct xdr_stream xdr;
1981 struct compound_hdr hdr = { 2335 struct compound_hdr hdr = {
1982 .nops = 0, 2336 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1983 }; 2337 };
1984 2338
1985 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2339 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1986 encode_compound_hdr(&xdr, &hdr); 2340 encode_compound_hdr(&xdr, req, &hdr);
2341 encode_sequence(&xdr, &args->seq_args, &hdr);
1987 encode_putfh(&xdr, args->fhandle, &hdr); 2342 encode_putfh(&xdr, args->fhandle, &hdr);
1988 encode_delegreturn(&xdr, args->stateid, &hdr); 2343 encode_delegreturn(&xdr, args->stateid, &hdr);
1989 encode_getfattr(&xdr, args->bitmask, &hdr); 2344 encode_getfattr(&xdr, args->bitmask, &hdr);
@@ -1998,28 +2353,119 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
1998{ 2353{
1999 struct xdr_stream xdr; 2354 struct xdr_stream xdr;
2000 struct compound_hdr hdr = { 2355 struct compound_hdr hdr = {
2001 .nops = 0, 2356 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2002 }; 2357 };
2003 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 2358 uint32_t replen;
2004 int replen;
2005 2359
2006 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 2360 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2007 encode_compound_hdr(&xdr, &hdr); 2361 encode_compound_hdr(&xdr, req, &hdr);
2362 encode_sequence(&xdr, &args->seq_args, &hdr);
2008 encode_putfh(&xdr, args->dir_fh, &hdr); 2363 encode_putfh(&xdr, args->dir_fh, &hdr);
2009 encode_lookup(&xdr, args->name, &hdr); 2364 encode_lookup(&xdr, args->name, &hdr);
2365 replen = hdr.replen; /* get the attribute into args->page */
2010 encode_fs_locations(&xdr, args->bitmask, &hdr); 2366 encode_fs_locations(&xdr, args->bitmask, &hdr);
2011 2367
2012 /* set up reply 2368 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page,
2013 * toplevel_status + OP_PUTFH + status
2014 * + OP_LOOKUP + status + OP_GETATTR + status = 7
2015 */
2016 replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
2017 xdr_inline_pages(&req->rq_rcv_buf, replen, &args->page,
2018 0, PAGE_SIZE); 2369 0, PAGE_SIZE);
2019 encode_nops(&hdr); 2370 encode_nops(&hdr);
2020 return 0; 2371 return 0;
2021} 2372}
2022 2373
2374#if defined(CONFIG_NFS_V4_1)
2375/*
2376 * EXCHANGE_ID request
2377 */
2378static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
2379 struct nfs41_exchange_id_args *args)
2380{
2381 struct xdr_stream xdr;
2382 struct compound_hdr hdr = {
2383 .minorversion = args->client->cl_minorversion,
2384 };
2385
2386 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2387 encode_compound_hdr(&xdr, req, &hdr);
2388 encode_exchange_id(&xdr, args, &hdr);
2389 encode_nops(&hdr);
2390 return 0;
2391}
2392
2393/*
2394 * a CREATE_SESSION request
2395 */
2396static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p,
2397 struct nfs41_create_session_args *args)
2398{
2399 struct xdr_stream xdr;
2400 struct compound_hdr hdr = {
2401 .minorversion = args->client->cl_minorversion,
2402 };
2403
2404 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2405 encode_compound_hdr(&xdr, req, &hdr);
2406 encode_create_session(&xdr, args, &hdr);
2407 encode_nops(&hdr);
2408 return 0;
2409}
2410
2411/*
2412 * a DESTROY_SESSION request
2413 */
2414static int nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, uint32_t *p,
2415 struct nfs4_session *session)
2416{
2417 struct xdr_stream xdr;
2418 struct compound_hdr hdr = {
2419 .minorversion = session->clp->cl_minorversion,
2420 };
2421
2422 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2423 encode_compound_hdr(&xdr, req, &hdr);
2424 encode_destroy_session(&xdr, session, &hdr);
2425 encode_nops(&hdr);
2426 return 0;
2427}
2428
2429/*
2430 * a SEQUENCE request
2431 */
2432static int nfs4_xdr_enc_sequence(struct rpc_rqst *req, uint32_t *p,
2433 struct nfs4_sequence_args *args)
2434{
2435 struct xdr_stream xdr;
2436 struct compound_hdr hdr = {
2437 .minorversion = nfs4_xdr_minorversion(args),
2438 };
2439
2440 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2441 encode_compound_hdr(&xdr, req, &hdr);
2442 encode_sequence(&xdr, args, &hdr);
2443 encode_nops(&hdr);
2444 return 0;
2445}
2446
2447/*
2448 * a GET_LEASE_TIME request
2449 */
2450static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
2451 struct nfs4_get_lease_time_args *args)
2452{
2453 struct xdr_stream xdr;
2454 struct compound_hdr hdr = {
2455 .minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
2456 };
2457 const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
2458
2459 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2460 encode_compound_hdr(&xdr, req, &hdr);
2461 encode_sequence(&xdr, &args->la_seq_args, &hdr);
2462 encode_putrootfh(&xdr, &hdr);
2463 encode_fsinfo(&xdr, lease_bitmap, &hdr);
2464 encode_nops(&hdr);
2465 return 0;
2466}
2467#endif /* CONFIG_NFS_V4_1 */
2468
2023/* 2469/*
2024 * START OF "GENERIC" DECODE ROUTINES. 2470 * START OF "GENERIC" DECODE ROUTINES.
2025 * These may look a little ugly since they are imported from a "generic" 2471 * These may look a little ugly since they are imported from a "generic"
@@ -3657,7 +4103,7 @@ decode_savefh(struct xdr_stream *xdr)
3657 return decode_op_hdr(xdr, OP_SAVEFH); 4103 return decode_op_hdr(xdr, OP_SAVEFH);
3658} 4104}
3659 4105
3660static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res) 4106static int decode_setattr(struct xdr_stream *xdr)
3661{ 4107{
3662 __be32 *p; 4108 __be32 *p;
3663 uint32_t bmlen; 4109 uint32_t bmlen;
@@ -3735,6 +4181,169 @@ static int decode_delegreturn(struct xdr_stream *xdr)
3735 return decode_op_hdr(xdr, OP_DELEGRETURN); 4181 return decode_op_hdr(xdr, OP_DELEGRETURN);
3736} 4182}
3737 4183
4184#if defined(CONFIG_NFS_V4_1)
4185static int decode_exchange_id(struct xdr_stream *xdr,
4186 struct nfs41_exchange_id_res *res)
4187{
4188 __be32 *p;
4189 uint32_t dummy;
4190 int status;
4191 struct nfs_client *clp = res->client;
4192
4193 status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
4194 if (status)
4195 return status;
4196
4197 READ_BUF(8);
4198 READ64(clp->cl_ex_clid);
4199 READ_BUF(12);
4200 READ32(clp->cl_seqid);
4201 READ32(clp->cl_exchange_flags);
4202
4203 /* We ask for SP4_NONE */
4204 READ32(dummy);
4205 if (dummy != SP4_NONE)
4206 return -EIO;
4207
4208 /* Throw away minor_id */
4209 READ_BUF(8);
4210
4211 /* Throw away Major id */
4212 READ_BUF(4);
4213 READ32(dummy);
4214 READ_BUF(dummy);
4215
4216 /* Throw away server_scope */
4217 READ_BUF(4);
4218 READ32(dummy);
4219 READ_BUF(dummy);
4220
4221 /* Throw away Implementation id array */
4222 READ_BUF(4);
4223 READ32(dummy);
4224 READ_BUF(dummy);
4225
4226 return 0;
4227}
4228
4229static int decode_chan_attrs(struct xdr_stream *xdr,
4230 struct nfs4_channel_attrs *attrs)
4231{
4232 __be32 *p;
4233 u32 nr_attrs;
4234
4235 READ_BUF(28);
4236 READ32(attrs->headerpadsz);
4237 READ32(attrs->max_rqst_sz);
4238 READ32(attrs->max_resp_sz);
4239 READ32(attrs->max_resp_sz_cached);
4240 READ32(attrs->max_ops);
4241 READ32(attrs->max_reqs);
4242 READ32(nr_attrs);
4243 if (unlikely(nr_attrs > 1)) {
4244 printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n",
4245 __func__, nr_attrs);
4246 return -EINVAL;
4247 }
4248 if (nr_attrs == 1)
4249 READ_BUF(4); /* skip rdma_attrs */
4250 return 0;
4251}
4252
4253static int decode_create_session(struct xdr_stream *xdr,
4254 struct nfs41_create_session_res *res)
4255{
4256 __be32 *p;
4257 int status;
4258 struct nfs_client *clp = res->client;
4259 struct nfs4_session *session = clp->cl_session;
4260
4261 status = decode_op_hdr(xdr, OP_CREATE_SESSION);
4262
4263 if (status)
4264 return status;
4265
4266 /* sessionid */
4267 READ_BUF(NFS4_MAX_SESSIONID_LEN);
4268 COPYMEM(&session->sess_id, NFS4_MAX_SESSIONID_LEN);
4269
4270 /* seqid, flags */
4271 READ_BUF(8);
4272 READ32(clp->cl_seqid);
4273 READ32(session->flags);
4274
4275 /* Channel attributes */
4276 status = decode_chan_attrs(xdr, &session->fc_attrs);
4277 if (!status)
4278 status = decode_chan_attrs(xdr, &session->bc_attrs);
4279 return status;
4280}
4281
4282static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
4283{
4284 return decode_op_hdr(xdr, OP_DESTROY_SESSION);
4285}
4286#endif /* CONFIG_NFS_V4_1 */
4287
4288static int decode_sequence(struct xdr_stream *xdr,
4289 struct nfs4_sequence_res *res,
4290 struct rpc_rqst *rqstp)
4291{
4292#if defined(CONFIG_NFS_V4_1)
4293 struct nfs4_slot *slot;
4294 struct nfs4_sessionid id;
4295 u32 dummy;
4296 int status;
4297 __be32 *p;
4298
4299 if (!res->sr_session)
4300 return 0;
4301
4302 status = decode_op_hdr(xdr, OP_SEQUENCE);
4303 if (status)
4304 goto out_err;
4305
4306 /*
4307 * If the server returns different values for sessionID, slotID or
4308 * sequence number, the server is looney tunes.
4309 */
4310 status = -ESERVERFAULT;
4311
4312 slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
4313 READ_BUF(NFS4_MAX_SESSIONID_LEN + 20);
4314 COPYMEM(id.data, NFS4_MAX_SESSIONID_LEN);
4315 if (memcmp(id.data, res->sr_session->sess_id.data,
4316 NFS4_MAX_SESSIONID_LEN)) {
4317 dprintk("%s Invalid session id\n", __func__);
4318 goto out_err;
4319 }
4320 /* seqid */
4321 READ32(dummy);
4322 if (dummy != slot->seq_nr) {
4323 dprintk("%s Invalid sequence number\n", __func__);
4324 goto out_err;
4325 }
4326 /* slot id */
4327 READ32(dummy);
4328 if (dummy != res->sr_slotid) {
4329 dprintk("%s Invalid slot id\n", __func__);
4330 goto out_err;
4331 }
4332 /* highest slot id - currently not processed */
4333 READ32(dummy);
4334 /* target highest slot id - currently not processed */
4335 READ32(dummy);
4336 /* result flags - currently not processed */
4337 READ32(dummy);
4338 status = 0;
4339out_err:
4340 res->sr_status = status;
4341 return status;
4342#else /* CONFIG_NFS_V4_1 */
4343 return 0;
4344#endif /* CONFIG_NFS_V4_1 */
4345}
4346
3738/* 4347/*
3739 * END OF "GENERIC" DECODE ROUTINES. 4348 * END OF "GENERIC" DECODE ROUTINES.
3740 */ 4349 */
@@ -3752,6 +4361,9 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct
3752 status = decode_compound_hdr(&xdr, &hdr); 4361 status = decode_compound_hdr(&xdr, &hdr);
3753 if (status) 4362 if (status)
3754 goto out; 4363 goto out;
4364 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4365 if (status)
4366 goto out;
3755 status = decode_putfh(&xdr); 4367 status = decode_putfh(&xdr);
3756 if (status) 4368 if (status)
3757 goto out; 4369 goto out;
@@ -3773,7 +4385,11 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_ac
3773 int status; 4385 int status;
3774 4386
3775 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 4387 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3776 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) 4388 status = decode_compound_hdr(&xdr, &hdr);
4389 if (status)
4390 goto out;
4391 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4392 if (status)
3777 goto out; 4393 goto out;
3778 status = decode_putfh(&xdr); 4394 status = decode_putfh(&xdr);
3779 if (status != 0) 4395 if (status != 0)
@@ -3796,7 +4412,11 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lo
3796 int status; 4412 int status;
3797 4413
3798 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 4414 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3799 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) 4415 status = decode_compound_hdr(&xdr, &hdr);
4416 if (status)
4417 goto out;
4418 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4419 if (status)
3800 goto out; 4420 goto out;
3801 if ((status = decode_putfh(&xdr)) != 0) 4421 if ((status = decode_putfh(&xdr)) != 0)
3802 goto out; 4422 goto out;
@@ -3819,7 +4439,11 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nf
3819 int status; 4439 int status;
3820 4440
3821 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 4441 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3822 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) 4442 status = decode_compound_hdr(&xdr, &hdr);
4443 if (status)
4444 goto out;
4445 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4446 if (status)
3823 goto out; 4447 goto out;
3824 if ((status = decode_putrootfh(&xdr)) != 0) 4448 if ((status = decode_putrootfh(&xdr)) != 0)
3825 goto out; 4449 goto out;
@@ -3839,7 +4463,11 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_rem
3839 int status; 4463 int status;
3840 4464
3841 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 4465 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3842 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) 4466 status = decode_compound_hdr(&xdr, &hdr);
4467 if (status)
4468 goto out;
4469 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4470 if (status)
3843 goto out; 4471 goto out;
3844 if ((status = decode_putfh(&xdr)) != 0) 4472 if ((status = decode_putfh(&xdr)) != 0)
3845 goto out; 4473 goto out;
@@ -3860,7 +4488,11 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_re
3860 int status; 4488 int status;
3861 4489
3862 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 4490 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3863 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) 4491 status = decode_compound_hdr(&xdr, &hdr);
4492 if (status)
4493 goto out;
4494 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4495 if (status)
3864 goto out; 4496 goto out;
3865 if ((status = decode_putfh(&xdr)) != 0) 4497 if ((status = decode_putfh(&xdr)) != 0)
3866 goto out; 4498 goto out;
@@ -3890,7 +4522,11 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link
3890 int status; 4522 int status;
3891 4523
3892 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 4524 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3893 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) 4525 status = decode_compound_hdr(&xdr, &hdr);
4526 if (status)
4527 goto out;
4528 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4529 if (status)
3894 goto out; 4530 goto out;
3895 if ((status = decode_putfh(&xdr)) != 0) 4531 if ((status = decode_putfh(&xdr)) != 0)
3896 goto out; 4532 goto out;
@@ -3923,7 +4559,11 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_cr
3923 int status; 4559 int status;
3924 4560
3925 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 4561 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3926 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) 4562 status = decode_compound_hdr(&xdr, &hdr);
4563 if (status)
4564 goto out;
4565 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4566 if (status)
3927 goto out; 4567 goto out;
3928 if ((status = decode_putfh(&xdr)) != 0) 4568 if ((status = decode_putfh(&xdr)) != 0)
3929 goto out; 4569 goto out;
@@ -3963,6 +4603,9 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_g
3963 status = decode_compound_hdr(&xdr, &hdr); 4603 status = decode_compound_hdr(&xdr, &hdr);
3964 if (status) 4604 if (status)
3965 goto out; 4605 goto out;
4606 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4607 if (status)
4608 goto out;
3966 status = decode_putfh(&xdr); 4609 status = decode_putfh(&xdr);
3967 if (status) 4610 if (status)
3968 goto out; 4611 goto out;
@@ -3979,12 +4622,13 @@ nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args
3979{ 4622{
3980 struct xdr_stream xdr; 4623 struct xdr_stream xdr;
3981 struct compound_hdr hdr = { 4624 struct compound_hdr hdr = {
3982 .nops = 0, 4625 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
3983 }; 4626 };
3984 int status; 4627 int status;
3985 4628
3986 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 4629 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
3987 encode_compound_hdr(&xdr, &hdr); 4630 encode_compound_hdr(&xdr, req, &hdr);
4631 encode_sequence(&xdr, &args->seq_args, &hdr);
3988 encode_putfh(&xdr, args->fh, &hdr); 4632 encode_putfh(&xdr, args->fh, &hdr);
3989 status = encode_setacl(&xdr, args, &hdr); 4633 status = encode_setacl(&xdr, args, &hdr);
3990 encode_nops(&hdr); 4634 encode_nops(&hdr);
@@ -3995,7 +4639,8 @@ nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args
3995 * Decode SETACL response 4639 * Decode SETACL response
3996 */ 4640 */
3997static int 4641static int
3998nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p, void *res) 4642nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p,
4643 struct nfs_setaclres *res)
3999{ 4644{
4000 struct xdr_stream xdr; 4645 struct xdr_stream xdr;
4001 struct compound_hdr hdr; 4646 struct compound_hdr hdr;
@@ -4005,10 +4650,13 @@ nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p, void *res)
4005 status = decode_compound_hdr(&xdr, &hdr); 4650 status = decode_compound_hdr(&xdr, &hdr);
4006 if (status) 4651 if (status)
4007 goto out; 4652 goto out;
4653 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4654 if (status)
4655 goto out;
4008 status = decode_putfh(&xdr); 4656 status = decode_putfh(&xdr);
4009 if (status) 4657 if (status)
4010 goto out; 4658 goto out;
4011 status = decode_setattr(&xdr, res); 4659 status = decode_setattr(&xdr);
4012out: 4660out:
4013 return status; 4661 return status;
4014} 4662}
@@ -4017,7 +4665,8 @@ out:
4017 * Decode GETACL response 4665 * Decode GETACL response
4018 */ 4666 */
4019static int 4667static int
4020nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len) 4668nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p,
4669 struct nfs_getaclres *res)
4021{ 4670{
4022 struct xdr_stream xdr; 4671 struct xdr_stream xdr;
4023 struct compound_hdr hdr; 4672 struct compound_hdr hdr;
@@ -4027,10 +4676,13 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len)
4027 status = decode_compound_hdr(&xdr, &hdr); 4676 status = decode_compound_hdr(&xdr, &hdr);
4028 if (status) 4677 if (status)
4029 goto out; 4678 goto out;
4679 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4680 if (status)
4681 goto out;
4030 status = decode_putfh(&xdr); 4682 status = decode_putfh(&xdr);
4031 if (status) 4683 if (status)
4032 goto out; 4684 goto out;
4033 status = decode_getacl(&xdr, rqstp, acl_len); 4685 status = decode_getacl(&xdr, rqstp, &res->acl_len);
4034 4686
4035out: 4687out:
4036 return status; 4688 return status;
@@ -4049,6 +4701,9 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_clos
4049 status = decode_compound_hdr(&xdr, &hdr); 4701 status = decode_compound_hdr(&xdr, &hdr);
4050 if (status) 4702 if (status)
4051 goto out; 4703 goto out;
4704 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4705 if (status)
4706 goto out;
4052 status = decode_putfh(&xdr); 4707 status = decode_putfh(&xdr);
4053 if (status) 4708 if (status)
4054 goto out; 4709 goto out;
@@ -4079,6 +4734,9 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openr
4079 status = decode_compound_hdr(&xdr, &hdr); 4734 status = decode_compound_hdr(&xdr, &hdr);
4080 if (status) 4735 if (status)
4081 goto out; 4736 goto out;
4737 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4738 if (status)
4739 goto out;
4082 status = decode_putfh(&xdr); 4740 status = decode_putfh(&xdr);
4083 if (status) 4741 if (status)
4084 goto out; 4742 goto out;
@@ -4133,6 +4791,9 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nf
4133 status = decode_compound_hdr(&xdr, &hdr); 4791 status = decode_compound_hdr(&xdr, &hdr);
4134 if (status) 4792 if (status)
4135 goto out; 4793 goto out;
4794 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4795 if (status)
4796 goto out;
4136 status = decode_putfh(&xdr); 4797 status = decode_putfh(&xdr);
4137 if (status) 4798 if (status)
4138 goto out; 4799 goto out;
@@ -4157,10 +4818,13 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_se
4157 status = decode_compound_hdr(&xdr, &hdr); 4818 status = decode_compound_hdr(&xdr, &hdr);
4158 if (status) 4819 if (status)
4159 goto out; 4820 goto out;
4821 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4822 if (status)
4823 goto out;
4160 status = decode_putfh(&xdr); 4824 status = decode_putfh(&xdr);
4161 if (status) 4825 if (status)
4162 goto out; 4826 goto out;
4163 status = decode_setattr(&xdr, res); 4827 status = decode_setattr(&xdr);
4164 if (status) 4828 if (status)
4165 goto out; 4829 goto out;
4166 decode_getfattr(&xdr, res->fattr, res->server); 4830 decode_getfattr(&xdr, res->fattr, res->server);
@@ -4181,6 +4845,9 @@ static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_
4181 status = decode_compound_hdr(&xdr, &hdr); 4845 status = decode_compound_hdr(&xdr, &hdr);
4182 if (status) 4846 if (status)
4183 goto out; 4847 goto out;
4848 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4849 if (status)
4850 goto out;
4184 status = decode_putfh(&xdr); 4851 status = decode_putfh(&xdr);
4185 if (status) 4852 if (status)
4186 goto out; 4853 goto out;
@@ -4202,6 +4869,9 @@ static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock
4202 status = decode_compound_hdr(&xdr, &hdr); 4869 status = decode_compound_hdr(&xdr, &hdr);
4203 if (status) 4870 if (status)
4204 goto out; 4871 goto out;
4872 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4873 if (status)
4874 goto out;
4205 status = decode_putfh(&xdr); 4875 status = decode_putfh(&xdr);
4206 if (status) 4876 if (status)
4207 goto out; 4877 goto out;
@@ -4223,6 +4893,9 @@ static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock
4223 status = decode_compound_hdr(&xdr, &hdr); 4893 status = decode_compound_hdr(&xdr, &hdr);
4224 if (status) 4894 if (status)
4225 goto out; 4895 goto out;
4896 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4897 if (status)
4898 goto out;
4226 status = decode_putfh(&xdr); 4899 status = decode_putfh(&xdr);
4227 if (status) 4900 if (status)
4228 goto out; 4901 goto out;
@@ -4234,7 +4907,8 @@ out:
4234/* 4907/*
4235 * Decode READLINK response 4908 * Decode READLINK response
4236 */ 4909 */
4237static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res) 4910static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p,
4911 struct nfs4_readlink_res *res)
4238{ 4912{
4239 struct xdr_stream xdr; 4913 struct xdr_stream xdr;
4240 struct compound_hdr hdr; 4914 struct compound_hdr hdr;
@@ -4244,6 +4918,9 @@ static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res)
4244 status = decode_compound_hdr(&xdr, &hdr); 4918 status = decode_compound_hdr(&xdr, &hdr);
4245 if (status) 4919 if (status)
4246 goto out; 4920 goto out;
4921 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4922 if (status)
4923 goto out;
4247 status = decode_putfh(&xdr); 4924 status = decode_putfh(&xdr);
4248 if (status) 4925 if (status)
4249 goto out; 4926 goto out;
@@ -4265,6 +4942,9 @@ static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_r
4265 status = decode_compound_hdr(&xdr, &hdr); 4942 status = decode_compound_hdr(&xdr, &hdr);
4266 if (status) 4943 if (status)
4267 goto out; 4944 goto out;
4945 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4946 if (status)
4947 goto out;
4268 status = decode_putfh(&xdr); 4948 status = decode_putfh(&xdr);
4269 if (status) 4949 if (status)
4270 goto out; 4950 goto out;
@@ -4286,6 +4966,9 @@ static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readr
4286 status = decode_compound_hdr(&xdr, &hdr); 4966 status = decode_compound_hdr(&xdr, &hdr);
4287 if (status) 4967 if (status)
4288 goto out; 4968 goto out;
4969 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4970 if (status)
4971 goto out;
4289 status = decode_putfh(&xdr); 4972 status = decode_putfh(&xdr);
4290 if (status) 4973 if (status)
4291 goto out; 4974 goto out;
@@ -4309,6 +4992,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writ
4309 status = decode_compound_hdr(&xdr, &hdr); 4992 status = decode_compound_hdr(&xdr, &hdr);
4310 if (status) 4993 if (status)
4311 goto out; 4994 goto out;
4995 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4996 if (status)
4997 goto out;
4312 status = decode_putfh(&xdr); 4998 status = decode_putfh(&xdr);
4313 if (status) 4999 if (status)
4314 goto out; 5000 goto out;
@@ -4335,6 +5021,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_wri
4335 status = decode_compound_hdr(&xdr, &hdr); 5021 status = decode_compound_hdr(&xdr, &hdr);
4336 if (status) 5022 if (status)
4337 goto out; 5023 goto out;
5024 status = decode_sequence(&xdr, &res->seq_res, rqstp);
5025 if (status)
5026 goto out;
4338 status = decode_putfh(&xdr); 5027 status = decode_putfh(&xdr);
4339 if (status) 5028 if (status)
4340 goto out; 5029 goto out;
@@ -4349,7 +5038,8 @@ out:
4349/* 5038/*
4350 * FSINFO request 5039 * FSINFO request
4351 */ 5040 */
4352static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo) 5041static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
5042 struct nfs4_fsinfo_res *res)
4353{ 5043{
4354 struct xdr_stream xdr; 5044 struct xdr_stream xdr;
4355 struct compound_hdr hdr; 5045 struct compound_hdr hdr;
@@ -4358,16 +5048,19 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
4358 xdr_init_decode(&xdr, &req->rq_rcv_buf, p); 5048 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4359 status = decode_compound_hdr(&xdr, &hdr); 5049 status = decode_compound_hdr(&xdr, &hdr);
4360 if (!status) 5050 if (!status)
5051 status = decode_sequence(&xdr, &res->seq_res, req);
5052 if (!status)
4361 status = decode_putfh(&xdr); 5053 status = decode_putfh(&xdr);
4362 if (!status) 5054 if (!status)
4363 status = decode_fsinfo(&xdr, fsinfo); 5055 status = decode_fsinfo(&xdr, res->fsinfo);
4364 return status; 5056 return status;
4365} 5057}
4366 5058
4367/* 5059/*
4368 * PATHCONF request 5060 * PATHCONF request
4369 */ 5061 */
4370static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *pathconf) 5062static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
5063 struct nfs4_pathconf_res *res)
4371{ 5064{
4372 struct xdr_stream xdr; 5065 struct xdr_stream xdr;
4373 struct compound_hdr hdr; 5066 struct compound_hdr hdr;
@@ -4376,16 +5069,19 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pat
4376 xdr_init_decode(&xdr, &req->rq_rcv_buf, p); 5069 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4377 status = decode_compound_hdr(&xdr, &hdr); 5070 status = decode_compound_hdr(&xdr, &hdr);
4378 if (!status) 5071 if (!status)
5072 status = decode_sequence(&xdr, &res->seq_res, req);
5073 if (!status)
4379 status = decode_putfh(&xdr); 5074 status = decode_putfh(&xdr);
4380 if (!status) 5075 if (!status)
4381 status = decode_pathconf(&xdr, pathconf); 5076 status = decode_pathconf(&xdr, res->pathconf);
4382 return status; 5077 return status;
4383} 5078}
4384 5079
4385/* 5080/*
4386 * STATFS request 5081 * STATFS request
4387 */ 5082 */
4388static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *fsstat) 5083static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
5084 struct nfs4_statfs_res *res)
4389{ 5085{
4390 struct xdr_stream xdr; 5086 struct xdr_stream xdr;
4391 struct compound_hdr hdr; 5087 struct compound_hdr hdr;
@@ -4394,9 +5090,11 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fssta
4394 xdr_init_decode(&xdr, &req->rq_rcv_buf, p); 5090 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4395 status = decode_compound_hdr(&xdr, &hdr); 5091 status = decode_compound_hdr(&xdr, &hdr);
4396 if (!status) 5092 if (!status)
5093 status = decode_sequence(&xdr, &res->seq_res, req);
5094 if (!status)
4397 status = decode_putfh(&xdr); 5095 status = decode_putfh(&xdr);
4398 if (!status) 5096 if (!status)
4399 status = decode_statfs(&xdr, fsstat); 5097 status = decode_statfs(&xdr, res->fsstat);
4400 return status; 5098 return status;
4401} 5099}
4402 5100
@@ -4410,7 +5108,11 @@ static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4
4410 int status; 5108 int status;
4411 5109
4412 xdr_init_decode(&xdr, &req->rq_rcv_buf, p); 5110 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4413 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) 5111 status = decode_compound_hdr(&xdr, &hdr);
5112 if (status)
5113 goto out;
5114 status = decode_sequence(&xdr, &res->seq_res, req);
5115 if (status)
4414 goto out; 5116 goto out;
4415 if ((status = decode_putfh(&xdr)) != 0) 5117 if ((status = decode_putfh(&xdr)) != 0)
4416 goto out; 5118 goto out;
@@ -4483,7 +5185,10 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf
4483 5185
4484 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 5186 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4485 status = decode_compound_hdr(&xdr, &hdr); 5187 status = decode_compound_hdr(&xdr, &hdr);
4486 if (status != 0) 5188 if (status)
5189 goto out;
5190 status = decode_sequence(&xdr, &res->seq_res, rqstp);
5191 if (status)
4487 goto out; 5192 goto out;
4488 status = decode_putfh(&xdr); 5193 status = decode_putfh(&xdr);
4489 if (status != 0) 5194 if (status != 0)
@@ -4497,7 +5202,8 @@ out:
4497/* 5202/*
4498 * FS_LOCATIONS request 5203 * FS_LOCATIONS request
4499 */ 5204 */
4500static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations *res) 5205static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
5206 struct nfs4_fs_locations_res *res)
4501{ 5207{
4502 struct xdr_stream xdr; 5208 struct xdr_stream xdr;
4503 struct compound_hdr hdr; 5209 struct compound_hdr hdr;
@@ -4505,18 +5211,113 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
4505 5211
4506 xdr_init_decode(&xdr, &req->rq_rcv_buf, p); 5212 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4507 status = decode_compound_hdr(&xdr, &hdr); 5213 status = decode_compound_hdr(&xdr, &hdr);
4508 if (status != 0) 5214 if (status)
5215 goto out;
5216 status = decode_sequence(&xdr, &res->seq_res, req);
5217 if (status)
4509 goto out; 5218 goto out;
4510 if ((status = decode_putfh(&xdr)) != 0) 5219 if ((status = decode_putfh(&xdr)) != 0)
4511 goto out; 5220 goto out;
4512 if ((status = decode_lookup(&xdr)) != 0) 5221 if ((status = decode_lookup(&xdr)) != 0)
4513 goto out; 5222 goto out;
4514 xdr_enter_page(&xdr, PAGE_SIZE); 5223 xdr_enter_page(&xdr, PAGE_SIZE);
4515 status = decode_getfattr(&xdr, &res->fattr, res->server); 5224 status = decode_getfattr(&xdr, &res->fs_locations->fattr,
5225 res->fs_locations->server);
4516out: 5226out:
4517 return status; 5227 return status;
4518} 5228}
4519 5229
5230#if defined(CONFIG_NFS_V4_1)
5231/*
5232 * EXCHANGE_ID request
5233 */
5234static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
5235 void *res)
5236{
5237 struct xdr_stream xdr;
5238 struct compound_hdr hdr;
5239 int status;
5240
5241 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5242 status = decode_compound_hdr(&xdr, &hdr);
5243 if (!status)
5244 status = decode_exchange_id(&xdr, res);
5245 return status;
5246}
5247
5248/*
5249 * a CREATE_SESSION request
5250 */
5251static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
5252 struct nfs41_create_session_res *res)
5253{
5254 struct xdr_stream xdr;
5255 struct compound_hdr hdr;
5256 int status;
5257
5258 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5259 status = decode_compound_hdr(&xdr, &hdr);
5260 if (!status)
5261 status = decode_create_session(&xdr, res);
5262 return status;
5263}
5264
5265/*
5266 * a DESTROY_SESSION request
5267 */
5268static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
5269 void *dummy)
5270{
5271 struct xdr_stream xdr;
5272 struct compound_hdr hdr;
5273 int status;
5274
5275 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5276 status = decode_compound_hdr(&xdr, &hdr);
5277 if (!status)
5278 status = decode_destroy_session(&xdr, dummy);
5279 return status;
5280}
5281
5282/*
5283 * a SEQUENCE request
5284 */
5285static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
5286 struct nfs4_sequence_res *res)
5287{
5288 struct xdr_stream xdr;
5289 struct compound_hdr hdr;
5290 int status;
5291
5292 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5293 status = decode_compound_hdr(&xdr, &hdr);
5294 if (!status)
5295 status = decode_sequence(&xdr, res, rqstp);
5296 return status;
5297}
5298
5299/*
5300 * a GET_LEASE_TIME request
5301 */
5302static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
5303 struct nfs4_get_lease_time_res *res)
5304{
5305 struct xdr_stream xdr;
5306 struct compound_hdr hdr;
5307 int status;
5308
5309 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5310 status = decode_compound_hdr(&xdr, &hdr);
5311 if (!status)
5312 status = decode_sequence(&xdr, &res->lr_seq_res, rqstp);
5313 if (!status)
5314 status = decode_putrootfh(&xdr);
5315 if (!status)
5316 status = decode_fsinfo(&xdr, res->lr_fsinfo);
5317 return status;
5318}
5319#endif /* CONFIG_NFS_V4_1 */
5320
4520__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 5321__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
4521{ 5322{
4522 uint32_t bitmap[2] = {0}; 5323 uint32_t bitmap[2] = {0};
@@ -4686,6 +5487,13 @@ struct rpc_procinfo nfs4_procedures[] = {
4686 PROC(GETACL, enc_getacl, dec_getacl), 5487 PROC(GETACL, enc_getacl, dec_getacl),
4687 PROC(SETACL, enc_setacl, dec_setacl), 5488 PROC(SETACL, enc_setacl, dec_setacl),
4688 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), 5489 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
5490#if defined(CONFIG_NFS_V4_1)
5491 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
5492 PROC(CREATE_SESSION, enc_create_session, dec_create_session),
5493 PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session),
5494 PROC(SEQUENCE, enc_sequence, dec_sequence),
5495 PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
5496#endif /* CONFIG_NFS_V4_1 */
4689}; 5497};
4690 5498
4691struct rpc_version nfs_version4 = { 5499struct rpc_version nfs_version4 = {
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 4ace3c50a8eb..96c4ebfa46f4 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -22,6 +22,7 @@
22 22
23#include <asm/system.h> 23#include <asm/system.h>
24 24
25#include "nfs4_fs.h"
25#include "internal.h" 26#include "internal.h"
26#include "iostat.h" 27#include "iostat.h"
27#include "fscache.h" 28#include "fscache.h"
@@ -46,6 +47,7 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
46 memset(p, 0, sizeof(*p)); 47 memset(p, 0, sizeof(*p));
47 INIT_LIST_HEAD(&p->pages); 48 INIT_LIST_HEAD(&p->pages);
48 p->npages = pagecount; 49 p->npages = pagecount;
50 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
49 if (pagecount <= ARRAY_SIZE(p->page_array)) 51 if (pagecount <= ARRAY_SIZE(p->page_array))
50 p->pagevec = p->page_array; 52 p->pagevec = p->page_array;
51 else { 53 else {
@@ -357,19 +359,25 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
357 struct nfs_readres *resp = &data->res; 359 struct nfs_readres *resp = &data->res;
358 360
359 if (resp->eof || resp->count == argp->count) 361 if (resp->eof || resp->count == argp->count)
360 return; 362 goto out;
361 363
362 /* This is a short read! */ 364 /* This is a short read! */
363 nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); 365 nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
364 /* Has the server at least made some progress? */ 366 /* Has the server at least made some progress? */
365 if (resp->count == 0) 367 if (resp->count == 0)
366 return; 368 goto out;
367 369
368 /* Yes, so retry the read at the end of the data */ 370 /* Yes, so retry the read at the end of the data */
369 argp->offset += resp->count; 371 argp->offset += resp->count;
370 argp->pgbase += resp->count; 372 argp->pgbase += resp->count;
371 argp->count -= resp->count; 373 argp->count -= resp->count;
372 rpc_restart_call(task); 374 nfs4_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client);
375 return;
376out:
377 nfs4_sequence_free_slot(NFS_SERVER(data->inode)->nfs_client,
378 &data->res.seq_res);
379 return;
380
373} 381}
374 382
375/* 383/*
@@ -406,7 +414,23 @@ static void nfs_readpage_release_partial(void *calldata)
406 nfs_readdata_release(calldata); 414 nfs_readdata_release(calldata);
407} 415}
408 416
417#if defined(CONFIG_NFS_V4_1)
418void nfs_read_prepare(struct rpc_task *task, void *calldata)
419{
420 struct nfs_read_data *data = calldata;
421
422 if (nfs4_setup_sequence(NFS_SERVER(data->inode)->nfs_client,
423 &data->args.seq_args, &data->res.seq_res,
424 0, task))
425 return;
426 rpc_call_start(task);
427}
428#endif /* CONFIG_NFS_V4_1 */
429
409static const struct rpc_call_ops nfs_read_partial_ops = { 430static const struct rpc_call_ops nfs_read_partial_ops = {
431#if defined(CONFIG_NFS_V4_1)
432 .rpc_call_prepare = nfs_read_prepare,
433#endif /* CONFIG_NFS_V4_1 */
410 .rpc_call_done = nfs_readpage_result_partial, 434 .rpc_call_done = nfs_readpage_result_partial,
411 .rpc_release = nfs_readpage_release_partial, 435 .rpc_release = nfs_readpage_release_partial,
412}; 436};
@@ -470,6 +494,9 @@ static void nfs_readpage_release_full(void *calldata)
470} 494}
471 495
472static const struct rpc_call_ops nfs_read_full_ops = { 496static const struct rpc_call_ops nfs_read_full_ops = {
497#if defined(CONFIG_NFS_V4_1)
498 .rpc_call_prepare = nfs_read_prepare,
499#endif /* CONFIG_NFS_V4_1 */
473 .rpc_call_done = nfs_readpage_result_full, 500 .rpc_call_done = nfs_readpage_result_full,
474 .rpc_release = nfs_readpage_release_full, 501 .rpc_release = nfs_readpage_release_full,
475}; 502};
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 26127b69a275..6063054455f8 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -90,6 +90,7 @@ enum {
90 Opt_mountport, 90 Opt_mountport,
91 Opt_mountvers, 91 Opt_mountvers,
92 Opt_nfsvers, 92 Opt_nfsvers,
93 Opt_minorversion,
93 94
94 /* Mount options that take string arguments */ 95 /* Mount options that take string arguments */
95 Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, 96 Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
@@ -155,6 +156,7 @@ static const match_table_t nfs_mount_option_tokens = {
155 { Opt_mountvers, "mountvers=%u" }, 156 { Opt_mountvers, "mountvers=%u" },
156 { Opt_nfsvers, "nfsvers=%u" }, 157 { Opt_nfsvers, "nfsvers=%u" },
157 { Opt_nfsvers, "vers=%u" }, 158 { Opt_nfsvers, "vers=%u" },
159 { Opt_minorversion, "minorversion=%u" },
158 160
159 { Opt_sec, "sec=%s" }, 161 { Opt_sec, "sec=%s" },
160 { Opt_proto, "proto=%s" }, 162 { Opt_proto, "proto=%s" },
@@ -1211,6 +1213,13 @@ static int nfs_parse_mount_options(char *raw,
1211 nfs_parse_invalid_value("nfsvers"); 1213 nfs_parse_invalid_value("nfsvers");
1212 } 1214 }
1213 break; 1215 break;
1216 case Opt_minorversion:
1217 if (match_int(args, &option))
1218 return 0;
1219 if (option < 0 || option > NFS4_MAX_MINOR_VERSION)
1220 return 0;
1221 mnt->minorversion = option;
1222 break;
1214 1223
1215 /* 1224 /*
1216 * options that take text values 1225 * options that take text values
@@ -2263,6 +2272,7 @@ static int nfs4_validate_mount_data(void *options,
2263 args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */ 2272 args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */
2264 args->auth_flavors[0] = RPC_AUTH_UNIX; 2273 args->auth_flavors[0] = RPC_AUTH_UNIX;
2265 args->auth_flavor_len = 0; 2274 args->auth_flavor_len = 0;
2275 args->minorversion = 0;
2266 2276
2267 switch (data->version) { 2277 switch (data->version) {
2268 case 1: 2278 case 1:
@@ -2477,12 +2487,13 @@ static void nfs4_kill_super(struct super_block *sb)
2477{ 2487{
2478 struct nfs_server *server = NFS_SB(sb); 2488 struct nfs_server *server = NFS_SB(sb);
2479 2489
2490 dprintk("--> %s\n", __func__);
2480 nfs_super_return_all_delegations(sb); 2491 nfs_super_return_all_delegations(sb);
2481 kill_anon_super(sb); 2492 kill_anon_super(sb);
2482
2483 nfs4_renewd_prepare_shutdown(server); 2493 nfs4_renewd_prepare_shutdown(server);
2484 nfs_fscache_release_super_cookie(sb); 2494 nfs_fscache_release_super_cookie(sb);
2485 nfs_free_server(server); 2495 nfs_free_server(server);
2496 dprintk("<-- %s\n", __func__);
2486} 2497}
2487 2498
2488/* 2499/*
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index ecc295347775..1064c91ae810 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -15,6 +15,7 @@
15#include <linux/wait.h> 15#include <linux/wait.h>
16 16
17#include "internal.h" 17#include "internal.h"
18#include "nfs4_fs.h"
18 19
19struct nfs_unlinkdata { 20struct nfs_unlinkdata {
20 struct hlist_node list; 21 struct hlist_node list;
@@ -82,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
82 struct inode *dir = data->dir; 83 struct inode *dir = data->dir;
83 84
84 if (!NFS_PROTO(dir)->unlink_done(task, dir)) 85 if (!NFS_PROTO(dir)->unlink_done(task, dir))
85 rpc_restart_call(task); 86 nfs4_restart_rpc(task, NFS_SERVER(dir)->nfs_client);
86} 87}
87 88
88/** 89/**
@@ -102,9 +103,25 @@ static void nfs_async_unlink_release(void *calldata)
102 nfs_sb_deactive(sb); 103 nfs_sb_deactive(sb);
103} 104}
104 105
106#if defined(CONFIG_NFS_V4_1)
107void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
108{
109 struct nfs_unlinkdata *data = calldata;
110 struct nfs_server *server = NFS_SERVER(data->dir);
111
112 if (nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
113 &data->res.seq_res, 1, task))
114 return;
115 rpc_call_start(task);
116}
117#endif /* CONFIG_NFS_V4_1 */
118
105static const struct rpc_call_ops nfs_unlink_ops = { 119static const struct rpc_call_ops nfs_unlink_ops = {
106 .rpc_call_done = nfs_async_unlink_done, 120 .rpc_call_done = nfs_async_unlink_done,
107 .rpc_release = nfs_async_unlink_release, 121 .rpc_release = nfs_async_unlink_release,
122#if defined(CONFIG_NFS_V4_1)
123 .rpc_call_prepare = nfs_unlink_prepare,
124#endif /* CONFIG_NFS_V4_1 */
108}; 125};
109 126
110static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data) 127static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data)
@@ -241,6 +258,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
241 status = PTR_ERR(data->cred); 258 status = PTR_ERR(data->cred);
242 goto out_free; 259 goto out_free;
243 } 260 }
261 data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
244 262
245 status = -EBUSY; 263 status = -EBUSY;
246 spin_lock(&dentry->d_lock); 264 spin_lock(&dentry->d_lock);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e560a78995a3..ce728829f79a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -25,6 +25,7 @@
25#include "delegation.h" 25#include "delegation.h"
26#include "internal.h" 26#include "internal.h"
27#include "iostat.h" 27#include "iostat.h"
28#include "nfs4_fs.h"
28 29
29#define NFSDBG_FACILITY NFSDBG_PAGECACHE 30#define NFSDBG_FACILITY NFSDBG_PAGECACHE
30 31
@@ -52,6 +53,7 @@ struct nfs_write_data *nfs_commitdata_alloc(void)
52 if (p) { 53 if (p) {
53 memset(p, 0, sizeof(*p)); 54 memset(p, 0, sizeof(*p));
54 INIT_LIST_HEAD(&p->pages); 55 INIT_LIST_HEAD(&p->pages);
56 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
55 } 57 }
56 return p; 58 return p;
57} 59}
@@ -71,6 +73,7 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
71 memset(p, 0, sizeof(*p)); 73 memset(p, 0, sizeof(*p));
72 INIT_LIST_HEAD(&p->pages); 74 INIT_LIST_HEAD(&p->pages);
73 p->npages = pagecount; 75 p->npages = pagecount;
76 p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
74 if (pagecount <= ARRAY_SIZE(p->page_array)) 77 if (pagecount <= ARRAY_SIZE(p->page_array))
75 p->pagevec = p->page_array; 78 p->pagevec = p->page_array;
76 else { 79 else {
@@ -1048,7 +1051,23 @@ out:
1048 nfs_writedata_release(calldata); 1051 nfs_writedata_release(calldata);
1049} 1052}
1050 1053
1054#if defined(CONFIG_NFS_V4_1)
1055void nfs_write_prepare(struct rpc_task *task, void *calldata)
1056{
1057 struct nfs_write_data *data = calldata;
1058 struct nfs_client *clp = (NFS_SERVER(data->inode))->nfs_client;
1059
1060 if (nfs4_setup_sequence(clp, &data->args.seq_args,
1061 &data->res.seq_res, 1, task))
1062 return;
1063 rpc_call_start(task);
1064}
1065#endif /* CONFIG_NFS_V4_1 */
1066
1051static const struct rpc_call_ops nfs_write_partial_ops = { 1067static const struct rpc_call_ops nfs_write_partial_ops = {
1068#if defined(CONFIG_NFS_V4_1)
1069 .rpc_call_prepare = nfs_write_prepare,
1070#endif /* CONFIG_NFS_V4_1 */
1052 .rpc_call_done = nfs_writeback_done_partial, 1071 .rpc_call_done = nfs_writeback_done_partial,
1053 .rpc_release = nfs_writeback_release_partial, 1072 .rpc_release = nfs_writeback_release_partial,
1054}; 1073};
@@ -1111,6 +1130,9 @@ remove_request:
1111} 1130}
1112 1131
1113static const struct rpc_call_ops nfs_write_full_ops = { 1132static const struct rpc_call_ops nfs_write_full_ops = {
1133#if defined(CONFIG_NFS_V4_1)
1134 .rpc_call_prepare = nfs_write_prepare,
1135#endif /* CONFIG_NFS_V4_1 */
1114 .rpc_call_done = nfs_writeback_done_full, 1136 .rpc_call_done = nfs_writeback_done_full,
1115 .rpc_release = nfs_writeback_release_full, 1137 .rpc_release = nfs_writeback_release_full,
1116}; 1138};
@@ -1123,6 +1145,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
1123{ 1145{
1124 struct nfs_writeargs *argp = &data->args; 1146 struct nfs_writeargs *argp = &data->args;
1125 struct nfs_writeres *resp = &data->res; 1147 struct nfs_writeres *resp = &data->res;
1148 struct nfs_server *server = NFS_SERVER(data->inode);
1126 int status; 1149 int status;
1127 1150
1128 dprintk("NFS: %5u nfs_writeback_done (status %d)\n", 1151 dprintk("NFS: %5u nfs_writeback_done (status %d)\n",
@@ -1155,7 +1178,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
1155 if (time_before(complain, jiffies)) { 1178 if (time_before(complain, jiffies)) {
1156 dprintk("NFS: faulty NFS server %s:" 1179 dprintk("NFS: faulty NFS server %s:"
1157 " (committed = %d) != (stable = %d)\n", 1180 " (committed = %d) != (stable = %d)\n",
1158 NFS_SERVER(data->inode)->nfs_client->cl_hostname, 1181 server->nfs_client->cl_hostname,
1159 resp->verf->committed, argp->stable); 1182 resp->verf->committed, argp->stable);
1160 complain = jiffies + 300 * HZ; 1183 complain = jiffies + 300 * HZ;
1161 } 1184 }
@@ -1181,7 +1204,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
1181 */ 1204 */
1182 argp->stable = NFS_FILE_SYNC; 1205 argp->stable = NFS_FILE_SYNC;
1183 } 1206 }
1184 rpc_restart_call(task); 1207 nfs4_restart_rpc(task, server->nfs_client);
1185 return -EAGAIN; 1208 return -EAGAIN;
1186 } 1209 }
1187 if (time_before(complain, jiffies)) { 1210 if (time_before(complain, jiffies)) {
@@ -1193,6 +1216,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
1193 /* Can't do anything about it except throw an error. */ 1216 /* Can't do anything about it except throw an error. */
1194 task->tk_status = -EIO; 1217 task->tk_status = -EIO;
1195 } 1218 }
1219 nfs4_sequence_free_slot(server->nfs_client, &data->res.seq_res);
1196 return 0; 1220 return 0;
1197} 1221}
1198 1222
@@ -1349,6 +1373,9 @@ static void nfs_commit_release(void *calldata)
1349} 1373}
1350 1374
1351static const struct rpc_call_ops nfs_commit_ops = { 1375static const struct rpc_call_ops nfs_commit_ops = {
1376#if defined(CONFIG_NFS_V4_1)
1377 .rpc_call_prepare = nfs_write_prepare,
1378#endif /* CONFIG_NFS_V4_1 */
1352 .rpc_call_done = nfs_commit_done, 1379 .rpc_call_done = nfs_commit_done,
1353 .rpc_release = nfs_commit_release, 1380 .rpc_release = nfs_commit_release,
1354}; 1381};
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index e3f0cbcbd0db..bd2eba530667 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -21,6 +21,7 @@
21#define NFS4_FHSIZE 128 21#define NFS4_FHSIZE 128
22#define NFS4_MAXPATHLEN PATH_MAX 22#define NFS4_MAXPATHLEN PATH_MAX
23#define NFS4_MAXNAMLEN NAME_MAX 23#define NFS4_MAXNAMLEN NAME_MAX
24#define NFS4_OPAQUE_LIMIT 1024
24#define NFS4_MAX_SESSIONID_LEN 16 25#define NFS4_MAX_SESSIONID_LEN 16
25 26
26#define NFS4_ACCESS_READ 0x0001 27#define NFS4_ACCESS_READ 0x0001
@@ -130,6 +131,16 @@
130 131
131#define NFS4_MAX_UINT64 (~(u64)0) 132#define NFS4_MAX_UINT64 (~(u64)0)
132 133
134/* An NFS4 sessions server must support at least NFS4_MAX_OPS operations.
135 * If a compound requires more operations, adjust NFS4_MAX_OPS accordingly.
136 */
137#define NFS4_MAX_OPS 8
138
139/* Our NFS4 client back channel server only wants the cb_sequene and the
140 * actual operation per compound
141 */
142#define NFS4_MAX_BACK_CHANNEL_OPS 2
143
133enum nfs4_acl_whotype { 144enum nfs4_acl_whotype {
134 NFS4_ACL_WHO_NAMED = 0, 145 NFS4_ACL_WHO_NAMED = 0,
135 NFS4_ACL_WHO_OWNER, 146 NFS4_ACL_WHO_OWNER,
@@ -462,6 +473,13 @@ enum lock_type4 {
462#define NFSPROC4_NULL 0 473#define NFSPROC4_NULL 0
463#define NFSPROC4_COMPOUND 1 474#define NFSPROC4_COMPOUND 1
464#define NFS4_MINOR_VERSION 0 475#define NFS4_MINOR_VERSION 0
476
477#if defined(CONFIG_NFS_V4_1)
478#define NFS4_MAX_MINOR_VERSION 1
479#else
480#define NFS4_MAX_MINOR_VERSION 0
481#endif /* CONFIG_NFS_V4_1 */
482
465#define NFS4_DEBUG 1 483#define NFS4_DEBUG 1
466 484
467/* Index of predefined Linux client operations */ 485/* Index of predefined Linux client operations */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 6ad75948cbf7..19fe15d12042 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -4,11 +4,17 @@
4#include <linux/list.h> 4#include <linux/list.h>
5#include <linux/backing-dev.h> 5#include <linux/backing-dev.h>
6#include <linux/wait.h> 6#include <linux/wait.h>
7#include <linux/nfs_xdr.h>
8#include <linux/sunrpc/xprt.h>
7 9
8#include <asm/atomic.h> 10#include <asm/atomic.h>
9 11
12struct nfs4_session;
10struct nfs_iostats; 13struct nfs_iostats;
11struct nlm_host; 14struct nlm_host;
15struct nfs4_sequence_args;
16struct nfs4_sequence_res;
17struct nfs_server;
12 18
13/* 19/*
14 * The nfs_client identifies our client state to the server. 20 * The nfs_client identifies our client state to the server.
@@ -18,6 +24,7 @@ struct nfs_client {
18 int cl_cons_state; /* current construction state (-ve: init error) */ 24 int cl_cons_state; /* current construction state (-ve: init error) */
19#define NFS_CS_READY 0 /* ready to be used */ 25#define NFS_CS_READY 0 /* ready to be used */
20#define NFS_CS_INITING 1 /* busy initialising */ 26#define NFS_CS_INITING 1 /* busy initialising */
27#define NFS_CS_SESSION_INITING 2 /* busy initialising session */
21 unsigned long cl_res_state; /* NFS resources state */ 28 unsigned long cl_res_state; /* NFS resources state */
22#define NFS_CS_CALLBACK 1 /* - callback started */ 29#define NFS_CS_CALLBACK 1 /* - callback started */
23#define NFS_CS_IDMAP 2 /* - idmap started */ 30#define NFS_CS_IDMAP 2 /* - idmap started */
@@ -32,6 +39,7 @@ struct nfs_client {
32 const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ 39 const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */
33 int cl_proto; /* Network transport protocol */ 40 int cl_proto; /* Network transport protocol */
34 41
42 u32 cl_minorversion;/* NFSv4 minorversion */
35 struct rpc_cred *cl_machine_cred; 43 struct rpc_cred *cl_machine_cred;
36 44
37#ifdef CONFIG_NFS_V4 45#ifdef CONFIG_NFS_V4
@@ -63,7 +71,22 @@ struct nfs_client {
63 */ 71 */
64 char cl_ipaddr[48]; 72 char cl_ipaddr[48];
65 unsigned char cl_id_uniquifier; 73 unsigned char cl_id_uniquifier;
66#endif 74 int (* cl_call_sync)(struct nfs_server *server,
75 struct rpc_message *msg,
76 struct nfs4_sequence_args *args,
77 struct nfs4_sequence_res *res,
78 int cache_reply);
79#endif /* CONFIG_NFS_V4 */
80
81#ifdef CONFIG_NFS_V4_1
82 /* clientid returned from EXCHANGE_ID, used by session operations */
83 u64 cl_ex_clid;
84 /* The sequence id to use for the next CREATE_SESSION */
85 u32 cl_seqid;
86 /* The flags used for obtaining the clientid during EXCHANGE_ID */
87 u32 cl_exchange_flags;
88 struct nfs4_session *cl_session; /* sharred session */
89#endif /* CONFIG_NFS_V4_1 */
67 90
68#ifdef CONFIG_NFS_FSCACHE 91#ifdef CONFIG_NFS_FSCACHE
69 struct fscache_cookie *fscache; /* client index cache cookie */ 92 struct fscache_cookie *fscache; /* client index cache cookie */
@@ -145,4 +168,46 @@ struct nfs_server {
145#define NFS_CAP_ACLS (1U << 3) 168#define NFS_CAP_ACLS (1U << 3)
146#define NFS_CAP_ATOMIC_OPEN (1U << 4) 169#define NFS_CAP_ATOMIC_OPEN (1U << 4)
147 170
171
172/* maximum number of slots to use */
173#define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE
174
175#if defined(CONFIG_NFS_V4_1)
176
177/* Sessions */
178#define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long)))
179struct nfs4_slot_table {
180 struct nfs4_slot *slots; /* seqid per slot */
181 unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
182 spinlock_t slot_tbl_lock;
183 struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */
184 int max_slots; /* # slots in table */
185 int highest_used_slotid; /* sent to server on each SEQ.
186 * op for dynamic resizing */
187};
188
189static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
190{
191 return sp - tbl->slots;
192}
193
194/*
195 * Session related parameters
196 */
197struct nfs4_session {
198 struct nfs4_sessionid sess_id;
199 u32 flags;
200 unsigned long session_state;
201 u32 hash_alg;
202 u32 ssv_len;
203
204 /* The fore and back channel */
205 struct nfs4_channel_attrs fc_attrs;
206 struct nfs4_slot_table fc_slot_table;
207 struct nfs4_channel_attrs bc_attrs;
208 struct nfs4_slot_table bc_slot_table;
209 struct nfs_client *clp;
210};
211
212#endif /* CONFIG_NFS_V4_1 */
148#endif 213#endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index b89c34e40bc2..62f63fb0c4c8 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -145,6 +145,44 @@ struct nfs4_change_info {
145}; 145};
146 146
147struct nfs_seqid; 147struct nfs_seqid;
148
149/* nfs41 sessions channel attributes */
150struct nfs4_channel_attrs {
151 u32 headerpadsz;
152 u32 max_rqst_sz;
153 u32 max_resp_sz;
154 u32 max_resp_sz_cached;
155 u32 max_ops;
156 u32 max_reqs;
157};
158
159/* nfs41 sessions slot seqid */
160struct nfs4_slot {
161 u32 seq_nr;
162};
163
164struct nfs4_sequence_args {
165 struct nfs4_session *sa_session;
166 u8 sa_slotid;
167 u8 sa_cache_this;
168};
169
170struct nfs4_sequence_res {
171 struct nfs4_session *sr_session;
172 u8 sr_slotid; /* slot used to send request */
173 unsigned long sr_renewal_time;
174 int sr_status; /* sequence operation status */
175};
176
177struct nfs4_get_lease_time_args {
178 struct nfs4_sequence_args la_seq_args;
179};
180
181struct nfs4_get_lease_time_res {
182 struct nfs_fsinfo *lr_fsinfo;
183 struct nfs4_sequence_res lr_seq_res;
184};
185
148/* 186/*
149 * Arguments to the open call. 187 * Arguments to the open call.
150 */ 188 */
@@ -165,6 +203,7 @@ struct nfs_openargs {
165 const struct nfs_server *server; /* Needed for ID mapping */ 203 const struct nfs_server *server; /* Needed for ID mapping */
166 const u32 * bitmask; 204 const u32 * bitmask;
167 __u32 claim; 205 __u32 claim;
206 struct nfs4_sequence_args seq_args;
168}; 207};
169 208
170struct nfs_openres { 209struct nfs_openres {
@@ -181,6 +220,7 @@ struct nfs_openres {
181 __u32 do_recall; 220 __u32 do_recall;
182 __u64 maxsize; 221 __u64 maxsize;
183 __u32 attrset[NFS4_BITMAP_SIZE]; 222 __u32 attrset[NFS4_BITMAP_SIZE];
223 struct nfs4_sequence_res seq_res;
184}; 224};
185 225
186/* 226/*
@@ -206,6 +246,7 @@ struct nfs_closeargs {
206 struct nfs_seqid * seqid; 246 struct nfs_seqid * seqid;
207 fmode_t fmode; 247 fmode_t fmode;
208 const u32 * bitmask; 248 const u32 * bitmask;
249 struct nfs4_sequence_args seq_args;
209}; 250};
210 251
211struct nfs_closeres { 252struct nfs_closeres {
@@ -213,6 +254,7 @@ struct nfs_closeres {
213 struct nfs_fattr * fattr; 254 struct nfs_fattr * fattr;
214 struct nfs_seqid * seqid; 255 struct nfs_seqid * seqid;
215 const struct nfs_server *server; 256 const struct nfs_server *server;
257 struct nfs4_sequence_res seq_res;
216}; 258};
217/* 259/*
218 * * Arguments to the lock,lockt, and locku call. 260 * * Arguments to the lock,lockt, and locku call.
@@ -233,12 +275,14 @@ struct nfs_lock_args {
233 unsigned char block : 1; 275 unsigned char block : 1;
234 unsigned char reclaim : 1; 276 unsigned char reclaim : 1;
235 unsigned char new_lock_owner : 1; 277 unsigned char new_lock_owner : 1;
278 struct nfs4_sequence_args seq_args;
236}; 279};
237 280
238struct nfs_lock_res { 281struct nfs_lock_res {
239 nfs4_stateid stateid; 282 nfs4_stateid stateid;
240 struct nfs_seqid * lock_seqid; 283 struct nfs_seqid * lock_seqid;
241 struct nfs_seqid * open_seqid; 284 struct nfs_seqid * open_seqid;
285 struct nfs4_sequence_res seq_res;
242}; 286};
243 287
244struct nfs_locku_args { 288struct nfs_locku_args {
@@ -246,32 +290,38 @@ struct nfs_locku_args {
246 struct file_lock * fl; 290 struct file_lock * fl;
247 struct nfs_seqid * seqid; 291 struct nfs_seqid * seqid;
248 nfs4_stateid * stateid; 292 nfs4_stateid * stateid;
293 struct nfs4_sequence_args seq_args;
249}; 294};
250 295
251struct nfs_locku_res { 296struct nfs_locku_res {
252 nfs4_stateid stateid; 297 nfs4_stateid stateid;
253 struct nfs_seqid * seqid; 298 struct nfs_seqid * seqid;
299 struct nfs4_sequence_res seq_res;
254}; 300};
255 301
256struct nfs_lockt_args { 302struct nfs_lockt_args {
257 struct nfs_fh * fh; 303 struct nfs_fh * fh;
258 struct file_lock * fl; 304 struct file_lock * fl;
259 struct nfs_lowner lock_owner; 305 struct nfs_lowner lock_owner;
306 struct nfs4_sequence_args seq_args;
260}; 307};
261 308
262struct nfs_lockt_res { 309struct nfs_lockt_res {
263 struct file_lock * denied; /* LOCK, LOCKT failed */ 310 struct file_lock * denied; /* LOCK, LOCKT failed */
311 struct nfs4_sequence_res seq_res;
264}; 312};
265 313
266struct nfs4_delegreturnargs { 314struct nfs4_delegreturnargs {
267 const struct nfs_fh *fhandle; 315 const struct nfs_fh *fhandle;
268 const nfs4_stateid *stateid; 316 const nfs4_stateid *stateid;
269 const u32 * bitmask; 317 const u32 * bitmask;
318 struct nfs4_sequence_args seq_args;
270}; 319};
271 320
272struct nfs4_delegreturnres { 321struct nfs4_delegreturnres {
273 struct nfs_fattr * fattr; 322 struct nfs_fattr * fattr;
274 const struct nfs_server *server; 323 const struct nfs_server *server;
324 struct nfs4_sequence_res seq_res;
275}; 325};
276 326
277/* 327/*
@@ -284,12 +334,14 @@ struct nfs_readargs {
284 __u32 count; 334 __u32 count;
285 unsigned int pgbase; 335 unsigned int pgbase;
286 struct page ** pages; 336 struct page ** pages;
337 struct nfs4_sequence_args seq_args;
287}; 338};
288 339
289struct nfs_readres { 340struct nfs_readres {
290 struct nfs_fattr * fattr; 341 struct nfs_fattr * fattr;
291 __u32 count; 342 __u32 count;
292 int eof; 343 int eof;
344 struct nfs4_sequence_res seq_res;
293}; 345};
294 346
295/* 347/*
@@ -304,6 +356,7 @@ struct nfs_writeargs {
304 unsigned int pgbase; 356 unsigned int pgbase;
305 struct page ** pages; 357 struct page ** pages;
306 const u32 * bitmask; 358 const u32 * bitmask;
359 struct nfs4_sequence_args seq_args;
307}; 360};
308 361
309struct nfs_writeverf { 362struct nfs_writeverf {
@@ -316,6 +369,7 @@ struct nfs_writeres {
316 struct nfs_writeverf * verf; 369 struct nfs_writeverf * verf;
317 __u32 count; 370 __u32 count;
318 const struct nfs_server *server; 371 const struct nfs_server *server;
372 struct nfs4_sequence_res seq_res;
319}; 373};
320 374
321/* 375/*
@@ -325,12 +379,14 @@ struct nfs_removeargs {
325 const struct nfs_fh *fh; 379 const struct nfs_fh *fh;
326 struct qstr name; 380 struct qstr name;
327 const u32 * bitmask; 381 const u32 * bitmask;
382 struct nfs4_sequence_args seq_args;
328}; 383};
329 384
330struct nfs_removeres { 385struct nfs_removeres {
331 const struct nfs_server *server; 386 const struct nfs_server *server;
332 struct nfs4_change_info cinfo; 387 struct nfs4_change_info cinfo;
333 struct nfs_fattr dir_attr; 388 struct nfs_fattr dir_attr;
389 struct nfs4_sequence_res seq_res;
334}; 390};
335 391
336/* 392/*
@@ -383,6 +439,7 @@ struct nfs_setattrargs {
383 struct iattr * iap; 439 struct iattr * iap;
384 const struct nfs_server * server; /* Needed for name mapping */ 440 const struct nfs_server * server; /* Needed for name mapping */
385 const u32 * bitmask; 441 const u32 * bitmask;
442 struct nfs4_sequence_args seq_args;
386}; 443};
387 444
388struct nfs_setaclargs { 445struct nfs_setaclargs {
@@ -390,6 +447,11 @@ struct nfs_setaclargs {
390 size_t acl_len; 447 size_t acl_len;
391 unsigned int acl_pgbase; 448 unsigned int acl_pgbase;
392 struct page ** acl_pages; 449 struct page ** acl_pages;
450 struct nfs4_sequence_args seq_args;
451};
452
453struct nfs_setaclres {
454 struct nfs4_sequence_res seq_res;
393}; 455};
394 456
395struct nfs_getaclargs { 457struct nfs_getaclargs {
@@ -397,11 +459,18 @@ struct nfs_getaclargs {
397 size_t acl_len; 459 size_t acl_len;
398 unsigned int acl_pgbase; 460 unsigned int acl_pgbase;
399 struct page ** acl_pages; 461 struct page ** acl_pages;
462 struct nfs4_sequence_args seq_args;
463};
464
465struct nfs_getaclres {
466 size_t acl_len;
467 struct nfs4_sequence_res seq_res;
400}; 468};
401 469
402struct nfs_setattrres { 470struct nfs_setattrres {
403 struct nfs_fattr * fattr; 471 struct nfs_fattr * fattr;
404 const struct nfs_server * server; 472 const struct nfs_server * server;
473 struct nfs4_sequence_res seq_res;
405}; 474};
406 475
407struct nfs_linkargs { 476struct nfs_linkargs {
@@ -583,6 +652,7 @@ struct nfs4_accessargs {
583 const struct nfs_fh * fh; 652 const struct nfs_fh * fh;
584 const u32 * bitmask; 653 const u32 * bitmask;
585 u32 access; 654 u32 access;
655 struct nfs4_sequence_args seq_args;
586}; 656};
587 657
588struct nfs4_accessres { 658struct nfs4_accessres {
@@ -590,6 +660,7 @@ struct nfs4_accessres {
590 struct nfs_fattr * fattr; 660 struct nfs_fattr * fattr;
591 u32 supported; 661 u32 supported;
592 u32 access; 662 u32 access;
663 struct nfs4_sequence_res seq_res;
593}; 664};
594 665
595struct nfs4_create_arg { 666struct nfs4_create_arg {
@@ -609,6 +680,7 @@ struct nfs4_create_arg {
609 const struct iattr * attrs; 680 const struct iattr * attrs;
610 const struct nfs_fh * dir_fh; 681 const struct nfs_fh * dir_fh;
611 const u32 * bitmask; 682 const u32 * bitmask;
683 struct nfs4_sequence_args seq_args;
612}; 684};
613 685
614struct nfs4_create_res { 686struct nfs4_create_res {
@@ -617,21 +689,30 @@ struct nfs4_create_res {
617 struct nfs_fattr * fattr; 689 struct nfs_fattr * fattr;
618 struct nfs4_change_info dir_cinfo; 690 struct nfs4_change_info dir_cinfo;
619 struct nfs_fattr * dir_fattr; 691 struct nfs_fattr * dir_fattr;
692 struct nfs4_sequence_res seq_res;
620}; 693};
621 694
622struct nfs4_fsinfo_arg { 695struct nfs4_fsinfo_arg {
623 const struct nfs_fh * fh; 696 const struct nfs_fh * fh;
624 const u32 * bitmask; 697 const u32 * bitmask;
698 struct nfs4_sequence_args seq_args;
699};
700
701struct nfs4_fsinfo_res {
702 struct nfs_fsinfo *fsinfo;
703 struct nfs4_sequence_res seq_res;
625}; 704};
626 705
627struct nfs4_getattr_arg { 706struct nfs4_getattr_arg {
628 const struct nfs_fh * fh; 707 const struct nfs_fh * fh;
629 const u32 * bitmask; 708 const u32 * bitmask;
709 struct nfs4_sequence_args seq_args;
630}; 710};
631 711
632struct nfs4_getattr_res { 712struct nfs4_getattr_res {
633 const struct nfs_server * server; 713 const struct nfs_server * server;
634 struct nfs_fattr * fattr; 714 struct nfs_fattr * fattr;
715 struct nfs4_sequence_res seq_res;
635}; 716};
636 717
637struct nfs4_link_arg { 718struct nfs4_link_arg {
@@ -639,6 +720,7 @@ struct nfs4_link_arg {
639 const struct nfs_fh * dir_fh; 720 const struct nfs_fh * dir_fh;
640 const struct qstr * name; 721 const struct qstr * name;
641 const u32 * bitmask; 722 const u32 * bitmask;
723 struct nfs4_sequence_args seq_args;
642}; 724};
643 725
644struct nfs4_link_res { 726struct nfs4_link_res {
@@ -646,6 +728,7 @@ struct nfs4_link_res {
646 struct nfs_fattr * fattr; 728 struct nfs_fattr * fattr;
647 struct nfs4_change_info cinfo; 729 struct nfs4_change_info cinfo;
648 struct nfs_fattr * dir_attr; 730 struct nfs_fattr * dir_attr;
731 struct nfs4_sequence_res seq_res;
649}; 732};
650 733
651 734
@@ -653,21 +736,30 @@ struct nfs4_lookup_arg {
653 const struct nfs_fh * dir_fh; 736 const struct nfs_fh * dir_fh;
654 const struct qstr * name; 737 const struct qstr * name;
655 const u32 * bitmask; 738 const u32 * bitmask;
739 struct nfs4_sequence_args seq_args;
656}; 740};
657 741
658struct nfs4_lookup_res { 742struct nfs4_lookup_res {
659 const struct nfs_server * server; 743 const struct nfs_server * server;
660 struct nfs_fattr * fattr; 744 struct nfs_fattr * fattr;
661 struct nfs_fh * fh; 745 struct nfs_fh * fh;
746 struct nfs4_sequence_res seq_res;
662}; 747};
663 748
664struct nfs4_lookup_root_arg { 749struct nfs4_lookup_root_arg {
665 const u32 * bitmask; 750 const u32 * bitmask;
751 struct nfs4_sequence_args seq_args;
666}; 752};
667 753
668struct nfs4_pathconf_arg { 754struct nfs4_pathconf_arg {
669 const struct nfs_fh * fh; 755 const struct nfs_fh * fh;
670 const u32 * bitmask; 756 const u32 * bitmask;
757 struct nfs4_sequence_args seq_args;
758};
759
760struct nfs4_pathconf_res {
761 struct nfs_pathconf *pathconf;
762 struct nfs4_sequence_res seq_res;
671}; 763};
672 764
673struct nfs4_readdir_arg { 765struct nfs4_readdir_arg {
@@ -678,11 +770,13 @@ struct nfs4_readdir_arg {
678 struct page ** pages; /* zero-copy data */ 770 struct page ** pages; /* zero-copy data */
679 unsigned int pgbase; /* zero-copy data */ 771 unsigned int pgbase; /* zero-copy data */
680 const u32 * bitmask; 772 const u32 * bitmask;
773 struct nfs4_sequence_args seq_args;
681}; 774};
682 775
683struct nfs4_readdir_res { 776struct nfs4_readdir_res {
684 nfs4_verifier verifier; 777 nfs4_verifier verifier;
685 unsigned int pgbase; 778 unsigned int pgbase;
779 struct nfs4_sequence_res seq_res;
686}; 780};
687 781
688struct nfs4_readlink { 782struct nfs4_readlink {
@@ -690,6 +784,11 @@ struct nfs4_readlink {
690 unsigned int pgbase; 784 unsigned int pgbase;
691 unsigned int pglen; /* zero-copy data */ 785 unsigned int pglen; /* zero-copy data */
692 struct page ** pages; /* zero-copy data */ 786 struct page ** pages; /* zero-copy data */
787 struct nfs4_sequence_args seq_args;
788};
789
790struct nfs4_readlink_res {
791 struct nfs4_sequence_res seq_res;
693}; 792};
694 793
695struct nfs4_rename_arg { 794struct nfs4_rename_arg {
@@ -698,6 +797,7 @@ struct nfs4_rename_arg {
698 const struct qstr * old_name; 797 const struct qstr * old_name;
699 const struct qstr * new_name; 798 const struct qstr * new_name;
700 const u32 * bitmask; 799 const u32 * bitmask;
800 struct nfs4_sequence_args seq_args;
701}; 801};
702 802
703struct nfs4_rename_res { 803struct nfs4_rename_res {
@@ -706,6 +806,7 @@ struct nfs4_rename_res {
706 struct nfs_fattr * old_fattr; 806 struct nfs_fattr * old_fattr;
707 struct nfs4_change_info new_cinfo; 807 struct nfs4_change_info new_cinfo;
708 struct nfs_fattr * new_fattr; 808 struct nfs_fattr * new_fattr;
809 struct nfs4_sequence_res seq_res;
709}; 810};
710 811
711#define NFS4_SETCLIENTID_NAMELEN (127) 812#define NFS4_SETCLIENTID_NAMELEN (127)
@@ -724,6 +825,17 @@ struct nfs4_setclientid {
724struct nfs4_statfs_arg { 825struct nfs4_statfs_arg {
725 const struct nfs_fh * fh; 826 const struct nfs_fh * fh;
726 const u32 * bitmask; 827 const u32 * bitmask;
828 struct nfs4_sequence_args seq_args;
829};
830
831struct nfs4_statfs_res {
832 struct nfs_fsstat *fsstat;
833 struct nfs4_sequence_res seq_res;
834};
835
836struct nfs4_server_caps_arg {
837 struct nfs_fh *fhandle;
838 struct nfs4_sequence_args seq_args;
727}; 839};
728 840
729struct nfs4_server_caps_res { 841struct nfs4_server_caps_res {
@@ -731,6 +843,7 @@ struct nfs4_server_caps_res {
731 u32 acl_bitmask; 843 u32 acl_bitmask;
732 u32 has_links; 844 u32 has_links;
733 u32 has_symlinks; 845 u32 has_symlinks;
846 struct nfs4_sequence_res seq_res;
734}; 847};
735 848
736struct nfs4_string { 849struct nfs4_string {
@@ -765,10 +878,68 @@ struct nfs4_fs_locations_arg {
765 const struct qstr *name; 878 const struct qstr *name;
766 struct page *page; 879 struct page *page;
767 const u32 *bitmask; 880 const u32 *bitmask;
881 struct nfs4_sequence_args seq_args;
882};
883
884struct nfs4_fs_locations_res {
885 struct nfs4_fs_locations *fs_locations;
886 struct nfs4_sequence_res seq_res;
768}; 887};
769 888
770#endif /* CONFIG_NFS_V4 */ 889#endif /* CONFIG_NFS_V4 */
771 890
891struct nfstime4 {
892 u64 seconds;
893 u32 nseconds;
894};
895
896#ifdef CONFIG_NFS_V4_1
897struct nfs_impl_id4 {
898 u32 domain_len;
899 char *domain;
900 u32 name_len;
901 char *name;
902 struct nfstime4 date;
903};
904
905#define NFS4_EXCHANGE_ID_LEN (48)
906struct nfs41_exchange_id_args {
907 struct nfs_client *client;
908 nfs4_verifier *verifier;
909 unsigned int id_len;
910 char id[NFS4_EXCHANGE_ID_LEN];
911 u32 flags;
912};
913
914struct server_owner {
915 uint64_t minor_id;
916 uint32_t major_id_sz;
917 char major_id[NFS4_OPAQUE_LIMIT];
918};
919
920struct server_scope {
921 uint32_t server_scope_sz;
922 char server_scope[NFS4_OPAQUE_LIMIT];
923};
924
925struct nfs41_exchange_id_res {
926 struct nfs_client *client;
927 u32 flags;
928};
929
930struct nfs41_create_session_args {
931 struct nfs_client *client;
932 uint32_t flags;
933 uint32_t cb_program;
934 struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
935 struct nfs4_channel_attrs bc_attrs; /* Back Channel */
936};
937
938struct nfs41_create_session_res {
939 struct nfs_client *client;
940};
941#endif /* CONFIG_NFS_V4_1 */
942
772struct nfs_page; 943struct nfs_page;
773 944
774#define NFS_PAGEVEC_SIZE (8U) 945#define NFS_PAGEVEC_SIZE (8U)
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 4d61c873feed..7ef4b7ad1214 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -41,7 +41,6 @@
41#include <linux/kref.h> 41#include <linux/kref.h>
42#include <linux/sunrpc/clnt.h> 42#include <linux/sunrpc/clnt.h>
43 43
44#define NFS4_OPAQUE_LIMIT 1024
45typedef struct { 44typedef struct {
46 u32 cl_boot; 45 u32 cl_boot;
47 u32 cl_id; 46 u32 cl_id;
diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h
new file mode 100644
index 000000000000..6508f0dc0eff
--- /dev/null
+++ b/include/linux/sunrpc/bc_xprt.h
@@ -0,0 +1,49 @@
1/******************************************************************************
2
3(c) 2008 NetApp. All Rights Reserved.
4
5NetApp provides this source code under the GPL v2 License.
6The GPL v2 license is available at
7http://opensource.org/licenses/gpl-license.php.
8
9THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
12A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
13CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
15PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
17LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
18NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20
21******************************************************************************/
22
23/*
24 * Functions to create and manage the backchannel
25 */
26
27#ifndef _LINUX_SUNRPC_BC_XPRT_H
28#define _LINUX_SUNRPC_BC_XPRT_H
29
30#include <linux/sunrpc/svcsock.h>
31#include <linux/sunrpc/xprt.h>
32#include <linux/sunrpc/sched.h>
33
34#ifdef CONFIG_NFS_V4_1
35struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt);
36void xprt_free_bc_request(struct rpc_rqst *req);
37int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
38void xprt_destroy_backchannel(struct rpc_xprt *, int max_reqs);
39void bc_release_request(struct rpc_task *);
40int bc_send(struct rpc_rqst *req);
41#else /* CONFIG_NFS_V4_1 */
42static inline int xprt_setup_backchannel(struct rpc_xprt *xprt,
43 unsigned int min_reqs)
44{
45 return 0;
46}
47#endif /* CONFIG_NFS_V4_1 */
48#endif /* _LINUX_SUNRPC_BC_XPRT_H */
49
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index c39a21040dcb..37881f1a0bd7 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -143,6 +143,7 @@ int rpc_call_sync(struct rpc_clnt *clnt,
143 const struct rpc_message *msg, int flags); 143 const struct rpc_message *msg, int flags);
144struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, 144struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
145 int flags); 145 int flags);
146void rpc_restart_call_prepare(struct rpc_task *);
146void rpc_restart_call(struct rpc_task *); 147void rpc_restart_call(struct rpc_task *);
147void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); 148void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
148size_t rpc_max_payload(struct rpc_clnt *); 149size_t rpc_max_payload(struct rpc_clnt *);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 64981a2f1cae..401097781fc0 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -210,6 +210,8 @@ struct rpc_wait_queue {
210 */ 210 */
211struct rpc_task *rpc_new_task(const struct rpc_task_setup *); 211struct rpc_task *rpc_new_task(const struct rpc_task_setup *);
212struct rpc_task *rpc_run_task(const struct rpc_task_setup *); 212struct rpc_task *rpc_run_task(const struct rpc_task_setup *);
213struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
214 const struct rpc_call_ops *ops);
213void rpc_put_task(struct rpc_task *); 215void rpc_put_task(struct rpc_task *);
214void rpc_exit_task(struct rpc_task *); 216void rpc_exit_task(struct rpc_task *);
215void rpc_release_calldata(const struct rpc_call_ops *, void *); 217void rpc_release_calldata(const struct rpc_call_ops *, void *);
@@ -237,6 +239,7 @@ void rpc_show_tasks(void);
237int rpc_init_mempool(void); 239int rpc_init_mempool(void);
238void rpc_destroy_mempool(void); 240void rpc_destroy_mempool(void);
239extern struct workqueue_struct *rpciod_workqueue; 241extern struct workqueue_struct *rpciod_workqueue;
242void rpc_prepare_task(struct rpc_task *task);
240 243
241static inline void rpc_exit(struct rpc_task *task, int status) 244static inline void rpc_exit(struct rpc_task *task, int status)
242{ 245{
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 2a30775959e9..ea8009695c69 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -96,6 +96,15 @@ struct svc_serv {
96 svc_thread_fn sv_function; /* main function for threads */ 96 svc_thread_fn sv_function; /* main function for threads */
97 unsigned int sv_drc_max_pages; /* Total pages for DRC */ 97 unsigned int sv_drc_max_pages; /* Total pages for DRC */
98 unsigned int sv_drc_pages_used;/* DRC pages used */ 98 unsigned int sv_drc_pages_used;/* DRC pages used */
99#if defined(CONFIG_NFS_V4_1)
100 struct list_head sv_cb_list; /* queue for callback requests
101 * that arrive over the same
102 * connection */
103 spinlock_t sv_cb_lock; /* protects the svc_cb_list */
104 wait_queue_head_t sv_cb_waitq; /* sleep here if there are no
105 * entries in the svc_cb_list */
106 struct svc_xprt *bc_xprt;
107#endif /* CONFIG_NFS_V4_1 */
99}; 108};
100 109
101/* 110/*
@@ -411,6 +420,8 @@ int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
411int svc_pool_stats_open(struct svc_serv *serv, struct file *file); 420int svc_pool_stats_open(struct svc_serv *serv, struct file *file);
412void svc_destroy(struct svc_serv *); 421void svc_destroy(struct svc_serv *);
413int svc_process(struct svc_rqst *); 422int svc_process(struct svc_rqst *);
423int bc_svc_process(struct svc_serv *, struct rpc_rqst *,
424 struct svc_rqst *);
414int svc_register(const struct svc_serv *, const int, 425int svc_register(const struct svc_serv *, const int,
415 const unsigned short, const unsigned short); 426 const unsigned short, const unsigned short);
416 427
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 483e10380aae..6bb1ec4ae310 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -42,6 +42,8 @@ int svc_sock_names(char *buf, struct svc_serv *serv, char *toclose);
42int svc_addsock(struct svc_serv *serv, int fd, char *name_return); 42int svc_addsock(struct svc_serv *serv, int fd, char *name_return);
43void svc_init_xprt_sock(void); 43void svc_init_xprt_sock(void);
44void svc_cleanup_xprt_sock(void); 44void svc_cleanup_xprt_sock(void);
45struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot);
46void svc_sock_destroy(struct svc_xprt *);
45 47
46/* 48/*
47 * svc_makesock socket characteristics 49 * svc_makesock socket characteristics
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 08afe43118f4..1175d58efc2e 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -67,7 +67,8 @@ struct rpc_rqst {
67 struct rpc_task * rq_task; /* RPC task data */ 67 struct rpc_task * rq_task; /* RPC task data */
68 __be32 rq_xid; /* request XID */ 68 __be32 rq_xid; /* request XID */
69 int rq_cong; /* has incremented xprt->cong */ 69 int rq_cong; /* has incremented xprt->cong */
70 int rq_received; /* receive completed */ 70 int rq_reply_bytes_recvd; /* number of reply */
71 /* bytes received */
71 u32 rq_seqno; /* gss seq no. used on req. */ 72 u32 rq_seqno; /* gss seq no. used on req. */
72 int rq_enc_pages_num; 73 int rq_enc_pages_num;
73 struct page **rq_enc_pages; /* scratch pages for use by 74 struct page **rq_enc_pages; /* scratch pages for use by
@@ -97,6 +98,12 @@ struct rpc_rqst {
97 98
98 unsigned long rq_xtime; /* when transmitted */ 99 unsigned long rq_xtime; /* when transmitted */
99 int rq_ntrans; 100 int rq_ntrans;
101
102#if defined(CONFIG_NFS_V4_1)
103 struct list_head rq_bc_list; /* Callback service list */
104 unsigned long rq_bc_pa_state; /* Backchannel prealloc state */
105 struct list_head rq_bc_pa_list; /* Backchannel prealloc list */
106#endif /* CONFIG_NFS_V4_1 */
100}; 107};
101#define rq_svec rq_snd_buf.head 108#define rq_svec rq_snd_buf.head
102#define rq_slen rq_snd_buf.len 109#define rq_slen rq_snd_buf.len
@@ -174,6 +181,15 @@ struct rpc_xprt {
174 spinlock_t reserve_lock; /* lock slot table */ 181 spinlock_t reserve_lock; /* lock slot table */
175 u32 xid; /* Next XID value to use */ 182 u32 xid; /* Next XID value to use */
176 struct rpc_task * snd_task; /* Task blocked in send */ 183 struct rpc_task * snd_task; /* Task blocked in send */
184#if defined(CONFIG_NFS_V4_1)
185 struct svc_serv *bc_serv; /* The RPC service which will */
186 /* process the callback */
187 unsigned int bc_alloc_count; /* Total number of preallocs */
188 spinlock_t bc_pa_lock; /* Protects the preallocated
189 * items */
190 struct list_head bc_pa_list; /* List of preallocated
191 * backchannel rpc_rqst's */
192#endif /* CONFIG_NFS_V4_1 */
177 struct list_head recv; 193 struct list_head recv;
178 194
179 struct { 195 struct {
@@ -192,6 +208,26 @@ struct rpc_xprt {
192 const char *address_strings[RPC_DISPLAY_MAX]; 208 const char *address_strings[RPC_DISPLAY_MAX];
193}; 209};
194 210
211#if defined(CONFIG_NFS_V4_1)
212/*
213 * Backchannel flags
214 */
215#define RPC_BC_PA_IN_USE 0x0001 /* Preallocated backchannel */
216 /* buffer in use */
217#endif /* CONFIG_NFS_V4_1 */
218
219#if defined(CONFIG_NFS_V4_1)
220static inline int bc_prealloc(struct rpc_rqst *req)
221{
222 return test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
223}
224#else
225static inline int bc_prealloc(struct rpc_rqst *req)
226{
227 return 0;
228}
229#endif /* CONFIG_NFS_V4_1 */
230
195struct xprt_create { 231struct xprt_create {
196 int ident; /* XPRT_TRANSPORT identifier */ 232 int ident; /* XPRT_TRANSPORT identifier */
197 struct sockaddr * srcaddr; /* optional local address */ 233 struct sockaddr * srcaddr; /* optional local address */
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index 5369aa369b35..db73fd2a3f0e 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -13,5 +13,6 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
13 rpcb_clnt.o timer.o xdr.o \ 13 rpcb_clnt.o timer.o xdr.o \
14 sunrpc_syms.o cache.o rpc_pipe.o \ 14 sunrpc_syms.o cache.o rpc_pipe.o \
15 svc_xprt.o 15 svc_xprt.o
16sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o bc_svc.o
16sunrpc-$(CONFIG_PROC_FS) += stats.o 17sunrpc-$(CONFIG_PROC_FS) += stats.o
17sunrpc-$(CONFIG_SYSCTL) += sysctl.o 18sunrpc-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
new file mode 100644
index 000000000000..5a7d342e3087
--- /dev/null
+++ b/net/sunrpc/backchannel_rqst.c
@@ -0,0 +1,278 @@
1/******************************************************************************
2
3(c) 2007 Network Appliance, Inc. All Rights Reserved.
4(c) 2009 NetApp. All Rights Reserved.
5
6NetApp provides this source code under the GPL v2 License.
7The GPL v2 license is available at
8http://opensource.org/licenses/gpl-license.php.
9
10THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
11"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
13A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
15EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
17PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
18LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
22******************************************************************************/
23
24#include <linux/tcp.h>
25#include <linux/sunrpc/xprt.h>
26
27#ifdef RPC_DEBUG
28#define RPCDBG_FACILITY RPCDBG_TRANS
29#endif
30
31#if defined(CONFIG_NFS_V4_1)
32
33/*
34 * Helper routines that track the number of preallocation elements
35 * on the transport.
36 */
37static inline int xprt_need_to_requeue(struct rpc_xprt *xprt)
38{
39 return xprt->bc_alloc_count > 0;
40}
41
42static inline void xprt_inc_alloc_count(struct rpc_xprt *xprt, unsigned int n)
43{
44 xprt->bc_alloc_count += n;
45}
46
47static inline int xprt_dec_alloc_count(struct rpc_xprt *xprt, unsigned int n)
48{
49 return xprt->bc_alloc_count -= n;
50}
51
52/*
53 * Free the preallocated rpc_rqst structure and the memory
54 * buffers hanging off of it.
55 */
56static void xprt_free_allocation(struct rpc_rqst *req)
57{
58 struct xdr_buf *xbufp;
59
60 dprintk("RPC: free allocations for req= %p\n", req);
61 BUG_ON(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
62 xbufp = &req->rq_private_buf;
63 free_page((unsigned long)xbufp->head[0].iov_base);
64 xbufp = &req->rq_snd_buf;
65 free_page((unsigned long)xbufp->head[0].iov_base);
66 list_del(&req->rq_bc_pa_list);
67 kfree(req);
68}
69
70/*
71 * Preallocate up to min_reqs structures and related buffers for use
72 * by the backchannel. This function can be called multiple times
73 * when creating new sessions that use the same rpc_xprt. The
74 * preallocated buffers are added to the pool of resources used by
75 * the rpc_xprt. Anyone of these resources may be used used by an
76 * incoming callback request. It's up to the higher levels in the
77 * stack to enforce that the maximum number of session slots is not
78 * being exceeded.
79 *
80 * Some callback arguments can be large. For example, a pNFS server
81 * using multiple deviceids. The list can be unbound, but the client
82 * has the ability to tell the server the maximum size of the callback
83 * requests. Each deviceID is 16 bytes, so allocate one page
84 * for the arguments to have enough room to receive a number of these
85 * deviceIDs. The NFS client indicates to the pNFS server that its
86 * callback requests can be up to 4096 bytes in size.
87 */
88int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
89{
90 struct page *page_rcv = NULL, *page_snd = NULL;
91 struct xdr_buf *xbufp = NULL;
92 struct rpc_rqst *req, *tmp;
93 struct list_head tmp_list;
94 int i;
95
96 dprintk("RPC: setup backchannel transport\n");
97
98 /*
99 * We use a temporary list to keep track of the preallocated
100 * buffers. Once we're done building the list we splice it
101 * into the backchannel preallocation list off of the rpc_xprt
102 * struct. This helps minimize the amount of time the list
103 * lock is held on the rpc_xprt struct. It also makes cleanup
104 * easier in case of memory allocation errors.
105 */
106 INIT_LIST_HEAD(&tmp_list);
107 for (i = 0; i < min_reqs; i++) {
108 /* Pre-allocate one backchannel rpc_rqst */
109 req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL);
110 if (req == NULL) {
111 printk(KERN_ERR "Failed to create bc rpc_rqst\n");
112 goto out_free;
113 }
114
115 /* Add the allocated buffer to the tmp list */
116 dprintk("RPC: adding req= %p\n", req);
117 list_add(&req->rq_bc_pa_list, &tmp_list);
118
119 req->rq_xprt = xprt;
120 INIT_LIST_HEAD(&req->rq_list);
121 INIT_LIST_HEAD(&req->rq_bc_list);
122
123 /* Preallocate one XDR receive buffer */
124 page_rcv = alloc_page(GFP_KERNEL);
125 if (page_rcv == NULL) {
126 printk(KERN_ERR "Failed to create bc receive xbuf\n");
127 goto out_free;
128 }
129 xbufp = &req->rq_rcv_buf;
130 xbufp->head[0].iov_base = page_address(page_rcv);
131 xbufp->head[0].iov_len = PAGE_SIZE;
132 xbufp->tail[0].iov_base = NULL;
133 xbufp->tail[0].iov_len = 0;
134 xbufp->page_len = 0;
135 xbufp->len = PAGE_SIZE;
136 xbufp->buflen = PAGE_SIZE;
137
138 /* Preallocate one XDR send buffer */
139 page_snd = alloc_page(GFP_KERNEL);
140 if (page_snd == NULL) {
141 printk(KERN_ERR "Failed to create bc snd xbuf\n");
142 goto out_free;
143 }
144
145 xbufp = &req->rq_snd_buf;
146 xbufp->head[0].iov_base = page_address(page_snd);
147 xbufp->head[0].iov_len = 0;
148 xbufp->tail[0].iov_base = NULL;
149 xbufp->tail[0].iov_len = 0;
150 xbufp->page_len = 0;
151 xbufp->len = 0;
152 xbufp->buflen = PAGE_SIZE;
153 }
154
155 /*
156 * Add the temporary list to the backchannel preallocation list
157 */
158 spin_lock_bh(&xprt->bc_pa_lock);
159 list_splice(&tmp_list, &xprt->bc_pa_list);
160 xprt_inc_alloc_count(xprt, min_reqs);
161 spin_unlock_bh(&xprt->bc_pa_lock);
162
163 dprintk("RPC: setup backchannel transport done\n");
164 return 0;
165
166out_free:
167 /*
168 * Memory allocation failed, free the temporary list
169 */
170 list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list)
171 xprt_free_allocation(req);
172
173 dprintk("RPC: setup backchannel transport failed\n");
174 return -1;
175}
176EXPORT_SYMBOL(xprt_setup_backchannel);
177
178/*
179 * Destroys the backchannel preallocated structures.
180 * Since these structures may have been allocated by multiple calls
181 * to xprt_setup_backchannel, we only destroy up to the maximum number
182 * of reqs specified by the caller.
183 * @xprt: the transport holding the preallocated strucures
184 * @max_reqs the maximum number of preallocated structures to destroy
185 */
186void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs)
187{
188 struct rpc_rqst *req = NULL, *tmp = NULL;
189
190 dprintk("RPC: destroy backchannel transport\n");
191
192 BUG_ON(max_reqs == 0);
193 spin_lock_bh(&xprt->bc_pa_lock);
194 xprt_dec_alloc_count(xprt, max_reqs);
195 list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
196 dprintk("RPC: req=%p\n", req);
197 xprt_free_allocation(req);
198 if (--max_reqs == 0)
199 break;
200 }
201 spin_unlock_bh(&xprt->bc_pa_lock);
202
203 dprintk("RPC: backchannel list empty= %s\n",
204 list_empty(&xprt->bc_pa_list) ? "true" : "false");
205}
206EXPORT_SYMBOL(xprt_destroy_backchannel);
207
208/*
209 * One or more rpc_rqst structure have been preallocated during the
210 * backchannel setup. Buffer space for the send and private XDR buffers
211 * has been preallocated as well. Use xprt_alloc_bc_request to allocate
212 * to this request. Use xprt_free_bc_request to return it.
213 *
214 * Return an available rpc_rqst, otherwise NULL if non are available.
215 */
216struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt)
217{
218 struct rpc_rqst *req;
219
220 dprintk("RPC: allocate a backchannel request\n");
221 spin_lock_bh(&xprt->bc_pa_lock);
222 if (!list_empty(&xprt->bc_pa_list)) {
223 req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
224 rq_bc_pa_list);
225 list_del(&req->rq_bc_pa_list);
226 } else {
227 req = NULL;
228 }
229 spin_unlock_bh(&xprt->bc_pa_lock);
230
231 if (req != NULL) {
232 set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
233 req->rq_reply_bytes_recvd = 0;
234 req->rq_bytes_sent = 0;
235 memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
236 sizeof(req->rq_private_buf));
237 }
238 dprintk("RPC: backchannel req=%p\n", req);
239 return req;
240}
241
242/*
243 * Return the preallocated rpc_rqst structure and XDR buffers
244 * associated with this rpc_task.
245 */
246void xprt_free_bc_request(struct rpc_rqst *req)
247{
248 struct rpc_xprt *xprt = req->rq_xprt;
249
250 dprintk("RPC: free backchannel req=%p\n", req);
251
252 smp_mb__before_clear_bit();
253 BUG_ON(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
254 clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
255 smp_mb__after_clear_bit();
256
257 if (!xprt_need_to_requeue(xprt)) {
258 /*
259 * The last remaining session was destroyed while this
260 * entry was in use. Free the entry and don't attempt
261 * to add back to the list because there is no need to
262 * have anymore preallocated entries.
263 */
264 dprintk("RPC: Last session removed req=%p\n", req);
265 xprt_free_allocation(req);
266 return;
267 }
268
269 /*
270 * Return it to the list of preallocations so that it
271 * may be reused by a new callback request.
272 */
273 spin_lock_bh(&xprt->bc_pa_lock);
274 list_add(&req->rq_bc_pa_list, &xprt->bc_pa_list);
275 spin_unlock_bh(&xprt->bc_pa_lock);
276}
277
278#endif /* CONFIG_NFS_V4_1 */
diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c
new file mode 100644
index 000000000000..13f214f53120
--- /dev/null
+++ b/net/sunrpc/bc_svc.c
@@ -0,0 +1,81 @@
1/******************************************************************************
2
3(c) 2007 Network Appliance, Inc. All Rights Reserved.
4(c) 2009 NetApp. All Rights Reserved.
5
6NetApp provides this source code under the GPL v2 License.
7The GPL v2 license is available at
8http://opensource.org/licenses/gpl-license.php.
9
10THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
11"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
13A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
15EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
17PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
18LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
22******************************************************************************/
23
24/*
25 * The NFSv4.1 callback service helper routines.
26 * They implement the transport level processing required to send the
27 * reply over an existing open connection previously established by the client.
28 */
29
30#if defined(CONFIG_NFS_V4_1)
31
32#include <linux/module.h>
33
34#include <linux/sunrpc/xprt.h>
35#include <linux/sunrpc/sched.h>
36#include <linux/sunrpc/bc_xprt.h>
37
38#define RPCDBG_FACILITY RPCDBG_SVCDSP
39
40void bc_release_request(struct rpc_task *task)
41{
42 struct rpc_rqst *req = task->tk_rqstp;
43
44 dprintk("RPC: bc_release_request: task= %p\n", task);
45
46 /*
47 * Release this request only if it's a backchannel
48 * preallocated request
49 */
50 if (!bc_prealloc(req))
51 return;
52 xprt_free_bc_request(req);
53}
54
55/* Empty callback ops */
56static const struct rpc_call_ops nfs41_callback_ops = {
57};
58
59
60/*
61 * Send the callback reply
62 */
63int bc_send(struct rpc_rqst *req)
64{
65 struct rpc_task *task;
66 int ret;
67
68 dprintk("RPC: bc_send req= %p\n", req);
69 task = rpc_run_bc_task(req, &nfs41_callback_ops);
70 if (IS_ERR(task))
71 ret = PTR_ERR(task);
72 else {
73 BUG_ON(atomic_read(&task->tk_count) != 1);
74 ret = task->tk_status;
75 rpc_put_task(task);
76 }
77 return ret;
78 dprintk("RPC: bc_send ret= %d \n", ret);
79}
80
81#endif /* CONFIG_NFS_V4_1 */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 5abab094441f..5bc2f45bddf0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -36,7 +36,9 @@
36#include <linux/sunrpc/clnt.h> 36#include <linux/sunrpc/clnt.h>
37#include <linux/sunrpc/rpc_pipe_fs.h> 37#include <linux/sunrpc/rpc_pipe_fs.h>
38#include <linux/sunrpc/metrics.h> 38#include <linux/sunrpc/metrics.h>
39#include <linux/sunrpc/bc_xprt.h>
39 40
41#include "sunrpc.h"
40 42
41#ifdef RPC_DEBUG 43#ifdef RPC_DEBUG
42# define RPCDBG_FACILITY RPCDBG_CALL 44# define RPCDBG_FACILITY RPCDBG_CALL
@@ -63,6 +65,9 @@ static void call_decode(struct rpc_task *task);
63static void call_bind(struct rpc_task *task); 65static void call_bind(struct rpc_task *task);
64static void call_bind_status(struct rpc_task *task); 66static void call_bind_status(struct rpc_task *task);
65static void call_transmit(struct rpc_task *task); 67static void call_transmit(struct rpc_task *task);
68#if defined(CONFIG_NFS_V4_1)
69static void call_bc_transmit(struct rpc_task *task);
70#endif /* CONFIG_NFS_V4_1 */
66static void call_status(struct rpc_task *task); 71static void call_status(struct rpc_task *task);
67static void call_transmit_status(struct rpc_task *task); 72static void call_transmit_status(struct rpc_task *task);
68static void call_refresh(struct rpc_task *task); 73static void call_refresh(struct rpc_task *task);
@@ -613,6 +618,50 @@ rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
613} 618}
614EXPORT_SYMBOL_GPL(rpc_call_async); 619EXPORT_SYMBOL_GPL(rpc_call_async);
615 620
621#if defined(CONFIG_NFS_V4_1)
622/**
623 * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
624 * rpc_execute against it
625 * @ops: RPC call ops
626 */
627struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
628 const struct rpc_call_ops *tk_ops)
629{
630 struct rpc_task *task;
631 struct xdr_buf *xbufp = &req->rq_snd_buf;
632 struct rpc_task_setup task_setup_data = {
633 .callback_ops = tk_ops,
634 };
635
636 dprintk("RPC: rpc_run_bc_task req= %p\n", req);
637 /*
638 * Create an rpc_task to send the data
639 */
640 task = rpc_new_task(&task_setup_data);
641 if (!task) {
642 xprt_free_bc_request(req);
643 goto out;
644 }
645 task->tk_rqstp = req;
646
647 /*
648 * Set up the xdr_buf length.
649 * This also indicates that the buffer is XDR encoded already.
650 */
651 xbufp->len = xbufp->head[0].iov_len + xbufp->page_len +
652 xbufp->tail[0].iov_len;
653
654 task->tk_action = call_bc_transmit;
655 atomic_inc(&task->tk_count);
656 BUG_ON(atomic_read(&task->tk_count) != 2);
657 rpc_execute(task);
658
659out:
660 dprintk("RPC: rpc_run_bc_task: task= %p\n", task);
661 return task;
662}
663#endif /* CONFIG_NFS_V4_1 */
664
616void 665void
617rpc_call_start(struct rpc_task *task) 666rpc_call_start(struct rpc_task *task)
618{ 667{
@@ -695,6 +744,19 @@ void rpc_force_rebind(struct rpc_clnt *clnt)
695EXPORT_SYMBOL_GPL(rpc_force_rebind); 744EXPORT_SYMBOL_GPL(rpc_force_rebind);
696 745
697/* 746/*
747 * Restart an (async) RPC call from the call_prepare state.
748 * Usually called from within the exit handler.
749 */
750void
751rpc_restart_call_prepare(struct rpc_task *task)
752{
753 if (RPC_ASSASSINATED(task))
754 return;
755 task->tk_action = rpc_prepare_task;
756}
757EXPORT_SYMBOL_GPL(rpc_restart_call_prepare);
758
759/*
698 * Restart an (async) RPC call. Usually called from within the 760 * Restart an (async) RPC call. Usually called from within the
699 * exit handler. 761 * exit handler.
700 */ 762 */
@@ -1085,7 +1147,7 @@ call_transmit(struct rpc_task *task)
1085 * in order to allow access to the socket to other RPC requests. 1147 * in order to allow access to the socket to other RPC requests.
1086 */ 1148 */
1087 call_transmit_status(task); 1149 call_transmit_status(task);
1088 if (task->tk_msg.rpc_proc->p_decode != NULL) 1150 if (rpc_reply_expected(task))
1089 return; 1151 return;
1090 task->tk_action = rpc_exit_task; 1152 task->tk_action = rpc_exit_task;
1091 rpc_wake_up_queued_task(&task->tk_xprt->pending, task); 1153 rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
@@ -1120,6 +1182,72 @@ call_transmit_status(struct rpc_task *task)
1120 } 1182 }
1121} 1183}
1122 1184
1185#if defined(CONFIG_NFS_V4_1)
1186/*
1187 * 5b. Send the backchannel RPC reply. On error, drop the reply. In
1188 * addition, disconnect on connectivity errors.
1189 */
1190static void
1191call_bc_transmit(struct rpc_task *task)
1192{
1193 struct rpc_rqst *req = task->tk_rqstp;
1194
1195 BUG_ON(task->tk_status != 0);
1196 task->tk_status = xprt_prepare_transmit(task);
1197 if (task->tk_status == -EAGAIN) {
1198 /*
1199 * Could not reserve the transport. Try again after the
1200 * transport is released.
1201 */
1202 task->tk_status = 0;
1203 task->tk_action = call_bc_transmit;
1204 return;
1205 }
1206
1207 task->tk_action = rpc_exit_task;
1208 if (task->tk_status < 0) {
1209 printk(KERN_NOTICE "RPC: Could not send backchannel reply "
1210 "error: %d\n", task->tk_status);
1211 return;
1212 }
1213
1214 xprt_transmit(task);
1215 xprt_end_transmit(task);
1216 dprint_status(task);
1217 switch (task->tk_status) {
1218 case 0:
1219 /* Success */
1220 break;
1221 case -EHOSTDOWN:
1222 case -EHOSTUNREACH:
1223 case -ENETUNREACH:
1224 case -ETIMEDOUT:
1225 /*
1226 * Problem reaching the server. Disconnect and let the
1227 * forechannel reestablish the connection. The server will
1228 * have to retransmit the backchannel request and we'll
1229 * reprocess it. Since these ops are idempotent, there's no
1230 * need to cache our reply at this time.
1231 */
1232 printk(KERN_NOTICE "RPC: Could not send backchannel reply "
1233 "error: %d\n", task->tk_status);
1234 xprt_conditional_disconnect(task->tk_xprt,
1235 req->rq_connect_cookie);
1236 break;
1237 default:
1238 /*
1239 * We were unable to reply and will have to drop the
1240 * request. The server should reconnect and retransmit.
1241 */
1242 BUG_ON(task->tk_status == -EAGAIN);
1243 printk(KERN_NOTICE "RPC: Could not send backchannel reply "
1244 "error: %d\n", task->tk_status);
1245 break;
1246 }
1247 rpc_wake_up_queued_task(&req->rq_xprt->pending, task);
1248}
1249#endif /* CONFIG_NFS_V4_1 */
1250
1123/* 1251/*
1124 * 6. Sort out the RPC call status 1252 * 6. Sort out the RPC call status
1125 */ 1253 */
@@ -1130,8 +1258,8 @@ call_status(struct rpc_task *task)
1130 struct rpc_rqst *req = task->tk_rqstp; 1258 struct rpc_rqst *req = task->tk_rqstp;
1131 int status; 1259 int status;
1132 1260
1133 if (req->rq_received > 0 && !req->rq_bytes_sent) 1261 if (req->rq_reply_bytes_recvd > 0 && !req->rq_bytes_sent)
1134 task->tk_status = req->rq_received; 1262 task->tk_status = req->rq_reply_bytes_recvd;
1135 1263
1136 dprint_status(task); 1264 dprint_status(task);
1137 1265
@@ -1248,7 +1376,7 @@ call_decode(struct rpc_task *task)
1248 1376
1249 /* 1377 /*
1250 * Ensure that we see all writes made by xprt_complete_rqst() 1378 * Ensure that we see all writes made by xprt_complete_rqst()
1251 * before it changed req->rq_received. 1379 * before it changed req->rq_reply_bytes_recvd.
1252 */ 1380 */
1253 smp_rmb(); 1381 smp_rmb();
1254 req->rq_rcv_buf.len = req->rq_private_buf.len; 1382 req->rq_rcv_buf.len = req->rq_private_buf.len;
@@ -1289,7 +1417,7 @@ out_retry:
1289 task->tk_status = 0; 1417 task->tk_status = 0;
1290 /* Note: rpc_verify_header() may have freed the RPC slot */ 1418 /* Note: rpc_verify_header() may have freed the RPC slot */
1291 if (task->tk_rqstp == req) { 1419 if (task->tk_rqstp == req) {
1292 req->rq_received = req->rq_rcv_buf.len = 0; 1420 req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0;
1293 if (task->tk_client->cl_discrtry) 1421 if (task->tk_client->cl_discrtry)
1294 xprt_conditional_disconnect(task->tk_xprt, 1422 xprt_conditional_disconnect(task->tk_xprt,
1295 req->rq_connect_cookie); 1423 req->rq_connect_cookie);
@@ -1377,13 +1505,14 @@ rpc_verify_header(struct rpc_task *task)
1377 } 1505 }
1378 if ((len -= 3) < 0) 1506 if ((len -= 3) < 0)
1379 goto out_overflow; 1507 goto out_overflow;
1380 p += 1; /* skip XID */
1381 1508
1509 p += 1; /* skip XID */
1382 if ((n = ntohl(*p++)) != RPC_REPLY) { 1510 if ((n = ntohl(*p++)) != RPC_REPLY) {
1383 dprintk("RPC: %5u %s: not an RPC reply: %x\n", 1511 dprintk("RPC: %5u %s: not an RPC reply: %x\n",
1384 task->tk_pid, __func__, n); 1512 task->tk_pid, __func__, n);
1385 goto out_garbage; 1513 goto out_garbage;
1386 } 1514 }
1515
1387 if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { 1516 if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
1388 if (--len < 0) 1517 if (--len < 0)
1389 goto out_overflow; 1518 goto out_overflow;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index ff50a0546865..1102ce1251f7 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -569,7 +569,7 @@ EXPORT_SYMBOL_GPL(rpc_delay);
569/* 569/*
570 * Helper to call task->tk_ops->rpc_call_prepare 570 * Helper to call task->tk_ops->rpc_call_prepare
571 */ 571 */
572static void rpc_prepare_task(struct rpc_task *task) 572void rpc_prepare_task(struct rpc_task *task)
573{ 573{
574 task->tk_ops->rpc_call_prepare(task, task->tk_calldata); 574 task->tk_ops->rpc_call_prepare(task, task->tk_calldata);
575} 575}
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 1ef6e46d9da2..1b4e6791ecf3 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -141,12 +141,14 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats);
141void rpc_count_iostats(struct rpc_task *task) 141void rpc_count_iostats(struct rpc_task *task)
142{ 142{
143 struct rpc_rqst *req = task->tk_rqstp; 143 struct rpc_rqst *req = task->tk_rqstp;
144 struct rpc_iostats *stats = task->tk_client->cl_metrics; 144 struct rpc_iostats *stats;
145 struct rpc_iostats *op_metrics; 145 struct rpc_iostats *op_metrics;
146 long rtt, execute, queue; 146 long rtt, execute, queue;
147 147
148 if (!stats || !req) 148 if (!task->tk_client || !task->tk_client->cl_metrics || !req)
149 return; 149 return;
150
151 stats = task->tk_client->cl_metrics;
150 op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx]; 152 op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
151 153
152 op_metrics->om_ops++; 154 op_metrics->om_ops++;
@@ -154,7 +156,7 @@ void rpc_count_iostats(struct rpc_task *task)
154 op_metrics->om_timeouts += task->tk_timeouts; 156 op_metrics->om_timeouts += task->tk_timeouts;
155 157
156 op_metrics->om_bytes_sent += task->tk_bytes_sent; 158 op_metrics->om_bytes_sent += task->tk_bytes_sent;
157 op_metrics->om_bytes_recv += req->rq_received; 159 op_metrics->om_bytes_recv += req->rq_reply_bytes_recvd;
158 160
159 queue = (long)req->rq_xtime - task->tk_start; 161 queue = (long)req->rq_xtime - task->tk_start;
160 if (queue < 0) 162 if (queue < 0)
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h
new file mode 100644
index 000000000000..5d9dd742264b
--- /dev/null
+++ b/net/sunrpc/sunrpc.h
@@ -0,0 +1,37 @@
1/******************************************************************************
2
3(c) 2008 NetApp. All Rights Reserved.
4
5NetApp provides this source code under the GPL v2 License.
6The GPL v2 license is available at
7http://opensource.org/licenses/gpl-license.php.
8
9THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
12A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
13CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
15PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
17LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
18NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20
21******************************************************************************/
22
23/*
24 * Functions and macros used internally by RPC
25 */
26
27#ifndef _NET_SUNRPC_SUNRPC_H
28#define _NET_SUNRPC_SUNRPC_H
29
30static inline int rpc_reply_expected(struct rpc_task *task)
31{
32 return (task->tk_msg.rpc_proc != NULL) &&
33 (task->tk_msg.rpc_proc->p_decode != NULL);
34}
35
36#endif /* _NET_SUNRPC_SUNRPC_H */
37
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 5ed8931dfe98..952f206ff307 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -25,6 +25,7 @@
25#include <linux/sunrpc/stats.h> 25#include <linux/sunrpc/stats.h>
26#include <linux/sunrpc/svcsock.h> 26#include <linux/sunrpc/svcsock.h>
27#include <linux/sunrpc/clnt.h> 27#include <linux/sunrpc/clnt.h>
28#include <linux/sunrpc/bc_xprt.h>
28 29
29#define RPCDBG_FACILITY RPCDBG_SVCDSP 30#define RPCDBG_FACILITY RPCDBG_SVCDSP
30 31
@@ -486,6 +487,10 @@ svc_destroy(struct svc_serv *serv)
486 if (svc_serv_is_pooled(serv)) 487 if (svc_serv_is_pooled(serv))
487 svc_pool_map_put(); 488 svc_pool_map_put();
488 489
490#if defined(CONFIG_NFS_V4_1)
491 svc_sock_destroy(serv->bc_xprt);
492#endif /* CONFIG_NFS_V4_1 */
493
489 svc_unregister(serv); 494 svc_unregister(serv);
490 kfree(serv->sv_pools); 495 kfree(serv->sv_pools);
491 kfree(serv); 496 kfree(serv);
@@ -970,20 +975,18 @@ svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
970} 975}
971 976
972/* 977/*
973 * Process the RPC request. 978 * Common routine for processing the RPC request.
974 */ 979 */
975int 980static int
976svc_process(struct svc_rqst *rqstp) 981svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
977{ 982{
978 struct svc_program *progp; 983 struct svc_program *progp;
979 struct svc_version *versp = NULL; /* compiler food */ 984 struct svc_version *versp = NULL; /* compiler food */
980 struct svc_procedure *procp = NULL; 985 struct svc_procedure *procp = NULL;
981 struct kvec * argv = &rqstp->rq_arg.head[0];
982 struct kvec * resv = &rqstp->rq_res.head[0];
983 struct svc_serv *serv = rqstp->rq_server; 986 struct svc_serv *serv = rqstp->rq_server;
984 kxdrproc_t xdr; 987 kxdrproc_t xdr;
985 __be32 *statp; 988 __be32 *statp;
986 u32 dir, prog, vers, proc; 989 u32 prog, vers, proc;
987 __be32 auth_stat, rpc_stat; 990 __be32 auth_stat, rpc_stat;
988 int auth_res; 991 int auth_res;
989 __be32 *reply_statp; 992 __be32 *reply_statp;
@@ -993,19 +996,6 @@ svc_process(struct svc_rqst *rqstp)
993 if (argv->iov_len < 6*4) 996 if (argv->iov_len < 6*4)
994 goto err_short_len; 997 goto err_short_len;
995 998
996 /* setup response xdr_buf.
997 * Initially it has just one page
998 */
999 rqstp->rq_resused = 1;
1000 resv->iov_base = page_address(rqstp->rq_respages[0]);
1001 resv->iov_len = 0;
1002 rqstp->rq_res.pages = rqstp->rq_respages + 1;
1003 rqstp->rq_res.len = 0;
1004 rqstp->rq_res.page_base = 0;
1005 rqstp->rq_res.page_len = 0;
1006 rqstp->rq_res.buflen = PAGE_SIZE;
1007 rqstp->rq_res.tail[0].iov_base = NULL;
1008 rqstp->rq_res.tail[0].iov_len = 0;
1009 /* Will be turned off only in gss privacy case: */ 999 /* Will be turned off only in gss privacy case: */
1010 rqstp->rq_splice_ok = 1; 1000 rqstp->rq_splice_ok = 1;
1011 /* Will be turned off only when NFSv4 Sessions are used */ 1001 /* Will be turned off only when NFSv4 Sessions are used */
@@ -1014,17 +1004,13 @@ svc_process(struct svc_rqst *rqstp)
1014 /* Setup reply header */ 1004 /* Setup reply header */
1015 rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); 1005 rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp);
1016 1006
1017 rqstp->rq_xid = svc_getu32(argv);
1018 svc_putu32(resv, rqstp->rq_xid); 1007 svc_putu32(resv, rqstp->rq_xid);
1019 1008
1020 dir = svc_getnl(argv);
1021 vers = svc_getnl(argv); 1009 vers = svc_getnl(argv);
1022 1010
1023 /* First words of reply: */ 1011 /* First words of reply: */
1024 svc_putnl(resv, 1); /* REPLY */ 1012 svc_putnl(resv, 1); /* REPLY */
1025 1013
1026 if (dir != 0) /* direction != CALL */
1027 goto err_bad_dir;
1028 if (vers != 2) /* RPC version number */ 1014 if (vers != 2) /* RPC version number */
1029 goto err_bad_rpc; 1015 goto err_bad_rpc;
1030 1016
@@ -1147,7 +1133,7 @@ svc_process(struct svc_rqst *rqstp)
1147 sendit: 1133 sendit:
1148 if (svc_authorise(rqstp)) 1134 if (svc_authorise(rqstp))
1149 goto dropit; 1135 goto dropit;
1150 return svc_send(rqstp); 1136 return 1; /* Caller can now send it */
1151 1137
1152 dropit: 1138 dropit:
1153 svc_authorise(rqstp); /* doesn't hurt to call this twice */ 1139 svc_authorise(rqstp); /* doesn't hurt to call this twice */
@@ -1161,12 +1147,6 @@ err_short_len:
1161 1147
1162 goto dropit; /* drop request */ 1148 goto dropit; /* drop request */
1163 1149
1164err_bad_dir:
1165 svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
1166
1167 serv->sv_stats->rpcbadfmt++;
1168 goto dropit; /* drop request */
1169
1170err_bad_rpc: 1150err_bad_rpc:
1171 serv->sv_stats->rpcbadfmt++; 1151 serv->sv_stats->rpcbadfmt++;
1172 svc_putnl(resv, 1); /* REJECT */ 1152 svc_putnl(resv, 1); /* REJECT */
@@ -1220,6 +1200,100 @@ err_bad:
1220EXPORT_SYMBOL_GPL(svc_process); 1200EXPORT_SYMBOL_GPL(svc_process);
1221 1201
1222/* 1202/*
1203 * Process the RPC request.
1204 */
1205int
1206svc_process(struct svc_rqst *rqstp)
1207{
1208 struct kvec *argv = &rqstp->rq_arg.head[0];
1209 struct kvec *resv = &rqstp->rq_res.head[0];
1210 struct svc_serv *serv = rqstp->rq_server;
1211 u32 dir;
1212 int error;
1213
1214 /*
1215 * Setup response xdr_buf.
1216 * Initially it has just one page
1217 */
1218 rqstp->rq_resused = 1;
1219 resv->iov_base = page_address(rqstp->rq_respages[0]);
1220 resv->iov_len = 0;
1221 rqstp->rq_res.pages = rqstp->rq_respages + 1;
1222 rqstp->rq_res.len = 0;
1223 rqstp->rq_res.page_base = 0;
1224 rqstp->rq_res.page_len = 0;
1225 rqstp->rq_res.buflen = PAGE_SIZE;
1226 rqstp->rq_res.tail[0].iov_base = NULL;
1227 rqstp->rq_res.tail[0].iov_len = 0;
1228
1229 rqstp->rq_xid = svc_getu32(argv);
1230
1231 dir = svc_getnl(argv);
1232 if (dir != 0) {
1233 /* direction != CALL */
1234 svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
1235 serv->sv_stats->rpcbadfmt++;
1236 svc_drop(rqstp);
1237 return 0;
1238 }
1239
1240 error = svc_process_common(rqstp, argv, resv);
1241 if (error <= 0)
1242 return error;
1243
1244 return svc_send(rqstp);
1245}
1246
1247#if defined(CONFIG_NFS_V4_1)
1248/*
1249 * Process a backchannel RPC request that arrived over an existing
1250 * outbound connection
1251 */
1252int
1253bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
1254 struct svc_rqst *rqstp)
1255{
1256 struct kvec *argv = &rqstp->rq_arg.head[0];
1257 struct kvec *resv = &rqstp->rq_res.head[0];
1258 int error;
1259
1260 /* Build the svc_rqst used by the common processing routine */
1261 rqstp->rq_xprt = serv->bc_xprt;
1262 rqstp->rq_xid = req->rq_xid;
1263 rqstp->rq_prot = req->rq_xprt->prot;
1264 rqstp->rq_server = serv;
1265
1266 rqstp->rq_addrlen = sizeof(req->rq_xprt->addr);
1267 memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
1268 memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg));
1269 memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
1270
1271 /* reset result send buffer "put" position */
1272 resv->iov_len = 0;
1273
1274 if (rqstp->rq_prot != IPPROTO_TCP) {
1275 printk(KERN_ERR "No support for Non-TCP transports!\n");
1276 BUG();
1277 }
1278
1279 /*
1280 * Skip the next two words because they've already been
1281 * processed in the trasport
1282 */
1283 svc_getu32(argv); /* XID */
1284 svc_getnl(argv); /* CALLDIR */
1285
1286 error = svc_process_common(rqstp, argv, resv);
1287 if (error <= 0)
1288 return error;
1289
1290 memcpy(&req->rq_snd_buf, &rqstp->rq_res, sizeof(req->rq_snd_buf));
1291 return bc_send(req);
1292}
1293EXPORT_SYMBOL(bc_svc_process);
1294#endif /* CONFIG_NFS_V4_1 */
1295
1296/*
1223 * Return (transport-specific) limit on the rpc payload. 1297 * Return (transport-specific) limit on the rpc payload.
1224 */ 1298 */
1225u32 svc_max_payload(const struct svc_rqst *rqstp) 1299u32 svc_max_payload(const struct svc_rqst *rqstp)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 9d504234af4a..a2a03e500533 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1327,3 +1327,42 @@ static void svc_sock_free(struct svc_xprt *xprt)
1327 sock_release(svsk->sk_sock); 1327 sock_release(svsk->sk_sock);
1328 kfree(svsk); 1328 kfree(svsk);
1329} 1329}
1330
1331/*
1332 * Create a svc_xprt.
1333 *
1334 * For internal use only (e.g. nfsv4.1 backchannel).
1335 * Callers should typically use the xpo_create() method.
1336 */
1337struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot)
1338{
1339 struct svc_sock *svsk;
1340 struct svc_xprt *xprt = NULL;
1341
1342 dprintk("svc: %s\n", __func__);
1343 svsk = kzalloc(sizeof(*svsk), GFP_KERNEL);
1344 if (!svsk)
1345 goto out;
1346
1347 xprt = &svsk->sk_xprt;
1348 if (prot == IPPROTO_TCP)
1349 svc_xprt_init(&svc_tcp_class, xprt, serv);
1350 else if (prot == IPPROTO_UDP)
1351 svc_xprt_init(&svc_udp_class, xprt, serv);
1352 else
1353 BUG();
1354out:
1355 dprintk("svc: %s return %p\n", __func__, xprt);
1356 return xprt;
1357}
1358EXPORT_SYMBOL_GPL(svc_sock_create);
1359
1360/*
1361 * Destroy a svc_sock.
1362 */
1363void svc_sock_destroy(struct svc_xprt *xprt)
1364{
1365 if (xprt)
1366 kfree(container_of(xprt, struct svc_sock, sk_xprt));
1367}
1368EXPORT_SYMBOL_GPL(svc_sock_destroy);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 06ca058572f2..f412a852bc73 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -12,8 +12,9 @@
12 * - Next, the caller puts together the RPC message, stuffs it into 12 * - Next, the caller puts together the RPC message, stuffs it into
13 * the request struct, and calls xprt_transmit(). 13 * the request struct, and calls xprt_transmit().
14 * - xprt_transmit sends the message and installs the caller on the 14 * - xprt_transmit sends the message and installs the caller on the
15 * transport's wait list. At the same time, it installs a timer that 15 * transport's wait list. At the same time, if a reply is expected,
16 * is run after the packet's timeout has expired. 16 * it installs a timer that is run after the packet's timeout has
17 * expired.
17 * - When a packet arrives, the data_ready handler walks the list of 18 * - When a packet arrives, the data_ready handler walks the list of
18 * pending requests for that transport. If a matching XID is found, the 19 * pending requests for that transport. If a matching XID is found, the
19 * caller is woken up, and the timer removed. 20 * caller is woken up, and the timer removed.
@@ -46,6 +47,8 @@
46#include <linux/sunrpc/clnt.h> 47#include <linux/sunrpc/clnt.h>
47#include <linux/sunrpc/metrics.h> 48#include <linux/sunrpc/metrics.h>
48 49
50#include "sunrpc.h"
51
49/* 52/*
50 * Local variables 53 * Local variables
51 */ 54 */
@@ -192,8 +195,8 @@ EXPORT_SYMBOL_GPL(xprt_load_transport);
192 */ 195 */
193int xprt_reserve_xprt(struct rpc_task *task) 196int xprt_reserve_xprt(struct rpc_task *task)
194{ 197{
195 struct rpc_xprt *xprt = task->tk_xprt;
196 struct rpc_rqst *req = task->tk_rqstp; 198 struct rpc_rqst *req = task->tk_rqstp;
199 struct rpc_xprt *xprt = req->rq_xprt;
197 200
198 if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) { 201 if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
199 if (task == xprt->snd_task) 202 if (task == xprt->snd_task)
@@ -803,9 +806,10 @@ void xprt_complete_rqst(struct rpc_task *task, int copied)
803 806
804 list_del_init(&req->rq_list); 807 list_del_init(&req->rq_list);
805 req->rq_private_buf.len = copied; 808 req->rq_private_buf.len = copied;
806 /* Ensure all writes are done before we update req->rq_received */ 809 /* Ensure all writes are done before we update */
810 /* req->rq_reply_bytes_recvd */
807 smp_wmb(); 811 smp_wmb();
808 req->rq_received = copied; 812 req->rq_reply_bytes_recvd = copied;
809 rpc_wake_up_queued_task(&xprt->pending, task); 813 rpc_wake_up_queued_task(&xprt->pending, task);
810} 814}
811EXPORT_SYMBOL_GPL(xprt_complete_rqst); 815EXPORT_SYMBOL_GPL(xprt_complete_rqst);
@@ -820,7 +824,7 @@ static void xprt_timer(struct rpc_task *task)
820 dprintk("RPC: %5u xprt_timer\n", task->tk_pid); 824 dprintk("RPC: %5u xprt_timer\n", task->tk_pid);
821 825
822 spin_lock_bh(&xprt->transport_lock); 826 spin_lock_bh(&xprt->transport_lock);
823 if (!req->rq_received) { 827 if (!req->rq_reply_bytes_recvd) {
824 if (xprt->ops->timer) 828 if (xprt->ops->timer)
825 xprt->ops->timer(task); 829 xprt->ops->timer(task);
826 } else 830 } else
@@ -842,8 +846,8 @@ int xprt_prepare_transmit(struct rpc_task *task)
842 dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid); 846 dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid);
843 847
844 spin_lock_bh(&xprt->transport_lock); 848 spin_lock_bh(&xprt->transport_lock);
845 if (req->rq_received && !req->rq_bytes_sent) { 849 if (req->rq_reply_bytes_recvd && !req->rq_bytes_sent) {
846 err = req->rq_received; 850 err = req->rq_reply_bytes_recvd;
847 goto out_unlock; 851 goto out_unlock;
848 } 852 }
849 if (!xprt->ops->reserve_xprt(task)) 853 if (!xprt->ops->reserve_xprt(task))
@@ -855,7 +859,7 @@ out_unlock:
855 859
856void xprt_end_transmit(struct rpc_task *task) 860void xprt_end_transmit(struct rpc_task *task)
857{ 861{
858 xprt_release_write(task->tk_xprt, task); 862 xprt_release_write(task->tk_rqstp->rq_xprt, task);
859} 863}
860 864
861/** 865/**
@@ -872,8 +876,11 @@ void xprt_transmit(struct rpc_task *task)
872 876
873 dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); 877 dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
874 878
875 if (!req->rq_received) { 879 if (!req->rq_reply_bytes_recvd) {
876 if (list_empty(&req->rq_list)) { 880 if (list_empty(&req->rq_list) && rpc_reply_expected(task)) {
881 /*
882 * Add to the list only if we're expecting a reply
883 */
877 spin_lock_bh(&xprt->transport_lock); 884 spin_lock_bh(&xprt->transport_lock);
878 /* Update the softirq receive buffer */ 885 /* Update the softirq receive buffer */
879 memcpy(&req->rq_private_buf, &req->rq_rcv_buf, 886 memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
@@ -908,8 +915,13 @@ void xprt_transmit(struct rpc_task *task)
908 /* Don't race with disconnect */ 915 /* Don't race with disconnect */
909 if (!xprt_connected(xprt)) 916 if (!xprt_connected(xprt))
910 task->tk_status = -ENOTCONN; 917 task->tk_status = -ENOTCONN;
911 else if (!req->rq_received) 918 else if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) {
919 /*
920 * Sleep on the pending queue since
921 * we're expecting a reply.
922 */
912 rpc_sleep_on(&xprt->pending, task, xprt_timer); 923 rpc_sleep_on(&xprt->pending, task, xprt_timer);
924 }
913 spin_unlock_bh(&xprt->transport_lock); 925 spin_unlock_bh(&xprt->transport_lock);
914} 926}
915 927
@@ -982,11 +994,17 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
982 */ 994 */
983void xprt_release(struct rpc_task *task) 995void xprt_release(struct rpc_task *task)
984{ 996{
985 struct rpc_xprt *xprt = task->tk_xprt; 997 struct rpc_xprt *xprt;
986 struct rpc_rqst *req; 998 struct rpc_rqst *req;
999 int is_bc_request;
987 1000
988 if (!(req = task->tk_rqstp)) 1001 if (!(req = task->tk_rqstp))
989 return; 1002 return;
1003
1004 /* Preallocated backchannel request? */
1005 is_bc_request = bc_prealloc(req);
1006
1007 xprt = req->rq_xprt;
990 rpc_count_iostats(task); 1008 rpc_count_iostats(task);
991 spin_lock_bh(&xprt->transport_lock); 1009 spin_lock_bh(&xprt->transport_lock);
992 xprt->ops->release_xprt(xprt, task); 1010 xprt->ops->release_xprt(xprt, task);
@@ -999,10 +1017,19 @@ void xprt_release(struct rpc_task *task)
999 mod_timer(&xprt->timer, 1017 mod_timer(&xprt->timer,
1000 xprt->last_used + xprt->idle_timeout); 1018 xprt->last_used + xprt->idle_timeout);
1001 spin_unlock_bh(&xprt->transport_lock); 1019 spin_unlock_bh(&xprt->transport_lock);
1002 xprt->ops->buf_free(req->rq_buffer); 1020 if (!bc_prealloc(req))
1021 xprt->ops->buf_free(req->rq_buffer);
1003 task->tk_rqstp = NULL; 1022 task->tk_rqstp = NULL;
1004 if (req->rq_release_snd_buf) 1023 if (req->rq_release_snd_buf)
1005 req->rq_release_snd_buf(req); 1024 req->rq_release_snd_buf(req);
1025
1026 /*
1027 * Early exit if this is a backchannel preallocated request.
1028 * There is no need to have it added to the RPC slot list.
1029 */
1030 if (is_bc_request)
1031 return;
1032
1006 memset(req, 0, sizeof(*req)); /* mark unused */ 1033 memset(req, 0, sizeof(*req)); /* mark unused */
1007 1034
1008 dprintk("RPC: %5u release request %p\n", task->tk_pid, req); 1035 dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
@@ -1049,6 +1076,11 @@ found:
1049 1076
1050 INIT_LIST_HEAD(&xprt->free); 1077 INIT_LIST_HEAD(&xprt->free);
1051 INIT_LIST_HEAD(&xprt->recv); 1078 INIT_LIST_HEAD(&xprt->recv);
1079#if defined(CONFIG_NFS_V4_1)
1080 spin_lock_init(&xprt->bc_pa_lock);
1081 INIT_LIST_HEAD(&xprt->bc_pa_list);
1082#endif /* CONFIG_NFS_V4_1 */
1083
1052 INIT_WORK(&xprt->task_cleanup, xprt_autoclose); 1084 INIT_WORK(&xprt->task_cleanup, xprt_autoclose);
1053 setup_timer(&xprt->timer, xprt_init_autodisconnect, 1085 setup_timer(&xprt->timer, xprt_init_autodisconnect,
1054 (unsigned long)xprt); 1086 (unsigned long)xprt);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 6c2d61586551..9111d11c09fd 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -34,6 +34,9 @@
34#include <linux/sunrpc/sched.h> 34#include <linux/sunrpc/sched.h>
35#include <linux/sunrpc/xprtsock.h> 35#include <linux/sunrpc/xprtsock.h>
36#include <linux/file.h> 36#include <linux/file.h>
37#ifdef CONFIG_NFS_V4_1
38#include <linux/sunrpc/bc_xprt.h>
39#endif
37 40
38#include <net/sock.h> 41#include <net/sock.h>
39#include <net/checksum.h> 42#include <net/checksum.h>
@@ -270,6 +273,13 @@ struct sock_xprt {
270#define TCP_RCV_COPY_FRAGHDR (1UL << 1) 273#define TCP_RCV_COPY_FRAGHDR (1UL << 1)
271#define TCP_RCV_COPY_XID (1UL << 2) 274#define TCP_RCV_COPY_XID (1UL << 2)
272#define TCP_RCV_COPY_DATA (1UL << 3) 275#define TCP_RCV_COPY_DATA (1UL << 3)
276#define TCP_RCV_READ_CALLDIR (1UL << 4)
277#define TCP_RCV_COPY_CALLDIR (1UL << 5)
278
279/*
280 * TCP RPC flags
281 */
282#define TCP_RPC_REPLY (1UL << 6)
273 283
274static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) 284static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
275{ 285{
@@ -956,7 +966,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea
956 transport->tcp_offset = 0; 966 transport->tcp_offset = 0;
957 967
958 /* Sanity check of the record length */ 968 /* Sanity check of the record length */
959 if (unlikely(transport->tcp_reclen < 4)) { 969 if (unlikely(transport->tcp_reclen < 8)) {
960 dprintk("RPC: invalid TCP record fragment length\n"); 970 dprintk("RPC: invalid TCP record fragment length\n");
961 xprt_force_disconnect(xprt); 971 xprt_force_disconnect(xprt);
962 return; 972 return;
@@ -991,33 +1001,77 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r
991 if (used != len) 1001 if (used != len)
992 return; 1002 return;
993 transport->tcp_flags &= ~TCP_RCV_COPY_XID; 1003 transport->tcp_flags &= ~TCP_RCV_COPY_XID;
994 transport->tcp_flags |= TCP_RCV_COPY_DATA; 1004 transport->tcp_flags |= TCP_RCV_READ_CALLDIR;
995 transport->tcp_copied = 4; 1005 transport->tcp_copied = 4;
996 dprintk("RPC: reading reply for XID %08x\n", 1006 dprintk("RPC: reading %s XID %08x\n",
1007 (transport->tcp_flags & TCP_RPC_REPLY) ? "reply for"
1008 : "request with",
997 ntohl(transport->tcp_xid)); 1009 ntohl(transport->tcp_xid));
998 xs_tcp_check_fraghdr(transport); 1010 xs_tcp_check_fraghdr(transport);
999} 1011}
1000 1012
1001static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) 1013static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
1014 struct xdr_skb_reader *desc)
1002{ 1015{
1003 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); 1016 size_t len, used;
1004 struct rpc_rqst *req; 1017 u32 offset;
1018 __be32 calldir;
1019
1020 /*
1021 * We want transport->tcp_offset to be 8 at the end of this routine
1022 * (4 bytes for the xid and 4 bytes for the call/reply flag).
1023 * When this function is called for the first time,
1024 * transport->tcp_offset is 4 (after having already read the xid).
1025 */
1026 offset = transport->tcp_offset - sizeof(transport->tcp_xid);
1027 len = sizeof(calldir) - offset;
1028 dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len);
1029 used = xdr_skb_read_bits(desc, &calldir, len);
1030 transport->tcp_offset += used;
1031 if (used != len)
1032 return;
1033 transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR;
1034 transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
1035 transport->tcp_flags |= TCP_RCV_COPY_DATA;
1036 /*
1037 * We don't yet have the XDR buffer, so we will write the calldir
1038 * out after we get the buffer from the 'struct rpc_rqst'
1039 */
1040 if (ntohl(calldir) == RPC_REPLY)
1041 transport->tcp_flags |= TCP_RPC_REPLY;
1042 else
1043 transport->tcp_flags &= ~TCP_RPC_REPLY;
1044 dprintk("RPC: reading %s CALL/REPLY flag %08x\n",
1045 (transport->tcp_flags & TCP_RPC_REPLY) ?
1046 "reply for" : "request with", calldir);
1047 xs_tcp_check_fraghdr(transport);
1048}
1049
1050static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
1051 struct xdr_skb_reader *desc,
1052 struct rpc_rqst *req)
1053{
1054 struct sock_xprt *transport =
1055 container_of(xprt, struct sock_xprt, xprt);
1005 struct xdr_buf *rcvbuf; 1056 struct xdr_buf *rcvbuf;
1006 size_t len; 1057 size_t len;
1007 ssize_t r; 1058 ssize_t r;
1008 1059
1009 /* Find and lock the request corresponding to this xid */ 1060 rcvbuf = &req->rq_private_buf;
1010 spin_lock(&xprt->transport_lock); 1061
1011 req = xprt_lookup_rqst(xprt, transport->tcp_xid); 1062 if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
1012 if (!req) { 1063 /*
1013 transport->tcp_flags &= ~TCP_RCV_COPY_DATA; 1064 * Save the RPC direction in the XDR buffer
1014 dprintk("RPC: XID %08x request not found!\n", 1065 */
1015 ntohl(transport->tcp_xid)); 1066 __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ?
1016 spin_unlock(&xprt->transport_lock); 1067 htonl(RPC_REPLY) : 0;
1017 return; 1068
1069 memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
1070 &calldir, sizeof(calldir));
1071 transport->tcp_copied += sizeof(calldir);
1072 transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
1018 } 1073 }
1019 1074
1020 rcvbuf = &req->rq_private_buf;
1021 len = desc->count; 1075 len = desc->count;
1022 if (len > transport->tcp_reclen - transport->tcp_offset) { 1076 if (len > transport->tcp_reclen - transport->tcp_offset) {
1023 struct xdr_skb_reader my_desc; 1077 struct xdr_skb_reader my_desc;
@@ -1054,7 +1108,7 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea
1054 "tcp_offset = %u, tcp_reclen = %u\n", 1108 "tcp_offset = %u, tcp_reclen = %u\n",
1055 xprt, transport->tcp_copied, 1109 xprt, transport->tcp_copied,
1056 transport->tcp_offset, transport->tcp_reclen); 1110 transport->tcp_offset, transport->tcp_reclen);
1057 goto out; 1111 return;
1058 } 1112 }
1059 1113
1060 dprintk("RPC: XID %08x read %Zd bytes\n", 1114 dprintk("RPC: XID %08x read %Zd bytes\n",
@@ -1070,11 +1124,125 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea
1070 transport->tcp_flags &= ~TCP_RCV_COPY_DATA; 1124 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1071 } 1125 }
1072 1126
1073out: 1127 return;
1128}
1129
1130/*
1131 * Finds the request corresponding to the RPC xid and invokes the common
1132 * tcp read code to read the data.
1133 */
1134static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
1135 struct xdr_skb_reader *desc)
1136{
1137 struct sock_xprt *transport =
1138 container_of(xprt, struct sock_xprt, xprt);
1139 struct rpc_rqst *req;
1140
1141 dprintk("RPC: read reply XID %08x\n", ntohl(transport->tcp_xid));
1142
1143 /* Find and lock the request corresponding to this xid */
1144 spin_lock(&xprt->transport_lock);
1145 req = xprt_lookup_rqst(xprt, transport->tcp_xid);
1146 if (!req) {
1147 dprintk("RPC: XID %08x request not found!\n",
1148 ntohl(transport->tcp_xid));
1149 spin_unlock(&xprt->transport_lock);
1150 return -1;
1151 }
1152
1153 xs_tcp_read_common(xprt, desc, req);
1154
1074 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) 1155 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
1075 xprt_complete_rqst(req->rq_task, transport->tcp_copied); 1156 xprt_complete_rqst(req->rq_task, transport->tcp_copied);
1157
1076 spin_unlock(&xprt->transport_lock); 1158 spin_unlock(&xprt->transport_lock);
1077 xs_tcp_check_fraghdr(transport); 1159 return 0;
1160}
1161
1162#if defined(CONFIG_NFS_V4_1)
1163/*
1164 * Obtains an rpc_rqst previously allocated and invokes the common
1165 * tcp read code to read the data. The result is placed in the callback
1166 * queue.
1167 * If we're unable to obtain the rpc_rqst we schedule the closing of the
1168 * connection and return -1.
1169 */
1170static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
1171 struct xdr_skb_reader *desc)
1172{
1173 struct sock_xprt *transport =
1174 container_of(xprt, struct sock_xprt, xprt);
1175 struct rpc_rqst *req;
1176
1177 req = xprt_alloc_bc_request(xprt);
1178 if (req == NULL) {
1179 printk(KERN_WARNING "Callback slot table overflowed\n");
1180 xprt_force_disconnect(xprt);
1181 return -1;
1182 }
1183
1184 req->rq_xid = transport->tcp_xid;
1185 dprintk("RPC: read callback XID %08x\n", ntohl(req->rq_xid));
1186 xs_tcp_read_common(xprt, desc, req);
1187
1188 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
1189 struct svc_serv *bc_serv = xprt->bc_serv;
1190
1191 /*
1192 * Add callback request to callback list. The callback
1193 * service sleeps on the sv_cb_waitq waiting for new
1194 * requests. Wake it up after adding enqueing the
1195 * request.
1196 */
1197 dprintk("RPC: add callback request to list\n");
1198 spin_lock(&bc_serv->sv_cb_lock);
1199 list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
1200 spin_unlock(&bc_serv->sv_cb_lock);
1201 wake_up(&bc_serv->sv_cb_waitq);
1202 }
1203
1204 req->rq_private_buf.len = transport->tcp_copied;
1205
1206 return 0;
1207}
1208
1209static inline int _xs_tcp_read_data(struct rpc_xprt *xprt,
1210 struct xdr_skb_reader *desc)
1211{
1212 struct sock_xprt *transport =
1213 container_of(xprt, struct sock_xprt, xprt);
1214
1215 return (transport->tcp_flags & TCP_RPC_REPLY) ?
1216 xs_tcp_read_reply(xprt, desc) :
1217 xs_tcp_read_callback(xprt, desc);
1218}
1219#else
1220static inline int _xs_tcp_read_data(struct rpc_xprt *xprt,
1221 struct xdr_skb_reader *desc)
1222{
1223 return xs_tcp_read_reply(xprt, desc);
1224}
1225#endif /* CONFIG_NFS_V4_1 */
1226
1227/*
1228 * Read data off the transport. This can be either an RPC_CALL or an
1229 * RPC_REPLY. Relay the processing to helper functions.
1230 */
1231static void xs_tcp_read_data(struct rpc_xprt *xprt,
1232 struct xdr_skb_reader *desc)
1233{
1234 struct sock_xprt *transport =
1235 container_of(xprt, struct sock_xprt, xprt);
1236
1237 if (_xs_tcp_read_data(xprt, desc) == 0)
1238 xs_tcp_check_fraghdr(transport);
1239 else {
1240 /*
1241 * The transport_lock protects the request handling.
1242 * There's no need to hold it to update the tcp_flags.
1243 */
1244 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1245 }
1078} 1246}
1079 1247
1080static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc) 1248static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc)
@@ -1114,9 +1282,14 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
1114 xs_tcp_read_xid(transport, &desc); 1282 xs_tcp_read_xid(transport, &desc);
1115 continue; 1283 continue;
1116 } 1284 }
1285 /* Read in the call/reply flag */
1286 if (transport->tcp_flags & TCP_RCV_READ_CALLDIR) {
1287 xs_tcp_read_calldir(transport, &desc);
1288 continue;
1289 }
1117 /* Read in the request data */ 1290 /* Read in the request data */
1118 if (transport->tcp_flags & TCP_RCV_COPY_DATA) { 1291 if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
1119 xs_tcp_read_request(xprt, &desc); 1292 xs_tcp_read_data(xprt, &desc);
1120 continue; 1293 continue;
1121 } 1294 }
1122 /* Skip over any trailing bytes on short reads */ 1295 /* Skip over any trailing bytes on short reads */
@@ -2010,6 +2183,9 @@ static struct rpc_xprt_ops xs_tcp_ops = {
2010 .buf_free = rpc_free, 2183 .buf_free = rpc_free,
2011 .send_request = xs_tcp_send_request, 2184 .send_request = xs_tcp_send_request,
2012 .set_retrans_timeout = xprt_set_retrans_timeout_def, 2185 .set_retrans_timeout = xprt_set_retrans_timeout_def,
2186#if defined(CONFIG_NFS_V4_1)
2187 .release_request = bc_release_request,
2188#endif /* CONFIG_NFS_V4_1 */
2013 .close = xs_tcp_close, 2189 .close = xs_tcp_close,
2014 .destroy = xs_destroy, 2190 .destroy = xs_destroy,
2015 .print_stats = xs_tcp_print_stats, 2191 .print_stats = xs_tcp_print_stats,