aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/callback.h8
-rw-r--r--fs/nfs/callback_proc.c165
-rw-r--r--fs/nfs/callback_xdr.c105
-rw-r--r--fs/nfs/client.c48
-rw-r--r--fs/nfs/dns_resolve.c18
-rw-r--r--fs/nfs/file.c30
-rw-r--r--fs/nfs/inode.c7
-rw-r--r--fs/nfs/nfs3proc.c9
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c103
-rw-r--r--fs/nfs/nfs4renewd.c24
-rw-r--r--fs/nfs/nfs4state.c118
-rw-r--r--fs/nfs/nfs4xdr.c10
-rw-r--r--fs/nfs/proc.c41
14 files changed, 510 insertions, 178 deletions
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index d4036be0b589..85a7cfd1b8dd 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -119,6 +119,14 @@ struct cb_recallanyargs {
119}; 119};
120 120
121extern unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy); 121extern unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy);
122
123struct cb_recallslotargs {
124 struct sockaddr *crsa_addr;
125 uint32_t crsa_target_max_slots;
126};
127extern unsigned nfs4_callback_recallslot(struct cb_recallslotargs *args,
128 void *dummy);
129
122#endif /* CONFIG_NFS_V4_1 */ 130#endif /* CONFIG_NFS_V4_1 */
123 131
124extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); 132extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index defa9b4c470e..84761b5bb8e2 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -143,44 +143,49 @@ int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const n
143 * Return success if the sequenceID is one more than what we last saw on 143 * Return success if the sequenceID is one more than what we last saw on
144 * this slot, accounting for wraparound. Increments the slot's sequence. 144 * this slot, accounting for wraparound. Increments the slot's sequence.
145 * 145 *
146 * We don't yet implement a duplicate request cache, so at this time 146 * We don't yet implement a duplicate request cache, instead we set the
147 * we will log replays, and process them as if we had not seen them before, 147 * back channel ca_maxresponsesize_cached to zero. This is OK for now
148 * but we don't bump the sequence in the slot. Not too worried about it,
149 * since we only currently implement idempotent callbacks anyway. 148 * since we only currently implement idempotent callbacks anyway.
150 * 149 *
151 * We have a single slot backchannel at this time, so we don't bother 150 * We have a single slot backchannel at this time, so we don't bother
152 * checking the used_slots bit array on the table. The lower layer guarantees 151 * checking the used_slots bit array on the table. The lower layer guarantees
153 * a single outstanding callback request at a time. 152 * a single outstanding callback request at a time.
154 */ 153 */
155static int 154static __be32
156validate_seqid(struct nfs4_slot_table *tbl, u32 slotid, u32 seqid) 155validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
157{ 156{
158 struct nfs4_slot *slot; 157 struct nfs4_slot *slot;
159 158
160 dprintk("%s enter. slotid %d seqid %d\n", 159 dprintk("%s enter. slotid %d seqid %d\n",
161 __func__, slotid, seqid); 160 __func__, args->csa_slotid, args->csa_sequenceid);
162 161
163 if (slotid > NFS41_BC_MAX_CALLBACKS) 162 if (args->csa_slotid > NFS41_BC_MAX_CALLBACKS)
164 return htonl(NFS4ERR_BADSLOT); 163 return htonl(NFS4ERR_BADSLOT);
165 164
166 slot = tbl->slots + slotid; 165 slot = tbl->slots + args->csa_slotid;
167 dprintk("%s slot table seqid: %d\n", __func__, slot->seq_nr); 166 dprintk("%s slot table seqid: %d\n", __func__, slot->seq_nr);
168 167
169 /* Normal */ 168 /* Normal */
170 if (likely(seqid == slot->seq_nr + 1)) { 169 if (likely(args->csa_sequenceid == slot->seq_nr + 1)) {
171 slot->seq_nr++; 170 slot->seq_nr++;
172 return htonl(NFS4_OK); 171 return htonl(NFS4_OK);
173 } 172 }
174 173
175 /* Replay */ 174 /* Replay */
176 if (seqid == slot->seq_nr) { 175 if (args->csa_sequenceid == slot->seq_nr) {
177 dprintk("%s seqid %d is a replay - no DRC available\n", 176 dprintk("%s seqid %d is a replay\n",
178 __func__, seqid); 177 __func__, args->csa_sequenceid);
179 return htonl(NFS4_OK); 178 /* Signal process_op to set this error on next op */
179 if (args->csa_cachethis == 0)
180 return htonl(NFS4ERR_RETRY_UNCACHED_REP);
181
182 /* The ca_maxresponsesize_cached is 0 with no DRC */
183 else if (args->csa_cachethis == 1)
184 return htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE);
180 } 185 }
181 186
182 /* Wraparound */ 187 /* Wraparound */
183 if (seqid == 1 && (slot->seq_nr + 1) == 0) { 188 if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
184 slot->seq_nr = 1; 189 slot->seq_nr = 1;
185 return htonl(NFS4_OK); 190 return htonl(NFS4_OK);
186 } 191 }
@@ -225,27 +230,87 @@ validate_seqid(struct nfs4_slot_table *tbl, u32 slotid, u32 seqid)
225 return NULL; 230 return NULL;
226} 231}
227 232
228/* FIXME: referring calls should be processed */ 233/*
229unsigned nfs4_callback_sequence(struct cb_sequenceargs *args, 234 * For each referring call triple, check the session's slot table for
235 * a match. If the slot is in use and the sequence numbers match, the
236 * client is still waiting for a response to the original request.
237 */
238static bool referring_call_exists(struct nfs_client *clp,
239 uint32_t nrclists,
240 struct referring_call_list *rclists)
241{
242 bool status = 0;
243 int i, j;
244 struct nfs4_session *session;
245 struct nfs4_slot_table *tbl;
246 struct referring_call_list *rclist;
247 struct referring_call *ref;
248
249 /*
250 * XXX When client trunking is implemented, this becomes
251 * a session lookup from within the loop
252 */
253 session = clp->cl_session;
254 tbl = &session->fc_slot_table;
255
256 for (i = 0; i < nrclists; i++) {
257 rclist = &rclists[i];
258 if (memcmp(session->sess_id.data,
259 rclist->rcl_sessionid.data,
260 NFS4_MAX_SESSIONID_LEN) != 0)
261 continue;
262
263 for (j = 0; j < rclist->rcl_nrefcalls; j++) {
264 ref = &rclist->rcl_refcalls[j];
265
266 dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u "
267 "slotid %u\n", __func__,
268 ((u32 *)&rclist->rcl_sessionid.data)[0],
269 ((u32 *)&rclist->rcl_sessionid.data)[1],
270 ((u32 *)&rclist->rcl_sessionid.data)[2],
271 ((u32 *)&rclist->rcl_sessionid.data)[3],
272 ref->rc_sequenceid, ref->rc_slotid);
273
274 spin_lock(&tbl->slot_tbl_lock);
275 status = (test_bit(ref->rc_slotid, tbl->used_slots) &&
276 tbl->slots[ref->rc_slotid].seq_nr ==
277 ref->rc_sequenceid);
278 spin_unlock(&tbl->slot_tbl_lock);
279 if (status)
280 goto out;
281 }
282 }
283
284out:
285 return status;
286}
287
288__be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
230 struct cb_sequenceres *res) 289 struct cb_sequenceres *res)
231{ 290{
232 struct nfs_client *clp; 291 struct nfs_client *clp;
233 int i, status; 292 int i;
234 293 __be32 status;
235 for (i = 0; i < args->csa_nrclists; i++)
236 kfree(args->csa_rclists[i].rcl_refcalls);
237 kfree(args->csa_rclists);
238 294
239 status = htonl(NFS4ERR_BADSESSION); 295 status = htonl(NFS4ERR_BADSESSION);
240 clp = find_client_with_session(args->csa_addr, 4, &args->csa_sessionid); 296 clp = find_client_with_session(args->csa_addr, 4, &args->csa_sessionid);
241 if (clp == NULL) 297 if (clp == NULL)
242 goto out; 298 goto out;
243 299
244 status = validate_seqid(&clp->cl_session->bc_slot_table, 300 status = validate_seqid(&clp->cl_session->bc_slot_table, args);
245 args->csa_slotid, args->csa_sequenceid);
246 if (status) 301 if (status)
247 goto out_putclient; 302 goto out_putclient;
248 303
304 /*
305 * Check for pending referring calls. If a match is found, a
306 * related callback was received before the response to the original
307 * call.
308 */
309 if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) {
310 status = htonl(NFS4ERR_DELAY);
311 goto out_putclient;
312 }
313
249 memcpy(&res->csr_sessionid, &args->csa_sessionid, 314 memcpy(&res->csr_sessionid, &args->csa_sessionid,
250 sizeof(res->csr_sessionid)); 315 sizeof(res->csr_sessionid));
251 res->csr_sequenceid = args->csa_sequenceid; 316 res->csr_sequenceid = args->csa_sequenceid;
@@ -256,15 +321,23 @@ unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
256out_putclient: 321out_putclient:
257 nfs_put_client(clp); 322 nfs_put_client(clp);
258out: 323out:
259 dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); 324 for (i = 0; i < args->csa_nrclists; i++)
260 res->csr_status = status; 325 kfree(args->csa_rclists[i].rcl_refcalls);
261 return res->csr_status; 326 kfree(args->csa_rclists);
327
328 if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP))
329 res->csr_status = 0;
330 else
331 res->csr_status = status;
332 dprintk("%s: exit with status = %d res->csr_status %d\n", __func__,
333 ntohl(status), ntohl(res->csr_status));
334 return status;
262} 335}
263 336
264unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy) 337__be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy)
265{ 338{
266 struct nfs_client *clp; 339 struct nfs_client *clp;
267 int status; 340 __be32 status;
268 fmode_t flags = 0; 341 fmode_t flags = 0;
269 342
270 status = htonl(NFS4ERR_OP_NOT_IN_SESSION); 343 status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
@@ -289,4 +362,40 @@ out:
289 dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); 362 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
290 return status; 363 return status;
291} 364}
365
366/* Reduce the fore channel's max_slots to the target value */
367__be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy)
368{
369 struct nfs_client *clp;
370 struct nfs4_slot_table *fc_tbl;
371 __be32 status;
372
373 status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
374 clp = nfs_find_client(args->crsa_addr, 4);
375 if (clp == NULL)
376 goto out;
377
378 dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n",
379 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR),
380 args->crsa_target_max_slots);
381
382 fc_tbl = &clp->cl_session->fc_slot_table;
383
384 status = htonl(NFS4ERR_BAD_HIGH_SLOT);
385 if (args->crsa_target_max_slots > fc_tbl->max_slots ||
386 args->crsa_target_max_slots < 1)
387 goto out_putclient;
388
389 status = htonl(NFS4_OK);
390 if (args->crsa_target_max_slots == fc_tbl->max_slots)
391 goto out_putclient;
392
393 fc_tbl->target_max_slots = args->crsa_target_max_slots;
394 nfs41_handle_recall_slot(clp);
395out_putclient:
396 nfs_put_client(clp); /* balance nfs_find_client */
397out:
398 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
399 return status;
400}
292#endif /* CONFIG_NFS_V4_1 */ 401#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 8e1a2511c8be..db30c0b398b5 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -24,10 +24,14 @@
24#define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \ 24#define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
25 4 + 1 + 3) 25 4 + 1 + 3)
26#define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) 26#define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
27#define CB_OP_RECALLSLOT_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
27#endif /* CONFIG_NFS_V4_1 */ 28#endif /* CONFIG_NFS_V4_1 */
28 29
29#define NFSDBG_FACILITY NFSDBG_CALLBACK 30#define NFSDBG_FACILITY NFSDBG_CALLBACK
30 31
32/* Internal error code */
33#define NFS4ERR_RESOURCE_HDR 11050
34
31typedef __be32 (*callback_process_op_t)(void *, void *); 35typedef __be32 (*callback_process_op_t)(void *, void *);
32typedef __be32 (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *); 36typedef __be32 (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *);
33typedef __be32 (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *); 37typedef __be32 (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *);
@@ -173,7 +177,7 @@ static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op)
173 __be32 *p; 177 __be32 *p;
174 p = read_buf(xdr, 4); 178 p = read_buf(xdr, 4);
175 if (unlikely(p == NULL)) 179 if (unlikely(p == NULL))
176 return htonl(NFS4ERR_RESOURCE); 180 return htonl(NFS4ERR_RESOURCE_HDR);
177 *op = ntohl(*p); 181 *op = ntohl(*p);
178 return 0; 182 return 0;
179} 183}
@@ -215,10 +219,10 @@ out:
215 219
216#if defined(CONFIG_NFS_V4_1) 220#if defined(CONFIG_NFS_V4_1)
217 221
218static unsigned decode_sessionid(struct xdr_stream *xdr, 222static __be32 decode_sessionid(struct xdr_stream *xdr,
219 struct nfs4_sessionid *sid) 223 struct nfs4_sessionid *sid)
220{ 224{
221 uint32_t *p; 225 __be32 *p;
222 int len = NFS4_MAX_SESSIONID_LEN; 226 int len = NFS4_MAX_SESSIONID_LEN;
223 227
224 p = read_buf(xdr, len); 228 p = read_buf(xdr, len);
@@ -229,12 +233,12 @@ static unsigned decode_sessionid(struct xdr_stream *xdr,
229 return 0; 233 return 0;
230} 234}
231 235
232static unsigned decode_rc_list(struct xdr_stream *xdr, 236static __be32 decode_rc_list(struct xdr_stream *xdr,
233 struct referring_call_list *rc_list) 237 struct referring_call_list *rc_list)
234{ 238{
235 uint32_t *p; 239 __be32 *p;
236 int i; 240 int i;
237 unsigned status; 241 __be32 status;
238 242
239 status = decode_sessionid(xdr, &rc_list->rcl_sessionid); 243 status = decode_sessionid(xdr, &rc_list->rcl_sessionid);
240 if (status) 244 if (status)
@@ -267,13 +271,13 @@ out:
267 return status; 271 return status;
268} 272}
269 273
270static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp, 274static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
271 struct xdr_stream *xdr, 275 struct xdr_stream *xdr,
272 struct cb_sequenceargs *args) 276 struct cb_sequenceargs *args)
273{ 277{
274 uint32_t *p; 278 __be32 *p;
275 int i; 279 int i;
276 unsigned status; 280 __be32 status;
277 281
278 status = decode_sessionid(xdr, &args->csa_sessionid); 282 status = decode_sessionid(xdr, &args->csa_sessionid);
279 if (status) 283 if (status)
@@ -327,11 +331,11 @@ out_free:
327 goto out; 331 goto out;
328} 332}
329 333
330static unsigned decode_recallany_args(struct svc_rqst *rqstp, 334static __be32 decode_recallany_args(struct svc_rqst *rqstp,
331 struct xdr_stream *xdr, 335 struct xdr_stream *xdr,
332 struct cb_recallanyargs *args) 336 struct cb_recallanyargs *args)
333{ 337{
334 uint32_t *p; 338 __be32 *p;
335 339
336 args->craa_addr = svc_addr(rqstp); 340 args->craa_addr = svc_addr(rqstp);
337 p = read_buf(xdr, 4); 341 p = read_buf(xdr, 4);
@@ -346,6 +350,20 @@ static unsigned decode_recallany_args(struct svc_rqst *rqstp,
346 return 0; 350 return 0;
347} 351}
348 352
353static __be32 decode_recallslot_args(struct svc_rqst *rqstp,
354 struct xdr_stream *xdr,
355 struct cb_recallslotargs *args)
356{
357 __be32 *p;
358
359 args->crsa_addr = svc_addr(rqstp);
360 p = read_buf(xdr, 4);
361 if (unlikely(p == NULL))
362 return htonl(NFS4ERR_BADXDR);
363 args->crsa_target_max_slots = ntohl(*p++);
364 return 0;
365}
366
349#endif /* CONFIG_NFS_V4_1 */ 367#endif /* CONFIG_NFS_V4_1 */
350 368
351static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) 369static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
@@ -465,7 +483,7 @@ static __be32 encode_op_hdr(struct xdr_stream *xdr, uint32_t op, __be32 res)
465 483
466 p = xdr_reserve_space(xdr, 8); 484 p = xdr_reserve_space(xdr, 8);
467 if (unlikely(p == NULL)) 485 if (unlikely(p == NULL))
468 return htonl(NFS4ERR_RESOURCE); 486 return htonl(NFS4ERR_RESOURCE_HDR);
469 *p++ = htonl(op); 487 *p++ = htonl(op);
470 *p = res; 488 *p = res;
471 return 0; 489 return 0;
@@ -499,10 +517,10 @@ out:
499 517
500#if defined(CONFIG_NFS_V4_1) 518#if defined(CONFIG_NFS_V4_1)
501 519
502static unsigned encode_sessionid(struct xdr_stream *xdr, 520static __be32 encode_sessionid(struct xdr_stream *xdr,
503 const struct nfs4_sessionid *sid) 521 const struct nfs4_sessionid *sid)
504{ 522{
505 uint32_t *p; 523 __be32 *p;
506 int len = NFS4_MAX_SESSIONID_LEN; 524 int len = NFS4_MAX_SESSIONID_LEN;
507 525
508 p = xdr_reserve_space(xdr, len); 526 p = xdr_reserve_space(xdr, len);
@@ -513,11 +531,11 @@ static unsigned encode_sessionid(struct xdr_stream *xdr,
513 return 0; 531 return 0;
514} 532}
515 533
516static unsigned encode_cb_sequence_res(struct svc_rqst *rqstp, 534static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp,
517 struct xdr_stream *xdr, 535 struct xdr_stream *xdr,
518 const struct cb_sequenceres *res) 536 const struct cb_sequenceres *res)
519{ 537{
520 uint32_t *p; 538 __be32 *p;
521 unsigned status = res->csr_status; 539 unsigned status = res->csr_status;
522 540
523 if (unlikely(status != 0)) 541 if (unlikely(status != 0))
@@ -554,6 +572,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
554 case OP_CB_RECALL: 572 case OP_CB_RECALL:
555 case OP_CB_SEQUENCE: 573 case OP_CB_SEQUENCE:
556 case OP_CB_RECALL_ANY: 574 case OP_CB_RECALL_ANY:
575 case OP_CB_RECALL_SLOT:
557 *op = &callback_ops[op_nr]; 576 *op = &callback_ops[op_nr];
558 break; 577 break;
559 578
@@ -562,7 +581,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
562 case OP_CB_NOTIFY: 581 case OP_CB_NOTIFY:
563 case OP_CB_PUSH_DELEG: 582 case OP_CB_PUSH_DELEG:
564 case OP_CB_RECALLABLE_OBJ_AVAIL: 583 case OP_CB_RECALLABLE_OBJ_AVAIL:
565 case OP_CB_RECALL_SLOT:
566 case OP_CB_WANTS_CANCELLED: 584 case OP_CB_WANTS_CANCELLED:
567 case OP_CB_NOTIFY_LOCK: 585 case OP_CB_NOTIFY_LOCK:
568 return htonl(NFS4ERR_NOTSUPP); 586 return htonl(NFS4ERR_NOTSUPP);
@@ -602,20 +620,18 @@ preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op)
602static __be32 process_op(uint32_t minorversion, int nop, 620static __be32 process_op(uint32_t minorversion, int nop,
603 struct svc_rqst *rqstp, 621 struct svc_rqst *rqstp,
604 struct xdr_stream *xdr_in, void *argp, 622 struct xdr_stream *xdr_in, void *argp,
605 struct xdr_stream *xdr_out, void *resp) 623 struct xdr_stream *xdr_out, void *resp, int* drc_status)
606{ 624{
607 struct callback_op *op = &callback_ops[0]; 625 struct callback_op *op = &callback_ops[0];
608 unsigned int op_nr = OP_CB_ILLEGAL; 626 unsigned int op_nr;
609 __be32 status; 627 __be32 status;
610 long maxlen; 628 long maxlen;
611 __be32 res; 629 __be32 res;
612 630
613 dprintk("%s: start\n", __func__); 631 dprintk("%s: start\n", __func__);
614 status = decode_op_hdr(xdr_in, &op_nr); 632 status = decode_op_hdr(xdr_in, &op_nr);
615 if (unlikely(status)) { 633 if (unlikely(status))
616 status = htonl(NFS4ERR_OP_ILLEGAL); 634 return status;
617 goto out;
618 }
619 635
620 dprintk("%s: minorversion=%d nop=%d op_nr=%u\n", 636 dprintk("%s: minorversion=%d nop=%d op_nr=%u\n",
621 __func__, minorversion, nop, op_nr); 637 __func__, minorversion, nop, op_nr);
@@ -624,19 +640,32 @@ static __be32 process_op(uint32_t minorversion, int nop,
624 preprocess_nfs4_op(op_nr, &op); 640 preprocess_nfs4_op(op_nr, &op);
625 if (status == htonl(NFS4ERR_OP_ILLEGAL)) 641 if (status == htonl(NFS4ERR_OP_ILLEGAL))
626 op_nr = OP_CB_ILLEGAL; 642 op_nr = OP_CB_ILLEGAL;
627out: 643 if (status)
644 goto encode_hdr;
645
646 if (*drc_status) {
647 status = *drc_status;
648 goto encode_hdr;
649 }
650
628 maxlen = xdr_out->end - xdr_out->p; 651 maxlen = xdr_out->end - xdr_out->p;
629 if (maxlen > 0 && maxlen < PAGE_SIZE) { 652 if (maxlen > 0 && maxlen < PAGE_SIZE) {
630 if (likely(status == 0 && op->decode_args != NULL)) 653 status = op->decode_args(rqstp, xdr_in, argp);
631 status = op->decode_args(rqstp, xdr_in, argp); 654 if (likely(status == 0))
632 if (likely(status == 0 && op->process_op != NULL))
633 status = op->process_op(argp, resp); 655 status = op->process_op(argp, resp);
634 } else 656 } else
635 status = htonl(NFS4ERR_RESOURCE); 657 status = htonl(NFS4ERR_RESOURCE);
636 658
659 /* Only set by OP_CB_SEQUENCE processing */
660 if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) {
661 *drc_status = status;
662 status = 0;
663 }
664
665encode_hdr:
637 res = encode_op_hdr(xdr_out, op_nr, status); 666 res = encode_op_hdr(xdr_out, op_nr, status);
638 if (status == 0) 667 if (unlikely(res))
639 status = res; 668 return res;
640 if (op->encode_res != NULL && status == 0) 669 if (op->encode_res != NULL && status == 0)
641 status = op->encode_res(rqstp, xdr_out, resp); 670 status = op->encode_res(rqstp, xdr_out, resp);
642 dprintk("%s: done, status = %d\n", __func__, ntohl(status)); 671 dprintk("%s: done, status = %d\n", __func__, ntohl(status));
@@ -652,7 +681,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
652 struct cb_compound_hdr_res hdr_res = { NULL }; 681 struct cb_compound_hdr_res hdr_res = { NULL };
653 struct xdr_stream xdr_in, xdr_out; 682 struct xdr_stream xdr_in, xdr_out;
654 __be32 *p; 683 __be32 *p;
655 __be32 status; 684 __be32 status, drc_status = 0;
656 unsigned int nops = 0; 685 unsigned int nops = 0;
657 686
658 dprintk("%s: start\n", __func__); 687 dprintk("%s: start\n", __func__);
@@ -672,11 +701,18 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
672 return rpc_system_err; 701 return rpc_system_err;
673 702
674 while (status == 0 && nops != hdr_arg.nops) { 703 while (status == 0 && nops != hdr_arg.nops) {
675 status = process_op(hdr_arg.minorversion, nops, 704 status = process_op(hdr_arg.minorversion, nops, rqstp,
676 rqstp, &xdr_in, argp, &xdr_out, resp); 705 &xdr_in, argp, &xdr_out, resp, &drc_status);
677 nops++; 706 nops++;
678 } 707 }
679 708
709 /* Buffer overflow in decode_ops_hdr or encode_ops_hdr. Return
710 * resource error in cb_compound status without returning op */
711 if (unlikely(status == htonl(NFS4ERR_RESOURCE_HDR))) {
712 status = htonl(NFS4ERR_RESOURCE);
713 nops--;
714 }
715
680 *hdr_res.status = status; 716 *hdr_res.status = status;
681 *hdr_res.nops = htonl(nops); 717 *hdr_res.nops = htonl(nops);
682 dprintk("%s: done, status = %u\n", __func__, ntohl(status)); 718 dprintk("%s: done, status = %u\n", __func__, ntohl(status));
@@ -713,6 +749,11 @@ static struct callback_op callback_ops[] = {
713 .decode_args = (callback_decode_arg_t)decode_recallany_args, 749 .decode_args = (callback_decode_arg_t)decode_recallany_args,
714 .res_maxsize = CB_OP_RECALLANY_RES_MAXSZ, 750 .res_maxsize = CB_OP_RECALLANY_RES_MAXSZ,
715 }, 751 },
752 [OP_CB_RECALL_SLOT] = {
753 .process_op = (callback_process_op_t)nfs4_callback_recallslot,
754 .decode_args = (callback_decode_arg_t)decode_recallslot_args,
755 .res_maxsize = CB_OP_RECALLSLOT_RES_MAXSZ,
756 },
716#endif /* CONFIG_NFS_V4_1 */ 757#endif /* CONFIG_NFS_V4_1 */
717}; 758};
718 759
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ee77713ce68b..2274f1737336 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -164,30 +164,7 @@ error_0:
164 return ERR_PTR(err); 164 return ERR_PTR(err);
165} 165}
166 166
167static void nfs4_shutdown_client(struct nfs_client *clp)
168{
169#ifdef CONFIG_NFS_V4
170 if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
171 nfs4_kill_renewd(clp);
172 BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
173 if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
174 nfs_idmap_delete(clp);
175
176 rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
177#endif
178}
179
180/*
181 * Destroy the NFS4 callback service
182 */
183static void nfs4_destroy_callback(struct nfs_client *clp)
184{
185#ifdef CONFIG_NFS_V4 167#ifdef CONFIG_NFS_V4
186 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
187 nfs_callback_down(clp->cl_minorversion);
188#endif /* CONFIG_NFS_V4 */
189}
190
191/* 168/*
192 * Clears/puts all minor version specific parts from an nfs_client struct 169 * Clears/puts all minor version specific parts from an nfs_client struct
193 * reverting it to minorversion 0. 170 * reverting it to minorversion 0.
@@ -202,9 +179,33 @@ static void nfs4_clear_client_minor_version(struct nfs_client *clp)
202 179
203 clp->cl_call_sync = _nfs4_call_sync; 180 clp->cl_call_sync = _nfs4_call_sync;
204#endif /* CONFIG_NFS_V4_1 */ 181#endif /* CONFIG_NFS_V4_1 */
182}
205 183
184/*
185 * Destroy the NFS4 callback service
186 */
187static void nfs4_destroy_callback(struct nfs_client *clp)
188{
189 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
190 nfs_callback_down(clp->cl_minorversion);
191}
192
193static void nfs4_shutdown_client(struct nfs_client *clp)
194{
195 if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
196 nfs4_kill_renewd(clp);
197 nfs4_clear_client_minor_version(clp);
206 nfs4_destroy_callback(clp); 198 nfs4_destroy_callback(clp);
199 if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
200 nfs_idmap_delete(clp);
201
202 rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
207} 203}
204#else
205static void nfs4_shutdown_client(struct nfs_client *clp)
206{
207}
208#endif /* CONFIG_NFS_V4 */
208 209
209/* 210/*
210 * Destroy a shared client record 211 * Destroy a shared client record
@@ -213,7 +214,6 @@ static void nfs_free_client(struct nfs_client *clp)
213{ 214{
214 dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); 215 dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
215 216
216 nfs4_clear_client_minor_version(clp);
217 nfs4_shutdown_client(clp); 217 nfs4_shutdown_client(clp);
218 218
219 nfs_fscache_release_client_cookie(clp); 219 nfs_fscache_release_client_cookie(clp);
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index 95e1ca765d47..3f0cd4dfddaf 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -36,6 +36,19 @@ struct nfs_dns_ent {
36}; 36};
37 37
38 38
39static void nfs_dns_ent_update(struct cache_head *cnew,
40 struct cache_head *ckey)
41{
42 struct nfs_dns_ent *new;
43 struct nfs_dns_ent *key;
44
45 new = container_of(cnew, struct nfs_dns_ent, h);
46 key = container_of(ckey, struct nfs_dns_ent, h);
47
48 memcpy(&new->addr, &key->addr, key->addrlen);
49 new->addrlen = key->addrlen;
50}
51
39static void nfs_dns_ent_init(struct cache_head *cnew, 52static void nfs_dns_ent_init(struct cache_head *cnew,
40 struct cache_head *ckey) 53 struct cache_head *ckey)
41{ 54{
@@ -49,8 +62,7 @@ static void nfs_dns_ent_init(struct cache_head *cnew,
49 new->hostname = kstrndup(key->hostname, key->namelen, GFP_KERNEL); 62 new->hostname = kstrndup(key->hostname, key->namelen, GFP_KERNEL);
50 if (new->hostname) { 63 if (new->hostname) {
51 new->namelen = key->namelen; 64 new->namelen = key->namelen;
52 memcpy(&new->addr, &key->addr, key->addrlen); 65 nfs_dns_ent_update(cnew, ckey);
53 new->addrlen = key->addrlen;
54 } else { 66 } else {
55 new->namelen = 0; 67 new->namelen = 0;
56 new->addrlen = 0; 68 new->addrlen = 0;
@@ -234,7 +246,7 @@ static struct cache_detail nfs_dns_resolve = {
234 .cache_show = nfs_dns_show, 246 .cache_show = nfs_dns_show,
235 .match = nfs_dns_match, 247 .match = nfs_dns_match,
236 .init = nfs_dns_ent_init, 248 .init = nfs_dns_ent_init,
237 .update = nfs_dns_ent_init, 249 .update = nfs_dns_ent_update,
238 .alloc = nfs_dns_ent_alloc, 250 .alloc = nfs_dns_ent_alloc,
239}; 251};
240 252
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 63f2071d6445..ae8d02294e46 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -123,11 +123,11 @@ nfs_file_open(struct inode *inode, struct file *filp)
123 filp->f_path.dentry->d_parent->d_name.name, 123 filp->f_path.dentry->d_parent->d_name.name,
124 filp->f_path.dentry->d_name.name); 124 filp->f_path.dentry->d_name.name);
125 125
126 nfs_inc_stats(inode, NFSIOS_VFSOPEN);
126 res = nfs_check_flags(filp->f_flags); 127 res = nfs_check_flags(filp->f_flags);
127 if (res) 128 if (res)
128 return res; 129 return res;
129 130
130 nfs_inc_stats(inode, NFSIOS_VFSOPEN);
131 res = nfs_open(inode, filp); 131 res = nfs_open(inode, filp);
132 return res; 132 return res;
133} 133}
@@ -237,9 +237,9 @@ nfs_file_flush(struct file *file, fl_owner_t id)
237 dentry->d_parent->d_name.name, 237 dentry->d_parent->d_name.name,
238 dentry->d_name.name); 238 dentry->d_name.name);
239 239
240 nfs_inc_stats(inode, NFSIOS_VFSFLUSH);
240 if ((file->f_mode & FMODE_WRITE) == 0) 241 if ((file->f_mode & FMODE_WRITE) == 0)
241 return 0; 242 return 0;
242 nfs_inc_stats(inode, NFSIOS_VFSFLUSH);
243 243
244 /* Flush writes to the server and return any errors */ 244 /* Flush writes to the server and return any errors */
245 return nfs_do_fsync(ctx, inode); 245 return nfs_do_fsync(ctx, inode);
@@ -262,9 +262,11 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
262 (unsigned long) count, (unsigned long) pos); 262 (unsigned long) count, (unsigned long) pos);
263 263
264 result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); 264 result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
265 nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count); 265 if (!result) {
266 if (!result)
267 result = generic_file_aio_read(iocb, iov, nr_segs, pos); 266 result = generic_file_aio_read(iocb, iov, nr_segs, pos);
267 if (result > 0)
268 nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result);
269 }
268 return result; 270 return result;
269} 271}
270 272
@@ -282,8 +284,11 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
282 (unsigned long) count, (unsigned long long) *ppos); 284 (unsigned long) count, (unsigned long long) *ppos);
283 285
284 res = nfs_revalidate_mapping(inode, filp->f_mapping); 286 res = nfs_revalidate_mapping(inode, filp->f_mapping);
285 if (!res) 287 if (!res) {
286 res = generic_file_splice_read(filp, ppos, pipe, count, flags); 288 res = generic_file_splice_read(filp, ppos, pipe, count, flags);
289 if (res > 0)
290 nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, res);
291 }
287 return res; 292 return res;
288} 293}
289 294
@@ -596,6 +601,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
596{ 601{
597 struct dentry * dentry = iocb->ki_filp->f_path.dentry; 602 struct dentry * dentry = iocb->ki_filp->f_path.dentry;
598 struct inode * inode = dentry->d_inode; 603 struct inode * inode = dentry->d_inode;
604 unsigned long written = 0;
599 ssize_t result; 605 ssize_t result;
600 size_t count = iov_length(iov, nr_segs); 606 size_t count = iov_length(iov, nr_segs);
601 607
@@ -622,14 +628,18 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
622 if (!count) 628 if (!count)
623 goto out; 629 goto out;
624 630
625 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
626 result = generic_file_aio_write(iocb, iov, nr_segs, pos); 631 result = generic_file_aio_write(iocb, iov, nr_segs, pos);
632 if (result > 0)
633 written = result;
634
627 /* Return error values for O_DSYNC and IS_SYNC() */ 635 /* Return error values for O_DSYNC and IS_SYNC() */
628 if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { 636 if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) {
629 int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); 637 int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode);
630 if (err < 0) 638 if (err < 0)
631 result = err; 639 result = err;
632 } 640 }
641 if (result > 0)
642 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
633out: 643out:
634 return result; 644 return result;
635 645
@@ -644,6 +654,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
644{ 654{
645 struct dentry *dentry = filp->f_path.dentry; 655 struct dentry *dentry = filp->f_path.dentry;
646 struct inode *inode = dentry->d_inode; 656 struct inode *inode = dentry->d_inode;
657 unsigned long written = 0;
647 ssize_t ret; 658 ssize_t ret;
648 659
649 dprintk("NFS splice_write(%s/%s, %lu@%llu)\n", 660 dprintk("NFS splice_write(%s/%s, %lu@%llu)\n",
@@ -654,14 +665,17 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
654 * The combination of splice and an O_APPEND destination is disallowed. 665 * The combination of splice and an O_APPEND destination is disallowed.
655 */ 666 */
656 667
657 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
658
659 ret = generic_file_splice_write(pipe, filp, ppos, count, flags); 668 ret = generic_file_splice_write(pipe, filp, ppos, count, flags);
669 if (ret > 0)
670 written = ret;
671
660 if (ret >= 0 && nfs_need_sync_write(filp, inode)) { 672 if (ret >= 0 && nfs_need_sync_write(filp, inode)) {
661 int err = nfs_do_fsync(nfs_file_open_context(filp), inode); 673 int err = nfs_do_fsync(nfs_file_open_context(filp), inode);
662 if (err < 0) 674 if (err < 0)
663 ret = err; 675 ret = err;
664 } 676 }
677 if (ret > 0)
678 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
665 return ret; 679 return ret;
666} 680}
667 681
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index dbaaf7d2a188..657201acda84 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -595,11 +595,6 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
595 __put_nfs_open_context(ctx, 0); 595 __put_nfs_open_context(ctx, 0);
596} 596}
597 597
598static void put_nfs_open_context_sync(struct nfs_open_context *ctx)
599{
600 __put_nfs_open_context(ctx, 1);
601}
602
603/* 598/*
604 * Ensure that mmap has a recent RPC credential for use when writing out 599 * Ensure that mmap has a recent RPC credential for use when writing out
605 * shared pages 600 * shared pages
@@ -646,7 +641,7 @@ static void nfs_file_clear_open_context(struct file *filp)
646 spin_lock(&inode->i_lock); 641 spin_lock(&inode->i_lock);
647 list_move_tail(&ctx->list, &NFS_I(inode)->open_files); 642 list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
648 spin_unlock(&inode->i_lock); 643 spin_unlock(&inode->i_lock);
649 put_nfs_open_context_sync(ctx); 644 __put_nfs_open_context(ctx, filp->f_flags & O_DIRECT ? 0 : 1);
650 } 645 }
651} 646}
652 647
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 3f8881d1a050..24992f0a29f2 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -22,14 +22,14 @@
22 22
23#define NFSDBG_FACILITY NFSDBG_PROC 23#define NFSDBG_FACILITY NFSDBG_PROC
24 24
25/* A wrapper to handle the EJUKEBOX error message */ 25/* A wrapper to handle the EJUKEBOX and EKEYEXPIRED error messages */
26static int 26static int
27nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) 27nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
28{ 28{
29 int res; 29 int res;
30 do { 30 do {
31 res = rpc_call_sync(clnt, msg, flags); 31 res = rpc_call_sync(clnt, msg, flags);
32 if (res != -EJUKEBOX) 32 if (res != -EJUKEBOX && res != -EKEYEXPIRED)
33 break; 33 break;
34 schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); 34 schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
35 res = -ERESTARTSYS; 35 res = -ERESTARTSYS;
@@ -42,9 +42,10 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
42static int 42static int
43nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode) 43nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
44{ 44{
45 if (task->tk_status != -EJUKEBOX) 45 if (task->tk_status != -EJUKEBOX && task->tk_status != -EKEYEXPIRED)
46 return 0; 46 return 0;
47 nfs_inc_stats(inode, NFSIOS_DELAY); 47 if (task->tk_status == -EJUKEBOX)
48 nfs_inc_stats(inode, NFSIOS_DELAY);
48 task->tk_status = 0; 49 task->tk_status = 0;
49 rpc_restart_call(task); 50 rpc_restart_call(task);
50 rpc_delay(task, NFS_JUKEBOX_RETRY_TIME); 51 rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 0c6fda33d66e..a187200a7aac 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -46,6 +46,7 @@ enum nfs4_client_state {
46 NFS4CLNT_DELEGRETURN, 46 NFS4CLNT_DELEGRETURN,
47 NFS4CLNT_SESSION_RESET, 47 NFS4CLNT_SESSION_RESET,
48 NFS4CLNT_SESSION_DRAINING, 48 NFS4CLNT_SESSION_DRAINING,
49 NFS4CLNT_RECALL_SLOT,
49}; 50};
50 51
51/* 52/*
@@ -280,6 +281,7 @@ extern void nfs4_schedule_state_manager(struct nfs_client *);
280extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); 281extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
281extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state); 282extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state);
282extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 283extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
284extern void nfs41_handle_recall_slot(struct nfs_client *clp);
283extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 285extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
284extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); 286extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
285extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); 287extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 84d83be25a98..eda74c42d552 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -281,6 +281,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
281 } 281 }
282 case -NFS4ERR_GRACE: 282 case -NFS4ERR_GRACE:
283 case -NFS4ERR_DELAY: 283 case -NFS4ERR_DELAY:
284 case -EKEYEXPIRED:
284 ret = nfs4_delay(server->client, &exception->timeout); 285 ret = nfs4_delay(server->client, &exception->timeout);
285 if (ret != 0) 286 if (ret != 0)
286 break; 287 break;
@@ -418,7 +419,8 @@ static void nfs41_sequence_done(struct nfs_client *clp,
418 clp->cl_last_renewal = timestamp; 419 clp->cl_last_renewal = timestamp;
419 spin_unlock(&clp->cl_lock); 420 spin_unlock(&clp->cl_lock);
420 /* Check sequence flags */ 421 /* Check sequence flags */
421 nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); 422 if (atomic_read(&clp->cl_count) > 1)
423 nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
422 } 424 }
423out: 425out:
424 /* The session may be reset by one of the error handlers. */ 426 /* The session may be reset by one of the error handlers. */
@@ -1163,7 +1165,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
1163 int err; 1165 int err;
1164 do { 1166 do {
1165 err = _nfs4_do_open_reclaim(ctx, state); 1167 err = _nfs4_do_open_reclaim(ctx, state);
1166 if (err != -NFS4ERR_DELAY) 1168 if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
1167 break; 1169 break;
1168 nfs4_handle_exception(server, err, &exception); 1170 nfs4_handle_exception(server, err, &exception);
1169 } while (exception.retry); 1171 } while (exception.retry);
@@ -1582,6 +1584,7 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state
1582 goto out; 1584 goto out;
1583 case -NFS4ERR_GRACE: 1585 case -NFS4ERR_GRACE:
1584 case -NFS4ERR_DELAY: 1586 case -NFS4ERR_DELAY:
1587 case -EKEYEXPIRED:
1585 nfs4_handle_exception(server, err, &exception); 1588 nfs4_handle_exception(server, err, &exception);
1586 err = 0; 1589 err = 0;
1587 } 1590 }
@@ -3145,10 +3148,19 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa
3145 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special 3148 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
3146 * standalone procedure for queueing an asynchronous RENEW. 3149 * standalone procedure for queueing an asynchronous RENEW.
3147 */ 3150 */
3151static void nfs4_renew_release(void *data)
3152{
3153 struct nfs_client *clp = data;
3154
3155 if (atomic_read(&clp->cl_count) > 1)
3156 nfs4_schedule_state_renewal(clp);
3157 nfs_put_client(clp);
3158}
3159
3148static void nfs4_renew_done(struct rpc_task *task, void *data) 3160static void nfs4_renew_done(struct rpc_task *task, void *data)
3149{ 3161{
3150 struct nfs_client *clp = (struct nfs_client *)task->tk_msg.rpc_argp; 3162 struct nfs_client *clp = data;
3151 unsigned long timestamp = (unsigned long)data; 3163 unsigned long timestamp = task->tk_start;
3152 3164
3153 if (task->tk_status < 0) { 3165 if (task->tk_status < 0) {
3154 /* Unless we're shutting down, schedule state recovery! */ 3166 /* Unless we're shutting down, schedule state recovery! */
@@ -3164,6 +3176,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *data)
3164 3176
3165static const struct rpc_call_ops nfs4_renew_ops = { 3177static const struct rpc_call_ops nfs4_renew_ops = {
3166 .rpc_call_done = nfs4_renew_done, 3178 .rpc_call_done = nfs4_renew_done,
3179 .rpc_release = nfs4_renew_release,
3167}; 3180};
3168 3181
3169int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) 3182int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
@@ -3174,8 +3187,10 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
3174 .rpc_cred = cred, 3187 .rpc_cred = cred,
3175 }; 3188 };
3176 3189
3190 if (!atomic_inc_not_zero(&clp->cl_count))
3191 return -EIO;
3177 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, 3192 return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
3178 &nfs4_renew_ops, (void *)jiffies); 3193 &nfs4_renew_ops, clp);
3179} 3194}
3180 3195
3181int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) 3196int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
@@ -3452,6 +3467,7 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
3452 if (server) 3467 if (server)
3453 nfs_inc_server_stats(server, NFSIOS_DELAY); 3468 nfs_inc_server_stats(server, NFSIOS_DELAY);
3454 case -NFS4ERR_GRACE: 3469 case -NFS4ERR_GRACE:
3470 case -EKEYEXPIRED:
3455 rpc_delay(task, NFS4_POLL_RETRY_MAX); 3471 rpc_delay(task, NFS4_POLL_RETRY_MAX);
3456 task->tk_status = 0; 3472 task->tk_status = 0;
3457 return -EAGAIN; 3473 return -EAGAIN;
@@ -3564,6 +3580,7 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred)
3564 case -NFS4ERR_RESOURCE: 3580 case -NFS4ERR_RESOURCE:
3565 /* The IBM lawyers misread another document! */ 3581 /* The IBM lawyers misread another document! */
3566 case -NFS4ERR_DELAY: 3582 case -NFS4ERR_DELAY:
3583 case -EKEYEXPIRED:
3567 err = nfs4_delay(clp->cl_rpcclient, &timeout); 3584 err = nfs4_delay(clp->cl_rpcclient, &timeout);
3568 } 3585 }
3569 } while (err == 0); 3586 } while (err == 0);
@@ -4179,7 +4196,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
4179 if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) 4196 if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
4180 return 0; 4197 return 0;
4181 err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); 4198 err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
4182 if (err != -NFS4ERR_DELAY) 4199 if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
4183 break; 4200 break;
4184 nfs4_handle_exception(server, err, &exception); 4201 nfs4_handle_exception(server, err, &exception);
4185 } while (exception.retry); 4202 } while (exception.retry);
@@ -4204,6 +4221,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
4204 goto out; 4221 goto out;
4205 case -NFS4ERR_GRACE: 4222 case -NFS4ERR_GRACE:
4206 case -NFS4ERR_DELAY: 4223 case -NFS4ERR_DELAY:
4224 case -EKEYEXPIRED:
4207 nfs4_handle_exception(server, err, &exception); 4225 nfs4_handle_exception(server, err, &exception);
4208 err = 0; 4226 err = 0;
4209 } 4227 }
@@ -4355,6 +4373,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
4355 err = 0; 4373 err = 0;
4356 goto out; 4374 goto out;
4357 case -NFS4ERR_DELAY: 4375 case -NFS4ERR_DELAY:
4376 case -EKEYEXPIRED:
4358 break; 4377 break;
4359 } 4378 }
4360 err = nfs4_handle_exception(server, err, &exception); 4379 err = nfs4_handle_exception(server, err, &exception);
@@ -4500,7 +4519,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
4500 4519
4501 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); 4520 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
4502 4521
4503 if (status != NFS4ERR_CLID_INUSE) 4522 if (status != -NFS4ERR_CLID_INUSE)
4504 break; 4523 break;
4505 4524
4506 if (signalled()) 4525 if (signalled())
@@ -4554,6 +4573,7 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
4554 switch (task->tk_status) { 4573 switch (task->tk_status) {
4555 case -NFS4ERR_DELAY: 4574 case -NFS4ERR_DELAY:
4556 case -NFS4ERR_GRACE: 4575 case -NFS4ERR_GRACE:
4576 case -EKEYEXPIRED:
4557 dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); 4577 dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
4558 rpc_delay(task, NFS4_POLL_RETRY_MIN); 4578 rpc_delay(task, NFS4_POLL_RETRY_MIN);
4559 task->tk_status = 0; 4579 task->tk_status = 0;
@@ -4611,26 +4631,32 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
4611/* 4631/*
4612 * Reset a slot table 4632 * Reset a slot table
4613 */ 4633 */
4614static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots, 4634static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
4615 int old_max_slots, int ivalue) 4635 int ivalue)
4616{ 4636{
4637 struct nfs4_slot *new = NULL;
4617 int i; 4638 int i;
4618 int ret = 0; 4639 int ret = 0;
4619 4640
4620 dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__, max_slots, tbl); 4641 dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
4642 max_reqs, tbl->max_slots);
4621 4643
4622 /* 4644 /* Does the newly negotiated max_reqs match the existing slot table? */
4623 * Until we have dynamic slot table adjustment, insist 4645 if (max_reqs != tbl->max_slots) {
4624 * upon the same slot table size 4646 ret = -ENOMEM;
4625 */ 4647 new = kmalloc(max_reqs * sizeof(struct nfs4_slot),
4626 if (max_slots != old_max_slots) { 4648 GFP_KERNEL);
4627 dprintk("%s reset slot table does't match old\n", 4649 if (!new)
4628 __func__); 4650 goto out;
4629 ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */ 4651 ret = 0;
4630 goto out; 4652 kfree(tbl->slots);
4631 } 4653 }
4632 spin_lock(&tbl->slot_tbl_lock); 4654 spin_lock(&tbl->slot_tbl_lock);
4633 for (i = 0; i < max_slots; ++i) 4655 if (new) {
4656 tbl->slots = new;
4657 tbl->max_slots = max_reqs;
4658 }
4659 for (i = 0; i < tbl->max_slots; ++i)
4634 tbl->slots[i].seq_nr = ivalue; 4660 tbl->slots[i].seq_nr = ivalue;
4635 spin_unlock(&tbl->slot_tbl_lock); 4661 spin_unlock(&tbl->slot_tbl_lock);
4636 dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, 4662 dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
@@ -4648,16 +4674,12 @@ static int nfs4_reset_slot_tables(struct nfs4_session *session)
4648 int status; 4674 int status;
4649 4675
4650 status = nfs4_reset_slot_table(&session->fc_slot_table, 4676 status = nfs4_reset_slot_table(&session->fc_slot_table,
4651 session->fc_attrs.max_reqs, 4677 session->fc_attrs.max_reqs, 1);
4652 session->fc_slot_table.max_slots,
4653 1);
4654 if (status) 4678 if (status)
4655 return status; 4679 return status;
4656 4680
4657 status = nfs4_reset_slot_table(&session->bc_slot_table, 4681 status = nfs4_reset_slot_table(&session->bc_slot_table,
4658 session->bc_attrs.max_reqs, 4682 session->bc_attrs.max_reqs, 0);
4659 session->bc_slot_table.max_slots,
4660 0);
4661 return status; 4683 return status;
4662} 4684}
4663 4685
@@ -4798,16 +4820,14 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
4798 args->fc_attrs.headerpadsz = 0; 4820 args->fc_attrs.headerpadsz = 0;
4799 args->fc_attrs.max_rqst_sz = mxrqst_sz; 4821 args->fc_attrs.max_rqst_sz = mxrqst_sz;
4800 args->fc_attrs.max_resp_sz = mxresp_sz; 4822 args->fc_attrs.max_resp_sz = mxresp_sz;
4801 args->fc_attrs.max_resp_sz_cached = mxresp_sz;
4802 args->fc_attrs.max_ops = NFS4_MAX_OPS; 4823 args->fc_attrs.max_ops = NFS4_MAX_OPS;
4803 args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs; 4824 args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs;
4804 4825
4805 dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u " 4826 dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
4806 "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n", 4827 "max_ops=%u max_reqs=%u\n",
4807 __func__, 4828 __func__,
4808 args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz, 4829 args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
4809 args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops, 4830 args->fc_attrs.max_ops, args->fc_attrs.max_reqs);
4810 args->fc_attrs.max_reqs);
4811 4831
4812 /* Back channel attributes */ 4832 /* Back channel attributes */
4813 args->bc_attrs.headerpadsz = 0; 4833 args->bc_attrs.headerpadsz = 0;
@@ -5016,7 +5036,16 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
5016 &res, args.sa_cache_this, 1); 5036 &res, args.sa_cache_this, 1);
5017} 5037}
5018 5038
5019void nfs41_sequence_call_done(struct rpc_task *task, void *data) 5039static void nfs41_sequence_release(void *data)
5040{
5041 struct nfs_client *clp = (struct nfs_client *)data;
5042
5043 if (atomic_read(&clp->cl_count) > 1)
5044 nfs4_schedule_state_renewal(clp);
5045 nfs_put_client(clp);
5046}
5047
5048static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
5020{ 5049{
5021 struct nfs_client *clp = (struct nfs_client *)data; 5050 struct nfs_client *clp = (struct nfs_client *)data;
5022 5051
@@ -5024,6 +5053,8 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
5024 5053
5025 if (task->tk_status < 0) { 5054 if (task->tk_status < 0) {
5026 dprintk("%s ERROR %d\n", __func__, task->tk_status); 5055 dprintk("%s ERROR %d\n", __func__, task->tk_status);
5056 if (atomic_read(&clp->cl_count) == 1)
5057 goto out;
5027 5058
5028 if (_nfs4_async_handle_error(task, NULL, clp, NULL) 5059 if (_nfs4_async_handle_error(task, NULL, clp, NULL)
5029 == -EAGAIN) { 5060 == -EAGAIN) {
@@ -5032,7 +5063,7 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
5032 } 5063 }
5033 } 5064 }
5034 dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); 5065 dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
5035 5066out:
5036 kfree(task->tk_msg.rpc_argp); 5067 kfree(task->tk_msg.rpc_argp);
5037 kfree(task->tk_msg.rpc_resp); 5068 kfree(task->tk_msg.rpc_resp);
5038 5069
@@ -5057,6 +5088,7 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
5057static const struct rpc_call_ops nfs41_sequence_ops = { 5088static const struct rpc_call_ops nfs41_sequence_ops = {
5058 .rpc_call_done = nfs41_sequence_call_done, 5089 .rpc_call_done = nfs41_sequence_call_done,
5059 .rpc_call_prepare = nfs41_sequence_prepare, 5090 .rpc_call_prepare = nfs41_sequence_prepare,
5091 .rpc_release = nfs41_sequence_release,
5060}; 5092};
5061 5093
5062static int nfs41_proc_async_sequence(struct nfs_client *clp, 5094static int nfs41_proc_async_sequence(struct nfs_client *clp,
@@ -5069,12 +5101,13 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp,
5069 .rpc_cred = cred, 5101 .rpc_cred = cred,
5070 }; 5102 };
5071 5103
5104 if (!atomic_inc_not_zero(&clp->cl_count))
5105 return -EIO;
5072 args = kzalloc(sizeof(*args), GFP_KERNEL); 5106 args = kzalloc(sizeof(*args), GFP_KERNEL);
5073 if (!args)
5074 return -ENOMEM;
5075 res = kzalloc(sizeof(*res), GFP_KERNEL); 5107 res = kzalloc(sizeof(*res), GFP_KERNEL);
5076 if (!res) { 5108 if (!args || !res) {
5077 kfree(args); 5109 kfree(args);
5110 nfs_put_client(clp);
5078 return -ENOMEM; 5111 return -ENOMEM;
5079 } 5112 }
5080 res->sr_slotid = NFS4_MAX_SLOT_TABLE; 5113 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 0156c01c212c..d87f10327b72 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -36,11 +36,6 @@
36 * as an rpc_task, not a real kernel thread, so it always runs in rpciod's 36 * as an rpc_task, not a real kernel thread, so it always runs in rpciod's
37 * context. There is one renewd per nfs_server. 37 * context. There is one renewd per nfs_server.
38 * 38 *
39 * TODO: If the send queue gets backlogged (e.g., if the server goes down),
40 * we will keep filling the queue with periodic RENEW requests. We need a
41 * mechanism for ensuring that if renewd successfully sends off a request,
42 * then it only wakes up when the request is finished. Maybe use the
43 * child task framework of the RPC layer?
44 */ 39 */
45 40
46#include <linux/mm.h> 41#include <linux/mm.h>
@@ -63,7 +58,7 @@ nfs4_renew_state(struct work_struct *work)
63 struct nfs_client *clp = 58 struct nfs_client *clp =
64 container_of(work, struct nfs_client, cl_renewd.work); 59 container_of(work, struct nfs_client, cl_renewd.work);
65 struct rpc_cred *cred; 60 struct rpc_cred *cred;
66 long lease, timeout; 61 long lease;
67 unsigned long last, now; 62 unsigned long last, now;
68 63
69 ops = nfs4_state_renewal_ops[clp->cl_minorversion]; 64 ops = nfs4_state_renewal_ops[clp->cl_minorversion];
@@ -75,7 +70,6 @@ nfs4_renew_state(struct work_struct *work)
75 lease = clp->cl_lease_time; 70 lease = clp->cl_lease_time;
76 last = clp->cl_last_renewal; 71 last = clp->cl_last_renewal;
77 now = jiffies; 72 now = jiffies;
78 timeout = (2 * lease) / 3 + (long)last - (long)now;
79 /* Are we close to a lease timeout? */ 73 /* Are we close to a lease timeout? */
80 if (time_after(now, last + lease/3)) { 74 if (time_after(now, last + lease/3)) {
81 cred = ops->get_state_renewal_cred_locked(clp); 75 cred = ops->get_state_renewal_cred_locked(clp);
@@ -90,19 +84,15 @@ nfs4_renew_state(struct work_struct *work)
90 /* Queue an asynchronous RENEW. */ 84 /* Queue an asynchronous RENEW. */
91 ops->sched_state_renewal(clp, cred); 85 ops->sched_state_renewal(clp, cred);
92 put_rpccred(cred); 86 put_rpccred(cred);
87 goto out_exp;
93 } 88 }
94 timeout = (2 * lease) / 3; 89 } else {
95 spin_lock(&clp->cl_lock);
96 } else
97 dprintk("%s: failed to call renewd. Reason: lease not expired \n", 90 dprintk("%s: failed to call renewd. Reason: lease not expired \n",
98 __func__); 91 __func__);
99 if (timeout < 5 * HZ) /* safeguard */ 92 spin_unlock(&clp->cl_lock);
100 timeout = 5 * HZ; 93 }
101 dprintk("%s: requeueing work. Lease period = %ld\n", 94 nfs4_schedule_state_renewal(clp);
102 __func__, (timeout + HZ - 1) / HZ); 95out_exp:
103 cancel_delayed_work(&clp->cl_renewd);
104 schedule_delayed_work(&clp->cl_renewd, timeout);
105 spin_unlock(&clp->cl_lock);
106 nfs_expire_unreferenced_delegations(clp); 96 nfs_expire_unreferenced_delegations(clp);
107out: 97out:
108 dprintk("%s: done\n", __func__); 98 dprintk("%s: done\n", __func__);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c1e2733f4fa4..6c5ed51f105e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1249,26 +1249,65 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
1249} 1249}
1250 1250
1251#ifdef CONFIG_NFS_V4_1 1251#ifdef CONFIG_NFS_V4_1
1252void nfs41_handle_recall_slot(struct nfs_client *clp)
1253{
1254 set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
1255 nfs4_schedule_state_recovery(clp);
1256}
1257
1258static void nfs4_reset_all_state(struct nfs_client *clp)
1259{
1260 if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
1261 clp->cl_boot_time = CURRENT_TIME;
1262 nfs4_state_start_reclaim_nograce(clp);
1263 nfs4_schedule_state_recovery(clp);
1264 }
1265}
1266
1267static void nfs41_handle_server_reboot(struct nfs_client *clp)
1268{
1269 if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
1270 nfs4_state_start_reclaim_reboot(clp);
1271 nfs4_schedule_state_recovery(clp);
1272 }
1273}
1274
1275static void nfs41_handle_state_revoked(struct nfs_client *clp)
1276{
1277 /* Temporary */
1278 nfs4_reset_all_state(clp);
1279}
1280
1281static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp)
1282{
1283 /* This will need to handle layouts too */
1284 nfs_expire_all_delegations(clp);
1285}
1286
1287static void nfs41_handle_cb_path_down(struct nfs_client *clp)
1288{
1289 nfs_expire_all_delegations(clp);
1290 if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0)
1291 nfs4_schedule_state_recovery(clp);
1292}
1293
1252void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) 1294void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
1253{ 1295{
1254 if (!flags) 1296 if (!flags)
1255 return; 1297 return;
1256 else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) { 1298 else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
1257 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1299 nfs41_handle_server_reboot(clp);
1258 nfs4_state_start_reclaim_reboot(clp); 1300 else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
1259 nfs4_schedule_state_recovery(clp);
1260 } else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
1261 SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | 1301 SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
1262 SEQ4_STATUS_ADMIN_STATE_REVOKED | 1302 SEQ4_STATUS_ADMIN_STATE_REVOKED |
1263 SEQ4_STATUS_RECALLABLE_STATE_REVOKED | 1303 SEQ4_STATUS_LEASE_MOVED))
1264 SEQ4_STATUS_LEASE_MOVED)) { 1304 nfs41_handle_state_revoked(clp);
1265 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1305 else if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
1266 nfs4_state_start_reclaim_nograce(clp); 1306 nfs41_handle_recallable_state_revoked(clp);
1267 nfs4_schedule_state_recovery(clp); 1307 else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
1268 } else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
1269 SEQ4_STATUS_BACKCHANNEL_FAULT | 1308 SEQ4_STATUS_BACKCHANNEL_FAULT |
1270 SEQ4_STATUS_CB_PATH_DOWN_SESSION)) 1309 SEQ4_STATUS_CB_PATH_DOWN_SESSION))
1271 nfs_expire_all_delegations(clp); 1310 nfs41_handle_cb_path_down(clp);
1272} 1311}
1273 1312
1274static int nfs4_reset_session(struct nfs_client *clp) 1313static int nfs4_reset_session(struct nfs_client *clp)
@@ -1285,23 +1324,52 @@ static int nfs4_reset_session(struct nfs_client *clp)
1285 1324
1286 memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN); 1325 memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN);
1287 status = nfs4_proc_create_session(clp); 1326 status = nfs4_proc_create_session(clp);
1288 if (status) 1327 if (status) {
1289 status = nfs4_recovery_handle_error(clp, status); 1328 status = nfs4_recovery_handle_error(clp, status);
1329 goto out;
1330 }
1331 /* create_session negotiated new slot table */
1332 clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
1290 1333
1291out: 1334 /* Let the state manager reestablish state */
1292 /* 1335 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1293 * Let the state manager reestablish state
1294 */
1295 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
1296 status == 0)
1297 nfs41_setup_state_renewal(clp); 1336 nfs41_setup_state_renewal(clp);
1298 1337out:
1299 return status; 1338 return status;
1300} 1339}
1301 1340
1341static int nfs4_recall_slot(struct nfs_client *clp)
1342{
1343 struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table;
1344 struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs;
1345 struct nfs4_slot *new, *old;
1346 int i;
1347
1348 nfs4_begin_drain_session(clp);
1349 new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot),
1350 GFP_KERNEL);
1351 if (!new)
1352 return -ENOMEM;
1353
1354 spin_lock(&fc_tbl->slot_tbl_lock);
1355 for (i = 0; i < fc_tbl->target_max_slots; i++)
1356 new[i].seq_nr = fc_tbl->slots[i].seq_nr;
1357 old = fc_tbl->slots;
1358 fc_tbl->slots = new;
1359 fc_tbl->max_slots = fc_tbl->target_max_slots;
1360 fc_tbl->target_max_slots = 0;
1361 fc_attrs->max_reqs = fc_tbl->max_slots;
1362 spin_unlock(&fc_tbl->slot_tbl_lock);
1363
1364 kfree(old);
1365 nfs4_end_drain_session(clp);
1366 return 0;
1367}
1368
1302#else /* CONFIG_NFS_V4_1 */ 1369#else /* CONFIG_NFS_V4_1 */
1303static int nfs4_reset_session(struct nfs_client *clp) { return 0; } 1370static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
1304static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } 1371static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
1372static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
1305#endif /* CONFIG_NFS_V4_1 */ 1373#endif /* CONFIG_NFS_V4_1 */
1306 1374
1307/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors 1375/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors
@@ -1314,6 +1382,7 @@ static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
1314 case -NFS4ERR_DELAY: 1382 case -NFS4ERR_DELAY:
1315 case -NFS4ERR_CLID_INUSE: 1383 case -NFS4ERR_CLID_INUSE:
1316 case -EAGAIN: 1384 case -EAGAIN:
1385 case -EKEYEXPIRED:
1317 break; 1386 break;
1318 1387
1319 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery 1388 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
@@ -1397,6 +1466,15 @@ static void nfs4_state_manager(struct nfs_client *clp)
1397 nfs_client_return_marked_delegations(clp); 1466 nfs_client_return_marked_delegations(clp);
1398 continue; 1467 continue;
1399 } 1468 }
1469 /* Recall session slots */
1470 if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)
1471 && nfs4_has_session(clp)) {
1472 status = nfs4_recall_slot(clp);
1473 if (status < 0)
1474 goto out_error;
1475 continue;
1476 }
1477
1400 1478
1401 nfs4_clear_state_manager_bit(clp); 1479 nfs4_clear_state_manager_bit(clp);
1402 /* Did we race with an attempt to give us more work? */ 1480 /* Did we race with an attempt to give us more work? */
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 5cd5184b56db..4d338be492cb 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1578,6 +1578,14 @@ static void encode_create_session(struct xdr_stream *xdr,
1578 char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; 1578 char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
1579 uint32_t len; 1579 uint32_t len;
1580 struct nfs_client *clp = args->client; 1580 struct nfs_client *clp = args->client;
1581 u32 max_resp_sz_cached;
1582
1583 /*
1584 * Assumes OPEN is the biggest non-idempotent compound.
1585 * 2 is the verifier.
1586 */
1587 max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE +
1588 RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT;
1581 1589
1582 len = scnprintf(machine_name, sizeof(machine_name), "%s", 1590 len = scnprintf(machine_name, sizeof(machine_name), "%s",
1583 clp->cl_ipaddr); 1591 clp->cl_ipaddr);
@@ -1592,7 +1600,7 @@ static void encode_create_session(struct xdr_stream *xdr,
1592 *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ 1600 *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
1593 *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ 1601 *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */
1594 *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ 1602 *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */
1595 *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz_cached); /* Max resp sz cached */ 1603 *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */
1596 *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */ 1604 *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */
1597 *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */ 1605 *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */
1598 *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ 1606 *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index ef583854d8d0..c752d944fe9e 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -47,6 +47,39 @@
47#define NFSDBG_FACILITY NFSDBG_PROC 47#define NFSDBG_FACILITY NFSDBG_PROC
48 48
49/* 49/*
50 * wrapper to handle the -EKEYEXPIRED error message. This should generally
51 * only happen if using krb5 auth and a user's TGT expires. NFSv2 doesn't
52 * support the NFSERR_JUKEBOX error code, but we handle this situation in the
53 * same way that we handle that error with NFSv3.
54 */
55static int
56nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
57{
58 int res;
59 do {
60 res = rpc_call_sync(clnt, msg, flags);
61 if (res != -EKEYEXPIRED)
62 break;
63 schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
64 res = -ERESTARTSYS;
65 } while (!fatal_signal_pending(current));
66 return res;
67}
68
69#define rpc_call_sync(clnt, msg, flags) nfs_rpc_wrapper(clnt, msg, flags)
70
71static int
72nfs_async_handle_expired_key(struct rpc_task *task)
73{
74 if (task->tk_status != -EKEYEXPIRED)
75 return 0;
76 task->tk_status = 0;
77 rpc_restart_call(task);
78 rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
79 return 1;
80}
81
82/*
50 * Bare-bones access to getattr: this is for nfs_read_super. 83 * Bare-bones access to getattr: this is for nfs_read_super.
51 */ 84 */
52static int 85static int
@@ -307,6 +340,8 @@ nfs_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
307 340
308static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) 341static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
309{ 342{
343 if (nfs_async_handle_expired_key(task))
344 return 0;
310 nfs_mark_for_revalidate(dir); 345 nfs_mark_for_revalidate(dir);
311 return 1; 346 return 1;
312} 347}
@@ -560,6 +595,9 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
560 595
561static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) 596static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
562{ 597{
598 if (nfs_async_handle_expired_key(task))
599 return -EAGAIN;
600
563 nfs_invalidate_atime(data->inode); 601 nfs_invalidate_atime(data->inode);
564 if (task->tk_status >= 0) { 602 if (task->tk_status >= 0) {
565 nfs_refresh_inode(data->inode, data->res.fattr); 603 nfs_refresh_inode(data->inode, data->res.fattr);
@@ -579,6 +617,9 @@ static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message *
579 617
580static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) 618static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
581{ 619{
620 if (nfs_async_handle_expired_key(task))
621 return -EAGAIN;
622
582 if (task->tk_status >= 0) 623 if (task->tk_status >= 0)
583 nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); 624 nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr);
584 return 0; 625 return 0;