diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 1348 |
1 files changed, 1289 insertions, 59 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4674f8092da8..92ce43517814 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 | */ | ||
310 | static void | ||
311 | nfs4_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 | |||
333 | void 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 | |||
354 | static 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 | } | ||
388 | out: | ||
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 | */ | ||
404 | static u8 | ||
405 | nfs4_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; | ||
421 | out: | ||
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 | |||
427 | static 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 | |||
443 | static 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 | |||
508 | int 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 | } | ||
528 | out: | ||
529 | dprintk("<-- %s status=%d\n", __func__, ret); | ||
530 | return ret; | ||
531 | } | ||
532 | |||
533 | struct 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 | |||
540 | static 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 | |||
552 | static 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 | |||
560 | struct 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 | |||
565 | static 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 | |||
598 | int _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 | |||
610 | int _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 | |||
624 | static 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 */ | ||
634 | static 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 | |||
274 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | 642 | static 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); |
@@ -312,6 +680,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) | |||
312 | p->o_res.server = p->o_arg.server; | 680 | p->o_res.server = p->o_arg.server; |
313 | nfs_fattr_init(&p->f_attr); | 681 | nfs_fattr_init(&p->f_attr); |
314 | nfs_fattr_init(&p->dir_attr); | 682 | nfs_fattr_init(&p->dir_attr); |
683 | p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
315 | } | 684 | } |
316 | 685 | ||
317 | static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, | 686 | static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, |
@@ -804,16 +1173,30 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
804 | err = _nfs4_open_delegation_recall(ctx, state, stateid); | 1173 | err = _nfs4_open_delegation_recall(ctx, state, stateid); |
805 | switch (err) { | 1174 | switch (err) { |
806 | case 0: | 1175 | case 0: |
807 | return err; | 1176 | case -ENOENT: |
1177 | case -ESTALE: | ||
1178 | goto out; | ||
808 | case -NFS4ERR_STALE_CLIENTID: | 1179 | case -NFS4ERR_STALE_CLIENTID: |
809 | case -NFS4ERR_STALE_STATEID: | 1180 | case -NFS4ERR_STALE_STATEID: |
810 | case -NFS4ERR_EXPIRED: | 1181 | case -NFS4ERR_EXPIRED: |
811 | /* Don't recall a delegation if it was lost */ | 1182 | /* Don't recall a delegation if it was lost */ |
812 | nfs4_schedule_state_recovery(server->nfs_client); | 1183 | nfs4_schedule_state_recovery(server->nfs_client); |
813 | return err; | 1184 | goto out; |
1185 | case -ERESTARTSYS: | ||
1186 | /* | ||
1187 | * The show must go on: exit, but mark the | ||
1188 | * stateid as needing recovery. | ||
1189 | */ | ||
1190 | case -NFS4ERR_ADMIN_REVOKED: | ||
1191 | case -NFS4ERR_BAD_STATEID: | ||
1192 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); | ||
1193 | case -ENOMEM: | ||
1194 | err = 0; | ||
1195 | goto out; | ||
814 | } | 1196 | } |
815 | err = nfs4_handle_exception(server, err, &exception); | 1197 | err = nfs4_handle_exception(server, err, &exception); |
816 | } while (exception.retry); | 1198 | } while (exception.retry); |
1199 | out: | ||
817 | return err; | 1200 | return err; |
818 | } | 1201 | } |
819 | 1202 | ||
@@ -929,6 +1312,10 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
929 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | 1312 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); |
930 | } | 1313 | } |
931 | data->timestamp = jiffies; | 1314 | data->timestamp = jiffies; |
1315 | if (nfs4_setup_sequence(data->o_arg.server->nfs_client, | ||
1316 | &data->o_arg.seq_args, | ||
1317 | &data->o_res.seq_res, 1, task)) | ||
1318 | return; | ||
932 | rpc_call_start(task); | 1319 | rpc_call_start(task); |
933 | return; | 1320 | return; |
934 | out_no_action: | 1321 | out_no_action: |
@@ -941,6 +1328,10 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata) | |||
941 | struct nfs4_opendata *data = calldata; | 1328 | struct nfs4_opendata *data = calldata; |
942 | 1329 | ||
943 | data->rpc_status = task->tk_status; | 1330 | data->rpc_status = task->tk_status; |
1331 | |||
1332 | nfs4_sequence_done_free_slot(data->o_arg.server, &data->o_res.seq_res, | ||
1333 | task->tk_status); | ||
1334 | |||
944 | if (RPC_ASSASSINATED(task)) | 1335 | if (RPC_ASSASSINATED(task)) |
945 | return; | 1336 | return; |
946 | if (task->tk_status == 0) { | 1337 | if (task->tk_status == 0) { |
@@ -1269,7 +1660,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
1269 | } else | 1660 | } else |
1270 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); | 1661 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); |
1271 | 1662 | ||
1272 | status = rpc_call_sync(server->client, &msg, 0); | 1663 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); |
1273 | if (status == 0 && state != NULL) | 1664 | if (status == 0 && state != NULL) |
1274 | renew_lease(server, timestamp); | 1665 | renew_lease(server, timestamp); |
1275 | return status; | 1666 | return status; |
@@ -1318,6 +1709,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
1318 | struct nfs4_state *state = calldata->state; | 1709 | struct nfs4_state *state = calldata->state; |
1319 | struct nfs_server *server = NFS_SERVER(calldata->inode); | 1710 | struct nfs_server *server = NFS_SERVER(calldata->inode); |
1320 | 1711 | ||
1712 | nfs4_sequence_done(server, &calldata->res.seq_res, task->tk_status); | ||
1321 | if (RPC_ASSASSINATED(task)) | 1713 | if (RPC_ASSASSINATED(task)) |
1322 | return; | 1714 | return; |
1323 | /* hmm. we are done with the inode, and in the process of freeing | 1715 | /* hmm. we are done with the inode, and in the process of freeing |
@@ -1336,10 +1728,11 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
1336 | break; | 1728 | break; |
1337 | default: | 1729 | default: |
1338 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { | 1730 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { |
1339 | rpc_restart_call(task); | 1731 | nfs4_restart_rpc(task, server->nfs_client); |
1340 | return; | 1732 | return; |
1341 | } | 1733 | } |
1342 | } | 1734 | } |
1735 | nfs4_sequence_free_slot(server->nfs_client, &calldata->res.seq_res); | ||
1343 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); | 1736 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); |
1344 | } | 1737 | } |
1345 | 1738 | ||
@@ -1380,6 +1773,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
1380 | calldata->arg.fmode = FMODE_WRITE; | 1773 | calldata->arg.fmode = FMODE_WRITE; |
1381 | } | 1774 | } |
1382 | calldata->timestamp = jiffies; | 1775 | calldata->timestamp = jiffies; |
1776 | if (nfs4_setup_sequence((NFS_SERVER(calldata->inode))->nfs_client, | ||
1777 | &calldata->arg.seq_args, &calldata->res.seq_res, | ||
1778 | 1, task)) | ||
1779 | return; | ||
1383 | rpc_call_start(task); | 1780 | rpc_call_start(task); |
1384 | } | 1781 | } |
1385 | 1782 | ||
@@ -1419,13 +1816,15 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1419 | }; | 1816 | }; |
1420 | int status = -ENOMEM; | 1817 | int status = -ENOMEM; |
1421 | 1818 | ||
1422 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); | 1819 | calldata = kzalloc(sizeof(*calldata), GFP_KERNEL); |
1423 | if (calldata == NULL) | 1820 | if (calldata == NULL) |
1424 | goto out; | 1821 | goto out; |
1425 | calldata->inode = state->inode; | 1822 | calldata->inode = state->inode; |
1426 | calldata->state = state; | 1823 | calldata->state = state; |
1427 | calldata->arg.fh = NFS_FH(state->inode); | 1824 | calldata->arg.fh = NFS_FH(state->inode); |
1428 | calldata->arg.stateid = &state->open_stateid; | 1825 | calldata->arg.stateid = &state->open_stateid; |
1826 | if (nfs4_has_session(server->nfs_client)) | ||
1827 | memset(calldata->arg.stateid->data, 0, 4); /* clear seqid */ | ||
1429 | /* Serialization for the sequence id */ | 1828 | /* Serialization for the sequence id */ |
1430 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); | 1829 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); |
1431 | if (calldata->arg.seqid == NULL) | 1830 | if (calldata->arg.seqid == NULL) |
@@ -1435,6 +1834,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1435 | calldata->res.fattr = &calldata->fattr; | 1834 | calldata->res.fattr = &calldata->fattr; |
1436 | calldata->res.seqid = calldata->arg.seqid; | 1835 | calldata->res.seqid = calldata->arg.seqid; |
1437 | calldata->res.server = server; | 1836 | calldata->res.server = server; |
1837 | calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
1438 | calldata->path.mnt = mntget(path->mnt); | 1838 | calldata->path.mnt = mntget(path->mnt); |
1439 | calldata->path.dentry = dget(path->dentry); | 1839 | calldata->path.dentry = dget(path->dentry); |
1440 | 1840 | ||
@@ -1584,15 +1984,18 @@ void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) | |||
1584 | 1984 | ||
1585 | static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) | 1985 | static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) |
1586 | { | 1986 | { |
1987 | struct nfs4_server_caps_arg args = { | ||
1988 | .fhandle = fhandle, | ||
1989 | }; | ||
1587 | struct nfs4_server_caps_res res = {}; | 1990 | struct nfs4_server_caps_res res = {}; |
1588 | struct rpc_message msg = { | 1991 | struct rpc_message msg = { |
1589 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS], | 1992 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS], |
1590 | .rpc_argp = fhandle, | 1993 | .rpc_argp = &args, |
1591 | .rpc_resp = &res, | 1994 | .rpc_resp = &res, |
1592 | }; | 1995 | }; |
1593 | int status; | 1996 | int status; |
1594 | 1997 | ||
1595 | status = rpc_call_sync(server->client, &msg, 0); | 1998 | status = nfs4_call_sync(server, &msg, &args, &res, 0); |
1596 | if (status == 0) { | 1999 | if (status == 0) { |
1597 | memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); | 2000 | memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); |
1598 | if (res.attr_bitmask[0] & FATTR4_WORD0_ACL) | 2001 | if (res.attr_bitmask[0] & FATTR4_WORD0_ACL) |
@@ -1606,6 +2009,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; | 2009 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; |
1607 | server->acl_bitmask = res.acl_bitmask; | 2010 | server->acl_bitmask = res.acl_bitmask; |
1608 | } | 2011 | } |
2012 | |||
1609 | return status; | 2013 | return status; |
1610 | } | 2014 | } |
1611 | 2015 | ||
@@ -1637,8 +2041,15 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
1637 | .rpc_argp = &args, | 2041 | .rpc_argp = &args, |
1638 | .rpc_resp = &res, | 2042 | .rpc_resp = &res, |
1639 | }; | 2043 | }; |
2044 | int status; | ||
2045 | |||
1640 | nfs_fattr_init(info->fattr); | 2046 | nfs_fattr_init(info->fattr); |
1641 | return rpc_call_sync(server->client, &msg, 0); | 2047 | status = nfs4_recover_expired_lease(server); |
2048 | if (!status) | ||
2049 | status = nfs4_check_client_ready(server->nfs_client); | ||
2050 | if (!status) | ||
2051 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | ||
2052 | return status; | ||
1642 | } | 2053 | } |
1643 | 2054 | ||
1644 | static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2055 | static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
@@ -1728,7 +2139,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
1728 | }; | 2139 | }; |
1729 | 2140 | ||
1730 | nfs_fattr_init(fattr); | 2141 | nfs_fattr_init(fattr); |
1731 | return rpc_call_sync(server->client, &msg, 0); | 2142 | return nfs4_call_sync(server, &msg, &args, &res, 0); |
1732 | } | 2143 | } |
1733 | 2144 | ||
1734 | static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2145 | static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
@@ -1812,7 +2223,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d | |||
1812 | nfs_fattr_init(fattr); | 2223 | nfs_fattr_init(fattr); |
1813 | 2224 | ||
1814 | dprintk("NFS call lookupfh %s\n", name->name); | 2225 | dprintk("NFS call lookupfh %s\n", name->name); |
1815 | status = rpc_call_sync(server->client, &msg, 0); | 2226 | status = nfs4_call_sync(server, &msg, &args, &res, 0); |
1816 | dprintk("NFS reply lookupfh: %d\n", status); | 2227 | dprintk("NFS reply lookupfh: %d\n", status); |
1817 | return status; | 2228 | return status; |
1818 | } | 2229 | } |
@@ -1898,7 +2309,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
1898 | args.access |= NFS4_ACCESS_EXECUTE; | 2309 | args.access |= NFS4_ACCESS_EXECUTE; |
1899 | } | 2310 | } |
1900 | nfs_fattr_init(&fattr); | 2311 | nfs_fattr_init(&fattr); |
1901 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 2312 | status = nfs4_call_sync(server, &msg, &args, &res, 0); |
1902 | if (!status) { | 2313 | if (!status) { |
1903 | entry->mask = 0; | 2314 | entry->mask = 0; |
1904 | if (res.access & NFS4_ACCESS_READ) | 2315 | if (res.access & NFS4_ACCESS_READ) |
@@ -1957,13 +2368,14 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page, | |||
1957 | .pglen = pglen, | 2368 | .pglen = pglen, |
1958 | .pages = &page, | 2369 | .pages = &page, |
1959 | }; | 2370 | }; |
2371 | struct nfs4_readlink_res res; | ||
1960 | struct rpc_message msg = { | 2372 | struct rpc_message msg = { |
1961 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK], | 2373 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK], |
1962 | .rpc_argp = &args, | 2374 | .rpc_argp = &args, |
1963 | .rpc_resp = NULL, | 2375 | .rpc_resp = &res, |
1964 | }; | 2376 | }; |
1965 | 2377 | ||
1966 | return rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 2378 | return nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); |
1967 | } | 2379 | } |
1968 | 2380 | ||
1969 | static int nfs4_proc_readlink(struct inode *inode, struct page *page, | 2381 | static int nfs4_proc_readlink(struct inode *inode, struct page *page, |
@@ -2057,7 +2469,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
2057 | int status; | 2469 | int status; |
2058 | 2470 | ||
2059 | nfs_fattr_init(&res.dir_attr); | 2471 | nfs_fattr_init(&res.dir_attr); |
2060 | status = rpc_call_sync(server->client, &msg, 0); | 2472 | status = nfs4_call_sync(server, &msg, &args, &res, 1); |
2061 | if (status == 0) { | 2473 | if (status == 0) { |
2062 | update_changeattr(dir, &res.cinfo); | 2474 | update_changeattr(dir, &res.cinfo); |
2063 | nfs_post_op_update_inode(dir, &res.dir_attr); | 2475 | nfs_post_op_update_inode(dir, &res.dir_attr); |
@@ -2092,8 +2504,10 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
2092 | { | 2504 | { |
2093 | struct nfs_removeres *res = task->tk_msg.rpc_resp; | 2505 | struct nfs_removeres *res = task->tk_msg.rpc_resp; |
2094 | 2506 | ||
2507 | nfs4_sequence_done(res->server, &res->seq_res, task->tk_status); | ||
2095 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | 2508 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) |
2096 | return 0; | 2509 | return 0; |
2510 | nfs4_sequence_free_slot(res->server->nfs_client, &res->seq_res); | ||
2097 | update_changeattr(dir, &res->cinfo); | 2511 | update_changeattr(dir, &res->cinfo); |
2098 | nfs_post_op_update_inode(dir, &res->dir_attr); | 2512 | nfs_post_op_update_inode(dir, &res->dir_attr); |
2099 | return 1; | 2513 | return 1; |
@@ -2125,7 +2539,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
2125 | 2539 | ||
2126 | nfs_fattr_init(res.old_fattr); | 2540 | nfs_fattr_init(res.old_fattr); |
2127 | nfs_fattr_init(res.new_fattr); | 2541 | nfs_fattr_init(res.new_fattr); |
2128 | status = rpc_call_sync(server->client, &msg, 0); | 2542 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); |
2129 | 2543 | ||
2130 | if (!status) { | 2544 | if (!status) { |
2131 | update_changeattr(old_dir, &res.old_cinfo); | 2545 | update_changeattr(old_dir, &res.old_cinfo); |
@@ -2174,7 +2588,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
2174 | 2588 | ||
2175 | nfs_fattr_init(res.fattr); | 2589 | nfs_fattr_init(res.fattr); |
2176 | nfs_fattr_init(res.dir_attr); | 2590 | nfs_fattr_init(res.dir_attr); |
2177 | status = rpc_call_sync(server->client, &msg, 0); | 2591 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); |
2178 | if (!status) { | 2592 | if (!status) { |
2179 | update_changeattr(dir, &res.cinfo); | 2593 | update_changeattr(dir, &res.cinfo); |
2180 | nfs_post_op_update_inode(dir, res.dir_attr); | 2594 | nfs_post_op_update_inode(dir, res.dir_attr); |
@@ -2235,7 +2649,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
2235 | 2649 | ||
2236 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) | 2650 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) |
2237 | { | 2651 | { |
2238 | int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); | 2652 | int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg, |
2653 | &data->arg, &data->res, 1); | ||
2239 | if (status == 0) { | 2654 | if (status == 0) { |
2240 | update_changeattr(dir, &data->res.dir_cinfo); | 2655 | update_changeattr(dir, &data->res.dir_cinfo); |
2241 | nfs_post_op_update_inode(dir, data->res.dir_fattr); | 2656 | nfs_post_op_update_inode(dir, data->res.dir_fattr); |
@@ -2344,7 +2759,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
2344 | (unsigned long long)cookie); | 2759 | (unsigned long long)cookie); |
2345 | nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); | 2760 | nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); |
2346 | res.pgbase = args.pgbase; | 2761 | res.pgbase = args.pgbase; |
2347 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 2762 | status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0); |
2348 | if (status == 0) | 2763 | if (status == 0) |
2349 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); | 2764 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); |
2350 | 2765 | ||
@@ -2422,14 +2837,17 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2422 | .fh = fhandle, | 2837 | .fh = fhandle, |
2423 | .bitmask = server->attr_bitmask, | 2838 | .bitmask = server->attr_bitmask, |
2424 | }; | 2839 | }; |
2840 | struct nfs4_statfs_res res = { | ||
2841 | .fsstat = fsstat, | ||
2842 | }; | ||
2425 | struct rpc_message msg = { | 2843 | struct rpc_message msg = { |
2426 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS], | 2844 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS], |
2427 | .rpc_argp = &args, | 2845 | .rpc_argp = &args, |
2428 | .rpc_resp = fsstat, | 2846 | .rpc_resp = &res, |
2429 | }; | 2847 | }; |
2430 | 2848 | ||
2431 | nfs_fattr_init(fsstat->fattr); | 2849 | nfs_fattr_init(fsstat->fattr); |
2432 | return rpc_call_sync(server->client, &msg, 0); | 2850 | return nfs4_call_sync(server, &msg, &args, &res, 0); |
2433 | } | 2851 | } |
2434 | 2852 | ||
2435 | static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) | 2853 | static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) |
@@ -2451,13 +2869,16 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2451 | .fh = fhandle, | 2869 | .fh = fhandle, |
2452 | .bitmask = server->attr_bitmask, | 2870 | .bitmask = server->attr_bitmask, |
2453 | }; | 2871 | }; |
2872 | struct nfs4_fsinfo_res res = { | ||
2873 | .fsinfo = fsinfo, | ||
2874 | }; | ||
2454 | struct rpc_message msg = { | 2875 | struct rpc_message msg = { |
2455 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO], | 2876 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO], |
2456 | .rpc_argp = &args, | 2877 | .rpc_argp = &args, |
2457 | .rpc_resp = fsinfo, | 2878 | .rpc_resp = &res, |
2458 | }; | 2879 | }; |
2459 | 2880 | ||
2460 | return rpc_call_sync(server->client, &msg, 0); | 2881 | return nfs4_call_sync(server, &msg, &args, &res, 0); |
2461 | } | 2882 | } |
2462 | 2883 | ||
2463 | static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) | 2884 | static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) |
@@ -2486,10 +2907,13 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle | |||
2486 | .fh = fhandle, | 2907 | .fh = fhandle, |
2487 | .bitmask = server->attr_bitmask, | 2908 | .bitmask = server->attr_bitmask, |
2488 | }; | 2909 | }; |
2910 | struct nfs4_pathconf_res res = { | ||
2911 | .pathconf = pathconf, | ||
2912 | }; | ||
2489 | struct rpc_message msg = { | 2913 | struct rpc_message msg = { |
2490 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF], | 2914 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF], |
2491 | .rpc_argp = &args, | 2915 | .rpc_argp = &args, |
2492 | .rpc_resp = pathconf, | 2916 | .rpc_resp = &res, |
2493 | }; | 2917 | }; |
2494 | 2918 | ||
2495 | /* None of the pathconf attributes are mandatory to implement */ | 2919 | /* None of the pathconf attributes are mandatory to implement */ |
@@ -2499,7 +2923,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle | |||
2499 | } | 2923 | } |
2500 | 2924 | ||
2501 | nfs_fattr_init(pathconf->fattr); | 2925 | nfs_fattr_init(pathconf->fattr); |
2502 | return rpc_call_sync(server->client, &msg, 0); | 2926 | return nfs4_call_sync(server, &msg, &args, &res, 0); |
2503 | } | 2927 | } |
2504 | 2928 | ||
2505 | static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | 2929 | static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, |
@@ -2520,8 +2944,13 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
2520 | { | 2944 | { |
2521 | struct nfs_server *server = NFS_SERVER(data->inode); | 2945 | struct nfs_server *server = NFS_SERVER(data->inode); |
2522 | 2946 | ||
2947 | dprintk("--> %s\n", __func__); | ||
2948 | |||
2949 | /* nfs4_sequence_free_slot called in the read rpc_call_done */ | ||
2950 | nfs4_sequence_done(server, &data->res.seq_res, task->tk_status); | ||
2951 | |||
2523 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 2952 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
2524 | rpc_restart_call(task); | 2953 | nfs4_restart_rpc(task, server->nfs_client); |
2525 | return -EAGAIN; | 2954 | return -EAGAIN; |
2526 | } | 2955 | } |
2527 | 2956 | ||
@@ -2541,8 +2970,12 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
2541 | { | 2970 | { |
2542 | struct inode *inode = data->inode; | 2971 | struct inode *inode = data->inode; |
2543 | 2972 | ||
2973 | /* slot is freed in nfs_writeback_done */ | ||
2974 | nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, | ||
2975 | task->tk_status); | ||
2976 | |||
2544 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 2977 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
2545 | rpc_restart_call(task); | 2978 | nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client); |
2546 | return -EAGAIN; | 2979 | return -EAGAIN; |
2547 | } | 2980 | } |
2548 | if (task->tk_status >= 0) { | 2981 | if (task->tk_status >= 0) { |
@@ -2567,10 +3000,14 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
2567 | { | 3000 | { |
2568 | struct inode *inode = data->inode; | 3001 | struct inode *inode = data->inode; |
2569 | 3002 | ||
3003 | nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, | ||
3004 | task->tk_status); | ||
2570 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 3005 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { |
2571 | rpc_restart_call(task); | 3006 | nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client); |
2572 | return -EAGAIN; | 3007 | return -EAGAIN; |
2573 | } | 3008 | } |
3009 | nfs4_sequence_free_slot(NFS_SERVER(inode)->nfs_client, | ||
3010 | &data->res.seq_res); | ||
2574 | nfs_refresh_inode(inode, data->res.fattr); | 3011 | nfs_refresh_inode(inode, data->res.fattr); |
2575 | return 0; | 3012 | return 0; |
2576 | } | 3013 | } |
@@ -2603,6 +3040,9 @@ static void nfs4_renew_done(struct rpc_task *task, void *data) | |||
2603 | if (time_before(clp->cl_last_renewal,timestamp)) | 3040 | if (time_before(clp->cl_last_renewal,timestamp)) |
2604 | clp->cl_last_renewal = timestamp; | 3041 | clp->cl_last_renewal = timestamp; |
2605 | spin_unlock(&clp->cl_lock); | 3042 | spin_unlock(&clp->cl_lock); |
3043 | dprintk("%s calling put_rpccred on rpc_cred %p\n", __func__, | ||
3044 | task->tk_msg.rpc_cred); | ||
3045 | put_rpccred(task->tk_msg.rpc_cred); | ||
2606 | } | 3046 | } |
2607 | 3047 | ||
2608 | static const struct rpc_call_ops nfs4_renew_ops = { | 3048 | static const struct rpc_call_ops nfs4_renew_ops = { |
@@ -2742,12 +3182,14 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
2742 | .acl_pages = pages, | 3182 | .acl_pages = pages, |
2743 | .acl_len = buflen, | 3183 | .acl_len = buflen, |
2744 | }; | 3184 | }; |
2745 | size_t resp_len = buflen; | 3185 | struct nfs_getaclres res = { |
3186 | .acl_len = buflen, | ||
3187 | }; | ||
2746 | void *resp_buf; | 3188 | void *resp_buf; |
2747 | struct rpc_message msg = { | 3189 | struct rpc_message msg = { |
2748 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], | 3190 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], |
2749 | .rpc_argp = &args, | 3191 | .rpc_argp = &args, |
2750 | .rpc_resp = &resp_len, | 3192 | .rpc_resp = &res, |
2751 | }; | 3193 | }; |
2752 | struct page *localpage = NULL; | 3194 | struct page *localpage = NULL; |
2753 | int ret; | 3195 | int ret; |
@@ -2761,26 +3203,26 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
2761 | return -ENOMEM; | 3203 | return -ENOMEM; |
2762 | args.acl_pages[0] = localpage; | 3204 | args.acl_pages[0] = localpage; |
2763 | args.acl_pgbase = 0; | 3205 | args.acl_pgbase = 0; |
2764 | resp_len = args.acl_len = PAGE_SIZE; | 3206 | args.acl_len = PAGE_SIZE; |
2765 | } else { | 3207 | } else { |
2766 | resp_buf = buf; | 3208 | resp_buf = buf; |
2767 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); | 3209 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); |
2768 | } | 3210 | } |
2769 | ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 3211 | ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); |
2770 | if (ret) | 3212 | if (ret) |
2771 | goto out_free; | 3213 | goto out_free; |
2772 | if (resp_len > args.acl_len) | 3214 | if (res.acl_len > args.acl_len) |
2773 | nfs4_write_cached_acl(inode, NULL, resp_len); | 3215 | nfs4_write_cached_acl(inode, NULL, res.acl_len); |
2774 | else | 3216 | else |
2775 | nfs4_write_cached_acl(inode, resp_buf, resp_len); | 3217 | nfs4_write_cached_acl(inode, resp_buf, res.acl_len); |
2776 | if (buf) { | 3218 | if (buf) { |
2777 | ret = -ERANGE; | 3219 | ret = -ERANGE; |
2778 | if (resp_len > buflen) | 3220 | if (res.acl_len > buflen) |
2779 | goto out_free; | 3221 | goto out_free; |
2780 | if (localpage) | 3222 | if (localpage) |
2781 | memcpy(buf, resp_buf, resp_len); | 3223 | memcpy(buf, resp_buf, res.acl_len); |
2782 | } | 3224 | } |
2783 | ret = resp_len; | 3225 | ret = res.acl_len; |
2784 | out_free: | 3226 | out_free: |
2785 | if (localpage) | 3227 | if (localpage) |
2786 | __free_page(localpage); | 3228 | __free_page(localpage); |
@@ -2810,8 +3252,6 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) | |||
2810 | ret = nfs_revalidate_inode(server, inode); | 3252 | ret = nfs_revalidate_inode(server, inode); |
2811 | if (ret < 0) | 3253 | if (ret < 0) |
2812 | return ret; | 3254 | return ret; |
2813 | if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL) | ||
2814 | nfs_zap_acl_cache(inode); | ||
2815 | ret = nfs4_read_cached_acl(inode, buf, buflen); | 3255 | ret = nfs4_read_cached_acl(inode, buf, buflen); |
2816 | if (ret != -ENOENT) | 3256 | if (ret != -ENOENT) |
2817 | return ret; | 3257 | return ret; |
@@ -2827,10 +3267,11 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
2827 | .acl_pages = pages, | 3267 | .acl_pages = pages, |
2828 | .acl_len = buflen, | 3268 | .acl_len = buflen, |
2829 | }; | 3269 | }; |
3270 | struct nfs_setaclres res; | ||
2830 | struct rpc_message msg = { | 3271 | struct rpc_message msg = { |
2831 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL], | 3272 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL], |
2832 | .rpc_argp = &arg, | 3273 | .rpc_argp = &arg, |
2833 | .rpc_resp = NULL, | 3274 | .rpc_resp = &res, |
2834 | }; | 3275 | }; |
2835 | int ret; | 3276 | int ret; |
2836 | 3277 | ||
@@ -2838,7 +3279,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
2838 | return -EOPNOTSUPP; | 3279 | return -EOPNOTSUPP; |
2839 | nfs_inode_return_delegation(inode); | 3280 | nfs_inode_return_delegation(inode); |
2840 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | 3281 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); |
2841 | ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 3282 | ret = nfs4_call_sync(server, &msg, &arg, &res, 1); |
2842 | nfs_access_zap_cache(inode); | 3283 | nfs_access_zap_cache(inode); |
2843 | nfs_zap_acl_cache(inode); | 3284 | nfs_zap_acl_cache(inode); |
2844 | return ret; | 3285 | return ret; |
@@ -2857,10 +3298,8 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
2857 | } | 3298 | } |
2858 | 3299 | ||
2859 | static int | 3300 | static int |
2860 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | 3301 | _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs_client *clp, struct nfs4_state *state) |
2861 | { | 3302 | { |
2862 | struct nfs_client *clp = server->nfs_client; | ||
2863 | |||
2864 | if (!clp || task->tk_status >= 0) | 3303 | if (!clp || task->tk_status >= 0) |
2865 | return 0; | 3304 | return 0; |
2866 | switch(task->tk_status) { | 3305 | switch(task->tk_status) { |
@@ -2879,8 +3318,23 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
2879 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | 3318 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); |
2880 | task->tk_status = 0; | 3319 | task->tk_status = 0; |
2881 | return -EAGAIN; | 3320 | return -EAGAIN; |
3321 | #if defined(CONFIG_NFS_V4_1) | ||
3322 | case -NFS4ERR_BADSESSION: | ||
3323 | case -NFS4ERR_BADSLOT: | ||
3324 | case -NFS4ERR_BAD_HIGH_SLOT: | ||
3325 | case -NFS4ERR_DEADSESSION: | ||
3326 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
3327 | case -NFS4ERR_SEQ_FALSE_RETRY: | ||
3328 | case -NFS4ERR_SEQ_MISORDERED: | ||
3329 | dprintk("%s ERROR %d, Reset session\n", __func__, | ||
3330 | task->tk_status); | ||
3331 | set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); | ||
3332 | task->tk_status = 0; | ||
3333 | return -EAGAIN; | ||
3334 | #endif /* CONFIG_NFS_V4_1 */ | ||
2882 | case -NFS4ERR_DELAY: | 3335 | case -NFS4ERR_DELAY: |
2883 | nfs_inc_server_stats(server, NFSIOS_DELAY); | 3336 | if (server) |
3337 | nfs_inc_server_stats(server, NFSIOS_DELAY); | ||
2884 | case -NFS4ERR_GRACE: | 3338 | case -NFS4ERR_GRACE: |
2885 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3339 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
2886 | task->tk_status = 0; | 3340 | task->tk_status = 0; |
@@ -2893,6 +3347,12 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
2893 | return 0; | 3347 | return 0; |
2894 | } | 3348 | } |
2895 | 3349 | ||
3350 | static int | ||
3351 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | ||
3352 | { | ||
3353 | return _nfs4_async_handle_error(task, server, server->nfs_client, state); | ||
3354 | } | ||
3355 | |||
2896 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) | 3356 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) |
2897 | { | 3357 | { |
2898 | nfs4_verifier sc_verifier; | 3358 | nfs4_verifier sc_verifier; |
@@ -3000,6 +3460,10 @@ struct nfs4_delegreturndata { | |||
3000 | static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | 3460 | static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) |
3001 | { | 3461 | { |
3002 | struct nfs4_delegreturndata *data = calldata; | 3462 | struct nfs4_delegreturndata *data = calldata; |
3463 | |||
3464 | nfs4_sequence_done_free_slot(data->res.server, &data->res.seq_res, | ||
3465 | task->tk_status); | ||
3466 | |||
3003 | data->rpc_status = task->tk_status; | 3467 | data->rpc_status = task->tk_status; |
3004 | if (data->rpc_status == 0) | 3468 | if (data->rpc_status == 0) |
3005 | renew_lease(data->res.server, data->timestamp); | 3469 | renew_lease(data->res.server, data->timestamp); |
@@ -3010,7 +3474,25 @@ static void nfs4_delegreturn_release(void *calldata) | |||
3010 | kfree(calldata); | 3474 | kfree(calldata); |
3011 | } | 3475 | } |
3012 | 3476 | ||
3477 | #if defined(CONFIG_NFS_V4_1) | ||
3478 | static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | ||
3479 | { | ||
3480 | struct nfs4_delegreturndata *d_data; | ||
3481 | |||
3482 | d_data = (struct nfs4_delegreturndata *)data; | ||
3483 | |||
3484 | if (nfs4_setup_sequence(d_data->res.server->nfs_client, | ||
3485 | &d_data->args.seq_args, | ||
3486 | &d_data->res.seq_res, 1, task)) | ||
3487 | return; | ||
3488 | rpc_call_start(task); | ||
3489 | } | ||
3490 | #endif /* CONFIG_NFS_V4_1 */ | ||
3491 | |||
3013 | static const struct rpc_call_ops nfs4_delegreturn_ops = { | 3492 | static const struct rpc_call_ops nfs4_delegreturn_ops = { |
3493 | #if defined(CONFIG_NFS_V4_1) | ||
3494 | .rpc_call_prepare = nfs4_delegreturn_prepare, | ||
3495 | #endif /* CONFIG_NFS_V4_1 */ | ||
3014 | .rpc_call_done = nfs4_delegreturn_done, | 3496 | .rpc_call_done = nfs4_delegreturn_done, |
3015 | .rpc_release = nfs4_delegreturn_release, | 3497 | .rpc_release = nfs4_delegreturn_release, |
3016 | }; | 3498 | }; |
@@ -3032,7 +3514,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3032 | }; | 3514 | }; |
3033 | int status = 0; | 3515 | int status = 0; |
3034 | 3516 | ||
3035 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 3517 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
3036 | if (data == NULL) | 3518 | if (data == NULL) |
3037 | return -ENOMEM; | 3519 | return -ENOMEM; |
3038 | data->args.fhandle = &data->fh; | 3520 | data->args.fhandle = &data->fh; |
@@ -3042,6 +3524,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3042 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); | 3524 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); |
3043 | data->res.fattr = &data->fattr; | 3525 | data->res.fattr = &data->fattr; |
3044 | data->res.server = server; | 3526 | data->res.server = server; |
3527 | data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
3045 | nfs_fattr_init(data->res.fattr); | 3528 | nfs_fattr_init(data->res.fattr); |
3046 | data->timestamp = jiffies; | 3529 | data->timestamp = jiffies; |
3047 | data->rpc_status = 0; | 3530 | data->rpc_status = 0; |
@@ -3127,7 +3610,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
3127 | goto out; | 3610 | goto out; |
3128 | lsp = request->fl_u.nfs4_fl.owner; | 3611 | lsp = request->fl_u.nfs4_fl.owner; |
3129 | arg.lock_owner.id = lsp->ls_id.id; | 3612 | arg.lock_owner.id = lsp->ls_id.id; |
3130 | status = rpc_call_sync(server->client, &msg, 0); | 3613 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); |
3131 | switch (status) { | 3614 | switch (status) { |
3132 | case 0: | 3615 | case 0: |
3133 | request->fl_type = F_UNLCK; | 3616 | request->fl_type = F_UNLCK; |
@@ -3187,13 +3670,14 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, | |||
3187 | struct nfs4_unlockdata *p; | 3670 | struct nfs4_unlockdata *p; |
3188 | struct inode *inode = lsp->ls_state->inode; | 3671 | struct inode *inode = lsp->ls_state->inode; |
3189 | 3672 | ||
3190 | p = kmalloc(sizeof(*p), GFP_KERNEL); | 3673 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
3191 | if (p == NULL) | 3674 | if (p == NULL) |
3192 | return NULL; | 3675 | return NULL; |
3193 | p->arg.fh = NFS_FH(inode); | 3676 | p->arg.fh = NFS_FH(inode); |
3194 | p->arg.fl = &p->fl; | 3677 | p->arg.fl = &p->fl; |
3195 | p->arg.seqid = seqid; | 3678 | p->arg.seqid = seqid; |
3196 | p->res.seqid = seqid; | 3679 | p->res.seqid = seqid; |
3680 | p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
3197 | p->arg.stateid = &lsp->ls_stateid; | 3681 | p->arg.stateid = &lsp->ls_stateid; |
3198 | p->lsp = lsp; | 3682 | p->lsp = lsp; |
3199 | atomic_inc(&lsp->ls_count); | 3683 | atomic_inc(&lsp->ls_count); |
@@ -3217,6 +3701,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
3217 | { | 3701 | { |
3218 | struct nfs4_unlockdata *calldata = data; | 3702 | struct nfs4_unlockdata *calldata = data; |
3219 | 3703 | ||
3704 | nfs4_sequence_done(calldata->server, &calldata->res.seq_res, | ||
3705 | task->tk_status); | ||
3220 | if (RPC_ASSASSINATED(task)) | 3706 | if (RPC_ASSASSINATED(task)) |
3221 | return; | 3707 | return; |
3222 | switch (task->tk_status) { | 3708 | switch (task->tk_status) { |
@@ -3233,8 +3719,11 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
3233 | break; | 3719 | break; |
3234 | default: | 3720 | default: |
3235 | if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) | 3721 | if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) |
3236 | rpc_restart_call(task); | 3722 | nfs4_restart_rpc(task, |
3723 | calldata->server->nfs_client); | ||
3237 | } | 3724 | } |
3725 | nfs4_sequence_free_slot(calldata->server->nfs_client, | ||
3726 | &calldata->res.seq_res); | ||
3238 | } | 3727 | } |
3239 | 3728 | ||
3240 | static void nfs4_locku_prepare(struct rpc_task *task, void *data) | 3729 | static void nfs4_locku_prepare(struct rpc_task *task, void *data) |
@@ -3249,6 +3738,10 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
3249 | return; | 3738 | return; |
3250 | } | 3739 | } |
3251 | calldata->timestamp = jiffies; | 3740 | calldata->timestamp = jiffies; |
3741 | if (nfs4_setup_sequence(calldata->server->nfs_client, | ||
3742 | &calldata->arg.seq_args, | ||
3743 | &calldata->res.seq_res, 1, task)) | ||
3744 | return; | ||
3252 | rpc_call_start(task); | 3745 | rpc_call_start(task); |
3253 | } | 3746 | } |
3254 | 3747 | ||
@@ -3341,6 +3834,7 @@ struct nfs4_lockdata { | |||
3341 | unsigned long timestamp; | 3834 | unsigned long timestamp; |
3342 | int rpc_status; | 3835 | int rpc_status; |
3343 | int cancelled; | 3836 | int cancelled; |
3837 | struct nfs_server *server; | ||
3344 | }; | 3838 | }; |
3345 | 3839 | ||
3346 | static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | 3840 | static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, |
@@ -3366,7 +3860,9 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
3366 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | 3860 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; |
3367 | p->arg.lock_owner.id = lsp->ls_id.id; | 3861 | p->arg.lock_owner.id = lsp->ls_id.id; |
3368 | p->res.lock_seqid = p->arg.lock_seqid; | 3862 | p->res.lock_seqid = p->arg.lock_seqid; |
3863 | p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
3369 | p->lsp = lsp; | 3864 | p->lsp = lsp; |
3865 | p->server = server; | ||
3370 | atomic_inc(&lsp->ls_count); | 3866 | atomic_inc(&lsp->ls_count); |
3371 | p->ctx = get_nfs_open_context(ctx); | 3867 | p->ctx = get_nfs_open_context(ctx); |
3372 | memcpy(&p->fl, fl, sizeof(p->fl)); | 3868 | memcpy(&p->fl, fl, sizeof(p->fl)); |
@@ -3396,6 +3892,9 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
3396 | } else | 3892 | } else |
3397 | data->arg.new_lock_owner = 0; | 3893 | data->arg.new_lock_owner = 0; |
3398 | data->timestamp = jiffies; | 3894 | data->timestamp = jiffies; |
3895 | if (nfs4_setup_sequence(data->server->nfs_client, &data->arg.seq_args, | ||
3896 | &data->res.seq_res, 1, task)) | ||
3897 | return; | ||
3399 | rpc_call_start(task); | 3898 | rpc_call_start(task); |
3400 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); | 3899 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); |
3401 | } | 3900 | } |
@@ -3406,6 +3905,9 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) | |||
3406 | 3905 | ||
3407 | dprintk("%s: begin!\n", __func__); | 3906 | dprintk("%s: begin!\n", __func__); |
3408 | 3907 | ||
3908 | nfs4_sequence_done_free_slot(data->server, &data->res.seq_res, | ||
3909 | task->tk_status); | ||
3910 | |||
3409 | data->rpc_status = task->tk_status; | 3911 | data->rpc_status = task->tk_status; |
3410 | if (RPC_ASSASSINATED(task)) | 3912 | if (RPC_ASSASSINATED(task)) |
3411 | goto out; | 3913 | goto out; |
@@ -3487,8 +3989,6 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
3487 | ret = nfs4_wait_for_completion_rpc_task(task); | 3989 | ret = nfs4_wait_for_completion_rpc_task(task); |
3488 | if (ret == 0) { | 3990 | if (ret == 0) { |
3489 | ret = data->rpc_status; | 3991 | ret = data->rpc_status; |
3490 | if (ret == -NFS4ERR_DENIED) | ||
3491 | ret = -EAGAIN; | ||
3492 | } else | 3992 | } else |
3493 | data->cancelled = 1; | 3993 | data->cancelled = 1; |
3494 | rpc_put_task(task); | 3994 | rpc_put_task(task); |
@@ -3576,9 +4076,11 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock * | |||
3576 | int err; | 4076 | int err; |
3577 | 4077 | ||
3578 | do { | 4078 | do { |
4079 | err = _nfs4_proc_setlk(state, cmd, request); | ||
4080 | if (err == -NFS4ERR_DENIED) | ||
4081 | err = -EAGAIN; | ||
3579 | err = nfs4_handle_exception(NFS_SERVER(state->inode), | 4082 | err = nfs4_handle_exception(NFS_SERVER(state->inode), |
3580 | _nfs4_proc_setlk(state, cmd, request), | 4083 | err, &exception); |
3581 | &exception); | ||
3582 | } while (exception.retry); | 4084 | } while (exception.retry); |
3583 | return err; | 4085 | return err; |
3584 | } | 4086 | } |
@@ -3630,8 +4132,37 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
3630 | goto out; | 4132 | goto out; |
3631 | do { | 4133 | do { |
3632 | err = _nfs4_do_setlk(state, F_SETLK, fl, 0); | 4134 | err = _nfs4_do_setlk(state, F_SETLK, fl, 0); |
3633 | if (err != -NFS4ERR_DELAY) | 4135 | switch (err) { |
3634 | break; | 4136 | default: |
4137 | printk(KERN_ERR "%s: unhandled error %d.\n", | ||
4138 | __func__, err); | ||
4139 | case 0: | ||
4140 | case -ESTALE: | ||
4141 | goto out; | ||
4142 | case -NFS4ERR_EXPIRED: | ||
4143 | case -NFS4ERR_STALE_CLIENTID: | ||
4144 | case -NFS4ERR_STALE_STATEID: | ||
4145 | nfs4_schedule_state_recovery(server->nfs_client); | ||
4146 | goto out; | ||
4147 | case -ERESTARTSYS: | ||
4148 | /* | ||
4149 | * The show must go on: exit, but mark the | ||
4150 | * stateid as needing recovery. | ||
4151 | */ | ||
4152 | case -NFS4ERR_ADMIN_REVOKED: | ||
4153 | case -NFS4ERR_BAD_STATEID: | ||
4154 | case -NFS4ERR_OPENMODE: | ||
4155 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); | ||
4156 | err = 0; | ||
4157 | goto out; | ||
4158 | case -ENOMEM: | ||
4159 | case -NFS4ERR_DENIED: | ||
4160 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | ||
4161 | err = 0; | ||
4162 | goto out; | ||
4163 | case -NFS4ERR_DELAY: | ||
4164 | break; | ||
4165 | } | ||
3635 | err = nfs4_handle_exception(server, err, &exception); | 4166 | err = nfs4_handle_exception(server, err, &exception); |
3636 | } while (exception.retry); | 4167 | } while (exception.retry); |
3637 | out: | 4168 | out: |
@@ -3706,10 +4237,13 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
3706 | .page = page, | 4237 | .page = page, |
3707 | .bitmask = bitmask, | 4238 | .bitmask = bitmask, |
3708 | }; | 4239 | }; |
4240 | struct nfs4_fs_locations_res res = { | ||
4241 | .fs_locations = fs_locations, | ||
4242 | }; | ||
3709 | struct rpc_message msg = { | 4243 | struct rpc_message msg = { |
3710 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], | 4244 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], |
3711 | .rpc_argp = &args, | 4245 | .rpc_argp = &args, |
3712 | .rpc_resp = fs_locations, | 4246 | .rpc_resp = &res, |
3713 | }; | 4247 | }; |
3714 | int status; | 4248 | int status; |
3715 | 4249 | ||
@@ -3717,24 +4251,720 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
3717 | nfs_fattr_init(&fs_locations->fattr); | 4251 | nfs_fattr_init(&fs_locations->fattr); |
3718 | fs_locations->server = server; | 4252 | fs_locations->server = server; |
3719 | fs_locations->nlocations = 0; | 4253 | fs_locations->nlocations = 0; |
3720 | status = rpc_call_sync(server->client, &msg, 0); | 4254 | status = nfs4_call_sync(server, &msg, &args, &res, 0); |
3721 | nfs_fixup_referral_attributes(&fs_locations->fattr); | 4255 | nfs_fixup_referral_attributes(&fs_locations->fattr); |
3722 | dprintk("%s: returned status = %d\n", __func__, status); | 4256 | dprintk("%s: returned status = %d\n", __func__, status); |
3723 | return status; | 4257 | return status; |
3724 | } | 4258 | } |
3725 | 4259 | ||
3726 | struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { | 4260 | #ifdef CONFIG_NFS_V4_1 |
4261 | /* | ||
4262 | * nfs4_proc_exchange_id() | ||
4263 | * | ||
4264 | * Since the clientid has expired, all compounds using sessions | ||
4265 | * associated with the stale clientid will be returning | ||
4266 | * NFS4ERR_BADSESSION in the sequence operation, and will therefore | ||
4267 | * be in some phase of session reset. | ||
4268 | */ | ||
4269 | static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | ||
4270 | { | ||
4271 | nfs4_verifier verifier; | ||
4272 | struct nfs41_exchange_id_args args = { | ||
4273 | .client = clp, | ||
4274 | .flags = clp->cl_exchange_flags, | ||
4275 | }; | ||
4276 | struct nfs41_exchange_id_res res = { | ||
4277 | .client = clp, | ||
4278 | }; | ||
4279 | int status; | ||
4280 | struct rpc_message msg = { | ||
4281 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID], | ||
4282 | .rpc_argp = &args, | ||
4283 | .rpc_resp = &res, | ||
4284 | .rpc_cred = cred, | ||
4285 | }; | ||
4286 | __be32 *p; | ||
4287 | |||
4288 | dprintk("--> %s\n", __func__); | ||
4289 | BUG_ON(clp == NULL); | ||
4290 | |||
4291 | p = (u32 *)verifier.data; | ||
4292 | *p++ = htonl((u32)clp->cl_boot_time.tv_sec); | ||
4293 | *p = htonl((u32)clp->cl_boot_time.tv_nsec); | ||
4294 | args.verifier = &verifier; | ||
4295 | |||
4296 | while (1) { | ||
4297 | args.id_len = scnprintf(args.id, sizeof(args.id), | ||
4298 | "%s/%s %u", | ||
4299 | clp->cl_ipaddr, | ||
4300 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
4301 | RPC_DISPLAY_ADDR), | ||
4302 | clp->cl_id_uniquifier); | ||
4303 | |||
4304 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | ||
4305 | |||
4306 | if (status != NFS4ERR_CLID_INUSE) | ||
4307 | break; | ||
4308 | |||
4309 | if (signalled()) | ||
4310 | break; | ||
4311 | |||
4312 | if (++clp->cl_id_uniquifier == 0) | ||
4313 | break; | ||
4314 | } | ||
4315 | |||
4316 | dprintk("<-- %s status= %d\n", __func__, status); | ||
4317 | return status; | ||
4318 | } | ||
4319 | |||
4320 | struct nfs4_get_lease_time_data { | ||
4321 | struct nfs4_get_lease_time_args *args; | ||
4322 | struct nfs4_get_lease_time_res *res; | ||
4323 | struct nfs_client *clp; | ||
4324 | }; | ||
4325 | |||
4326 | static void nfs4_get_lease_time_prepare(struct rpc_task *task, | ||
4327 | void *calldata) | ||
4328 | { | ||
4329 | int ret; | ||
4330 | struct nfs4_get_lease_time_data *data = | ||
4331 | (struct nfs4_get_lease_time_data *)calldata; | ||
4332 | |||
4333 | dprintk("--> %s\n", __func__); | ||
4334 | /* just setup sequence, do not trigger session recovery | ||
4335 | since we're invoked within one */ | ||
4336 | ret = nfs41_setup_sequence(data->clp->cl_session, | ||
4337 | &data->args->la_seq_args, | ||
4338 | &data->res->lr_seq_res, 0, task); | ||
4339 | |||
4340 | BUG_ON(ret == -EAGAIN); | ||
4341 | rpc_call_start(task); | ||
4342 | dprintk("<-- %s\n", __func__); | ||
4343 | } | ||
4344 | |||
4345 | /* | ||
4346 | * Called from nfs4_state_manager thread for session setup, so don't recover | ||
4347 | * from sequence operation or clientid errors. | ||
4348 | */ | ||
4349 | static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | ||
4350 | { | ||
4351 | struct nfs4_get_lease_time_data *data = | ||
4352 | (struct nfs4_get_lease_time_data *)calldata; | ||
4353 | |||
4354 | dprintk("--> %s\n", __func__); | ||
4355 | nfs41_sequence_done(data->clp, &data->res->lr_seq_res, task->tk_status); | ||
4356 | switch (task->tk_status) { | ||
4357 | case -NFS4ERR_DELAY: | ||
4358 | case -NFS4ERR_GRACE: | ||
4359 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); | ||
4360 | rpc_delay(task, NFS4_POLL_RETRY_MIN); | ||
4361 | task->tk_status = 0; | ||
4362 | nfs4_restart_rpc(task, data->clp); | ||
4363 | return; | ||
4364 | } | ||
4365 | nfs41_sequence_free_slot(data->clp, &data->res->lr_seq_res); | ||
4366 | dprintk("<-- %s\n", __func__); | ||
4367 | } | ||
4368 | |||
4369 | struct rpc_call_ops nfs4_get_lease_time_ops = { | ||
4370 | .rpc_call_prepare = nfs4_get_lease_time_prepare, | ||
4371 | .rpc_call_done = nfs4_get_lease_time_done, | ||
4372 | }; | ||
4373 | |||
4374 | int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | ||
4375 | { | ||
4376 | struct rpc_task *task; | ||
4377 | struct nfs4_get_lease_time_args args; | ||
4378 | struct nfs4_get_lease_time_res res = { | ||
4379 | .lr_fsinfo = fsinfo, | ||
4380 | }; | ||
4381 | struct nfs4_get_lease_time_data data = { | ||
4382 | .args = &args, | ||
4383 | .res = &res, | ||
4384 | .clp = clp, | ||
4385 | }; | ||
4386 | struct rpc_message msg = { | ||
4387 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GET_LEASE_TIME], | ||
4388 | .rpc_argp = &args, | ||
4389 | .rpc_resp = &res, | ||
4390 | }; | ||
4391 | struct rpc_task_setup task_setup = { | ||
4392 | .rpc_client = clp->cl_rpcclient, | ||
4393 | .rpc_message = &msg, | ||
4394 | .callback_ops = &nfs4_get_lease_time_ops, | ||
4395 | .callback_data = &data | ||
4396 | }; | ||
4397 | int status; | ||
4398 | |||
4399 | res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
4400 | dprintk("--> %s\n", __func__); | ||
4401 | task = rpc_run_task(&task_setup); | ||
4402 | |||
4403 | if (IS_ERR(task)) | ||
4404 | status = PTR_ERR(task); | ||
4405 | else { | ||
4406 | status = task->tk_status; | ||
4407 | rpc_put_task(task); | ||
4408 | } | ||
4409 | dprintk("<-- %s return %d\n", __func__, status); | ||
4410 | |||
4411 | return status; | ||
4412 | } | ||
4413 | |||
4414 | /* | ||
4415 | * Reset a slot table | ||
4416 | */ | ||
4417 | static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots, | ||
4418 | int old_max_slots, int ivalue) | ||
4419 | { | ||
4420 | int i; | ||
4421 | int ret = 0; | ||
4422 | |||
4423 | dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__, max_slots, tbl); | ||
4424 | |||
4425 | /* | ||
4426 | * Until we have dynamic slot table adjustment, insist | ||
4427 | * upon the same slot table size | ||
4428 | */ | ||
4429 | if (max_slots != old_max_slots) { | ||
4430 | dprintk("%s reset slot table does't match old\n", | ||
4431 | __func__); | ||
4432 | ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */ | ||
4433 | goto out; | ||
4434 | } | ||
4435 | spin_lock(&tbl->slot_tbl_lock); | ||
4436 | for (i = 0; i < max_slots; ++i) | ||
4437 | tbl->slots[i].seq_nr = ivalue; | ||
4438 | tbl->highest_used_slotid = -1; | ||
4439 | spin_unlock(&tbl->slot_tbl_lock); | ||
4440 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | ||
4441 | tbl, tbl->slots, tbl->max_slots); | ||
4442 | out: | ||
4443 | dprintk("<-- %s: return %d\n", __func__, ret); | ||
4444 | return ret; | ||
4445 | } | ||
4446 | |||
4447 | /* | ||
4448 | * Reset the forechannel and backchannel slot tables | ||
4449 | */ | ||
4450 | static int nfs4_reset_slot_tables(struct nfs4_session *session) | ||
4451 | { | ||
4452 | int status; | ||
4453 | |||
4454 | status = nfs4_reset_slot_table(&session->fc_slot_table, | ||
4455 | session->fc_attrs.max_reqs, | ||
4456 | session->fc_slot_table.max_slots, | ||
4457 | 1); | ||
4458 | if (status) | ||
4459 | return status; | ||
4460 | |||
4461 | status = nfs4_reset_slot_table(&session->bc_slot_table, | ||
4462 | session->bc_attrs.max_reqs, | ||
4463 | session->bc_slot_table.max_slots, | ||
4464 | 0); | ||
4465 | return status; | ||
4466 | } | ||
4467 | |||
4468 | /* Destroy the slot table */ | ||
4469 | static void nfs4_destroy_slot_tables(struct nfs4_session *session) | ||
4470 | { | ||
4471 | if (session->fc_slot_table.slots != NULL) { | ||
4472 | kfree(session->fc_slot_table.slots); | ||
4473 | session->fc_slot_table.slots = NULL; | ||
4474 | } | ||
4475 | if (session->bc_slot_table.slots != NULL) { | ||
4476 | kfree(session->bc_slot_table.slots); | ||
4477 | session->bc_slot_table.slots = NULL; | ||
4478 | } | ||
4479 | return; | ||
4480 | } | ||
4481 | |||
4482 | /* | ||
4483 | * Initialize slot table | ||
4484 | */ | ||
4485 | static int nfs4_init_slot_table(struct nfs4_slot_table *tbl, | ||
4486 | int max_slots, int ivalue) | ||
4487 | { | ||
4488 | int i; | ||
4489 | struct nfs4_slot *slot; | ||
4490 | int ret = -ENOMEM; | ||
4491 | |||
4492 | BUG_ON(max_slots > NFS4_MAX_SLOT_TABLE); | ||
4493 | |||
4494 | dprintk("--> %s: max_reqs=%u\n", __func__, max_slots); | ||
4495 | |||
4496 | slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_KERNEL); | ||
4497 | if (!slot) | ||
4498 | goto out; | ||
4499 | for (i = 0; i < max_slots; ++i) | ||
4500 | slot[i].seq_nr = ivalue; | ||
4501 | ret = 0; | ||
4502 | |||
4503 | spin_lock(&tbl->slot_tbl_lock); | ||
4504 | if (tbl->slots != NULL) { | ||
4505 | spin_unlock(&tbl->slot_tbl_lock); | ||
4506 | dprintk("%s: slot table already initialized. tbl=%p slots=%p\n", | ||
4507 | __func__, tbl, tbl->slots); | ||
4508 | WARN_ON(1); | ||
4509 | goto out_free; | ||
4510 | } | ||
4511 | tbl->max_slots = max_slots; | ||
4512 | tbl->slots = slot; | ||
4513 | tbl->highest_used_slotid = -1; /* no slot is currently used */ | ||
4514 | spin_unlock(&tbl->slot_tbl_lock); | ||
4515 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | ||
4516 | tbl, tbl->slots, tbl->max_slots); | ||
4517 | out: | ||
4518 | dprintk("<-- %s: return %d\n", __func__, ret); | ||
4519 | return ret; | ||
4520 | |||
4521 | out_free: | ||
4522 | kfree(slot); | ||
4523 | goto out; | ||
4524 | } | ||
4525 | |||
4526 | /* | ||
4527 | * Initialize the forechannel and backchannel tables | ||
4528 | */ | ||
4529 | static int nfs4_init_slot_tables(struct nfs4_session *session) | ||
4530 | { | ||
4531 | int status; | ||
4532 | |||
4533 | status = nfs4_init_slot_table(&session->fc_slot_table, | ||
4534 | session->fc_attrs.max_reqs, 1); | ||
4535 | if (status) | ||
4536 | return status; | ||
4537 | |||
4538 | status = nfs4_init_slot_table(&session->bc_slot_table, | ||
4539 | session->bc_attrs.max_reqs, 0); | ||
4540 | if (status) | ||
4541 | nfs4_destroy_slot_tables(session); | ||
4542 | |||
4543 | return status; | ||
4544 | } | ||
4545 | |||
4546 | struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | ||
4547 | { | ||
4548 | struct nfs4_session *session; | ||
4549 | struct nfs4_slot_table *tbl; | ||
4550 | |||
4551 | session = kzalloc(sizeof(struct nfs4_session), GFP_KERNEL); | ||
4552 | if (!session) | ||
4553 | return NULL; | ||
4554 | |||
4555 | set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); | ||
4556 | /* | ||
4557 | * The create session reply races with the server back | ||
4558 | * channel probe. Mark the client NFS_CS_SESSION_INITING | ||
4559 | * so that the client back channel can find the | ||
4560 | * nfs_client struct | ||
4561 | */ | ||
4562 | clp->cl_cons_state = NFS_CS_SESSION_INITING; | ||
4563 | |||
4564 | tbl = &session->fc_slot_table; | ||
4565 | spin_lock_init(&tbl->slot_tbl_lock); | ||
4566 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); | ||
4567 | |||
4568 | tbl = &session->bc_slot_table; | ||
4569 | spin_lock_init(&tbl->slot_tbl_lock); | ||
4570 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); | ||
4571 | |||
4572 | session->clp = clp; | ||
4573 | return session; | ||
4574 | } | ||
4575 | |||
4576 | void nfs4_destroy_session(struct nfs4_session *session) | ||
4577 | { | ||
4578 | nfs4_proc_destroy_session(session); | ||
4579 | dprintk("%s Destroy backchannel for xprt %p\n", | ||
4580 | __func__, session->clp->cl_rpcclient->cl_xprt); | ||
4581 | xprt_destroy_backchannel(session->clp->cl_rpcclient->cl_xprt, | ||
4582 | NFS41_BC_MIN_CALLBACKS); | ||
4583 | nfs4_destroy_slot_tables(session); | ||
4584 | kfree(session); | ||
4585 | } | ||
4586 | |||
4587 | /* | ||
4588 | * Initialize the values to be used by the client in CREATE_SESSION | ||
4589 | * If nfs4_init_session set the fore channel request and response sizes, | ||
4590 | * use them. | ||
4591 | * | ||
4592 | * Set the back channel max_resp_sz_cached to zero to force the client to | ||
4593 | * always set csa_cachethis to FALSE because the current implementation | ||
4594 | * of the back channel DRC only supports caching the CB_SEQUENCE operation. | ||
4595 | */ | ||
4596 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | ||
4597 | { | ||
4598 | struct nfs4_session *session = args->client->cl_session; | ||
4599 | unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz, | ||
4600 | mxresp_sz = session->fc_attrs.max_resp_sz; | ||
4601 | |||
4602 | if (mxrqst_sz == 0) | ||
4603 | mxrqst_sz = NFS_MAX_FILE_IO_SIZE; | ||
4604 | if (mxresp_sz == 0) | ||
4605 | mxresp_sz = NFS_MAX_FILE_IO_SIZE; | ||
4606 | /* Fore channel attributes */ | ||
4607 | args->fc_attrs.headerpadsz = 0; | ||
4608 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | ||
4609 | args->fc_attrs.max_resp_sz = mxresp_sz; | ||
4610 | args->fc_attrs.max_resp_sz_cached = mxresp_sz; | ||
4611 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | ||
4612 | args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs; | ||
4613 | |||
4614 | dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u " | ||
4615 | "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n", | ||
4616 | __func__, | ||
4617 | args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz, | ||
4618 | args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops, | ||
4619 | args->fc_attrs.max_reqs); | ||
4620 | |||
4621 | /* Back channel attributes */ | ||
4622 | args->bc_attrs.headerpadsz = 0; | ||
4623 | args->bc_attrs.max_rqst_sz = PAGE_SIZE; | ||
4624 | args->bc_attrs.max_resp_sz = PAGE_SIZE; | ||
4625 | args->bc_attrs.max_resp_sz_cached = 0; | ||
4626 | args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS; | ||
4627 | args->bc_attrs.max_reqs = 1; | ||
4628 | |||
4629 | dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u " | ||
4630 | "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n", | ||
4631 | __func__, | ||
4632 | args->bc_attrs.max_rqst_sz, args->bc_attrs.max_resp_sz, | ||
4633 | args->bc_attrs.max_resp_sz_cached, args->bc_attrs.max_ops, | ||
4634 | args->bc_attrs.max_reqs); | ||
4635 | } | ||
4636 | |||
4637 | static int _verify_channel_attr(char *chan, char *attr_name, u32 sent, u32 rcvd) | ||
4638 | { | ||
4639 | if (rcvd <= sent) | ||
4640 | return 0; | ||
4641 | printk(KERN_WARNING "%s: Session INVALID: %s channel %s increased. " | ||
4642 | "sent=%u rcvd=%u\n", __func__, chan, attr_name, sent, rcvd); | ||
4643 | return -EINVAL; | ||
4644 | } | ||
4645 | |||
4646 | #define _verify_fore_channel_attr(_name_) \ | ||
4647 | _verify_channel_attr("fore", #_name_, \ | ||
4648 | args->fc_attrs._name_, \ | ||
4649 | session->fc_attrs._name_) | ||
4650 | |||
4651 | #define _verify_back_channel_attr(_name_) \ | ||
4652 | _verify_channel_attr("back", #_name_, \ | ||
4653 | args->bc_attrs._name_, \ | ||
4654 | session->bc_attrs._name_) | ||
4655 | |||
4656 | /* | ||
4657 | * The server is not allowed to increase the fore channel header pad size, | ||
4658 | * maximum response size, or maximum number of operations. | ||
4659 | * | ||
4660 | * The back channel attributes are only negotiatied down: We send what the | ||
4661 | * (back channel) server insists upon. | ||
4662 | */ | ||
4663 | static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args, | ||
4664 | struct nfs4_session *session) | ||
4665 | { | ||
4666 | int ret = 0; | ||
4667 | |||
4668 | ret |= _verify_fore_channel_attr(headerpadsz); | ||
4669 | ret |= _verify_fore_channel_attr(max_resp_sz); | ||
4670 | ret |= _verify_fore_channel_attr(max_ops); | ||
4671 | |||
4672 | ret |= _verify_back_channel_attr(headerpadsz); | ||
4673 | ret |= _verify_back_channel_attr(max_rqst_sz); | ||
4674 | ret |= _verify_back_channel_attr(max_resp_sz); | ||
4675 | ret |= _verify_back_channel_attr(max_resp_sz_cached); | ||
4676 | ret |= _verify_back_channel_attr(max_ops); | ||
4677 | ret |= _verify_back_channel_attr(max_reqs); | ||
4678 | |||
4679 | return ret; | ||
4680 | } | ||
4681 | |||
4682 | static int _nfs4_proc_create_session(struct nfs_client *clp) | ||
4683 | { | ||
4684 | struct nfs4_session *session = clp->cl_session; | ||
4685 | struct nfs41_create_session_args args = { | ||
4686 | .client = clp, | ||
4687 | .cb_program = NFS4_CALLBACK, | ||
4688 | }; | ||
4689 | struct nfs41_create_session_res res = { | ||
4690 | .client = clp, | ||
4691 | }; | ||
4692 | struct rpc_message msg = { | ||
4693 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION], | ||
4694 | .rpc_argp = &args, | ||
4695 | .rpc_resp = &res, | ||
4696 | }; | ||
4697 | int status; | ||
4698 | |||
4699 | nfs4_init_channel_attrs(&args); | ||
4700 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); | ||
4701 | |||
4702 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); | ||
4703 | |||
4704 | if (!status) | ||
4705 | /* Verify the session's negotiated channel_attrs values */ | ||
4706 | status = nfs4_verify_channel_attrs(&args, session); | ||
4707 | if (!status) { | ||
4708 | /* Increment the clientid slot sequence id */ | ||
4709 | clp->cl_seqid++; | ||
4710 | } | ||
4711 | |||
4712 | return status; | ||
4713 | } | ||
4714 | |||
4715 | /* | ||
4716 | * Issues a CREATE_SESSION operation to the server. | ||
4717 | * It is the responsibility of the caller to verify the session is | ||
4718 | * expired before calling this routine. | ||
4719 | */ | ||
4720 | int nfs4_proc_create_session(struct nfs_client *clp, int reset) | ||
4721 | { | ||
4722 | int status; | ||
4723 | unsigned *ptr; | ||
4724 | struct nfs_fsinfo fsinfo; | ||
4725 | struct nfs4_session *session = clp->cl_session; | ||
4726 | |||
4727 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); | ||
4728 | |||
4729 | status = _nfs4_proc_create_session(clp); | ||
4730 | if (status) | ||
4731 | goto out; | ||
4732 | |||
4733 | /* Init or reset the fore channel */ | ||
4734 | if (reset) | ||
4735 | status = nfs4_reset_slot_tables(session); | ||
4736 | else | ||
4737 | status = nfs4_init_slot_tables(session); | ||
4738 | dprintk("fore channel slot table initialization returned %d\n", status); | ||
4739 | if (status) | ||
4740 | goto out; | ||
4741 | |||
4742 | ptr = (unsigned *)&session->sess_id.data[0]; | ||
4743 | dprintk("%s client>seqid %d sessionid %u:%u:%u:%u\n", __func__, | ||
4744 | clp->cl_seqid, ptr[0], ptr[1], ptr[2], ptr[3]); | ||
4745 | |||
4746 | if (reset) | ||
4747 | /* Lease time is aleady set */ | ||
4748 | goto out; | ||
4749 | |||
4750 | /* Get the lease time */ | ||
4751 | status = nfs4_proc_get_lease_time(clp, &fsinfo); | ||
4752 | if (status == 0) { | ||
4753 | /* Update lease time and schedule renewal */ | ||
4754 | spin_lock(&clp->cl_lock); | ||
4755 | clp->cl_lease_time = fsinfo.lease_time * HZ; | ||
4756 | clp->cl_last_renewal = jiffies; | ||
4757 | clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
4758 | spin_unlock(&clp->cl_lock); | ||
4759 | |||
4760 | nfs4_schedule_state_renewal(clp); | ||
4761 | } | ||
4762 | out: | ||
4763 | dprintk("<-- %s\n", __func__); | ||
4764 | return status; | ||
4765 | } | ||
4766 | |||
4767 | /* | ||
4768 | * Issue the over-the-wire RPC DESTROY_SESSION. | ||
4769 | * The caller must serialize access to this routine. | ||
4770 | */ | ||
4771 | int nfs4_proc_destroy_session(struct nfs4_session *session) | ||
4772 | { | ||
4773 | int status = 0; | ||
4774 | struct rpc_message msg; | ||
4775 | |||
4776 | dprintk("--> nfs4_proc_destroy_session\n"); | ||
4777 | |||
4778 | /* session is still being setup */ | ||
4779 | if (session->clp->cl_cons_state != NFS_CS_READY) | ||
4780 | return status; | ||
4781 | |||
4782 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION]; | ||
4783 | msg.rpc_argp = session; | ||
4784 | msg.rpc_resp = NULL; | ||
4785 | msg.rpc_cred = NULL; | ||
4786 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); | ||
4787 | |||
4788 | if (status) | ||
4789 | printk(KERN_WARNING | ||
4790 | "Got error %d from the server on DESTROY_SESSION. " | ||
4791 | "Session has been destroyed regardless...\n", status); | ||
4792 | |||
4793 | dprintk("<-- nfs4_proc_destroy_session\n"); | ||
4794 | return status; | ||
4795 | } | ||
4796 | |||
4797 | /* | ||
4798 | * Renew the cl_session lease. | ||
4799 | */ | ||
4800 | static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | ||
4801 | { | ||
4802 | struct nfs4_sequence_args args; | ||
4803 | struct nfs4_sequence_res res; | ||
4804 | |||
4805 | struct rpc_message msg = { | ||
4806 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE], | ||
4807 | .rpc_argp = &args, | ||
4808 | .rpc_resp = &res, | ||
4809 | .rpc_cred = cred, | ||
4810 | }; | ||
4811 | |||
4812 | args.sa_cache_this = 0; | ||
4813 | |||
4814 | return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args, | ||
4815 | &res, 0); | ||
4816 | } | ||
4817 | |||
4818 | void nfs41_sequence_call_done(struct rpc_task *task, void *data) | ||
4819 | { | ||
4820 | struct nfs_client *clp = (struct nfs_client *)data; | ||
4821 | |||
4822 | nfs41_sequence_done(clp, task->tk_msg.rpc_resp, task->tk_status); | ||
4823 | |||
4824 | if (task->tk_status < 0) { | ||
4825 | dprintk("%s ERROR %d\n", __func__, task->tk_status); | ||
4826 | |||
4827 | if (_nfs4_async_handle_error(task, NULL, clp, NULL) | ||
4828 | == -EAGAIN) { | ||
4829 | nfs4_restart_rpc(task, clp); | ||
4830 | return; | ||
4831 | } | ||
4832 | } | ||
4833 | nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp); | ||
4834 | dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); | ||
4835 | |||
4836 | put_rpccred(task->tk_msg.rpc_cred); | ||
4837 | kfree(task->tk_msg.rpc_argp); | ||
4838 | kfree(task->tk_msg.rpc_resp); | ||
4839 | |||
4840 | dprintk("<-- %s\n", __func__); | ||
4841 | } | ||
4842 | |||
4843 | static void nfs41_sequence_prepare(struct rpc_task *task, void *data) | ||
4844 | { | ||
4845 | struct nfs_client *clp; | ||
4846 | struct nfs4_sequence_args *args; | ||
4847 | struct nfs4_sequence_res *res; | ||
4848 | |||
4849 | clp = (struct nfs_client *)data; | ||
4850 | args = task->tk_msg.rpc_argp; | ||
4851 | res = task->tk_msg.rpc_resp; | ||
4852 | |||
4853 | if (nfs4_setup_sequence(clp, args, res, 0, task)) | ||
4854 | return; | ||
4855 | rpc_call_start(task); | ||
4856 | } | ||
4857 | |||
4858 | static const struct rpc_call_ops nfs41_sequence_ops = { | ||
4859 | .rpc_call_done = nfs41_sequence_call_done, | ||
4860 | .rpc_call_prepare = nfs41_sequence_prepare, | ||
4861 | }; | ||
4862 | |||
4863 | static int nfs41_proc_async_sequence(struct nfs_client *clp, | ||
4864 | struct rpc_cred *cred) | ||
4865 | { | ||
4866 | struct nfs4_sequence_args *args; | ||
4867 | struct nfs4_sequence_res *res; | ||
4868 | struct rpc_message msg = { | ||
4869 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE], | ||
4870 | .rpc_cred = cred, | ||
4871 | }; | ||
4872 | |||
4873 | args = kzalloc(sizeof(*args), GFP_KERNEL); | ||
4874 | if (!args) | ||
4875 | return -ENOMEM; | ||
4876 | res = kzalloc(sizeof(*res), GFP_KERNEL); | ||
4877 | if (!res) { | ||
4878 | kfree(args); | ||
4879 | return -ENOMEM; | ||
4880 | } | ||
4881 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
4882 | msg.rpc_argp = args; | ||
4883 | msg.rpc_resp = res; | ||
4884 | |||
4885 | return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, | ||
4886 | &nfs41_sequence_ops, (void *)clp); | ||
4887 | } | ||
4888 | |||
4889 | #endif /* CONFIG_NFS_V4_1 */ | ||
4890 | |||
4891 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | ||
3727 | .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, | 4892 | .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, |
3728 | .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, | 4893 | .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, |
3729 | .recover_open = nfs4_open_reclaim, | 4894 | .recover_open = nfs4_open_reclaim, |
3730 | .recover_lock = nfs4_lock_reclaim, | 4895 | .recover_lock = nfs4_lock_reclaim, |
4896 | .establish_clid = nfs4_init_clientid, | ||
4897 | .get_clid_cred = nfs4_get_setclientid_cred, | ||
4898 | }; | ||
4899 | |||
4900 | #if defined(CONFIG_NFS_V4_1) | ||
4901 | struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { | ||
4902 | .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, | ||
4903 | .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, | ||
4904 | .recover_open = nfs4_open_reclaim, | ||
4905 | .recover_lock = nfs4_lock_reclaim, | ||
4906 | .establish_clid = nfs4_proc_exchange_id, | ||
4907 | .get_clid_cred = nfs4_get_exchange_id_cred, | ||
4908 | }; | ||
4909 | #endif /* CONFIG_NFS_V4_1 */ | ||
4910 | |||
4911 | struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { | ||
4912 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, | ||
4913 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, | ||
4914 | .recover_open = nfs4_open_expired, | ||
4915 | .recover_lock = nfs4_lock_expired, | ||
4916 | .establish_clid = nfs4_init_clientid, | ||
4917 | .get_clid_cred = nfs4_get_setclientid_cred, | ||
3731 | }; | 4918 | }; |
3732 | 4919 | ||
3733 | struct nfs4_state_recovery_ops nfs4_nograce_recovery_ops = { | 4920 | #if defined(CONFIG_NFS_V4_1) |
4921 | struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = { | ||
3734 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, | 4922 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, |
3735 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, | 4923 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, |
3736 | .recover_open = nfs4_open_expired, | 4924 | .recover_open = nfs4_open_expired, |
3737 | .recover_lock = nfs4_lock_expired, | 4925 | .recover_lock = nfs4_lock_expired, |
4926 | .establish_clid = nfs4_proc_exchange_id, | ||
4927 | .get_clid_cred = nfs4_get_exchange_id_cred, | ||
4928 | }; | ||
4929 | #endif /* CONFIG_NFS_V4_1 */ | ||
4930 | |||
4931 | struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = { | ||
4932 | .sched_state_renewal = nfs4_proc_async_renew, | ||
4933 | .get_state_renewal_cred_locked = nfs4_get_renew_cred_locked, | ||
4934 | .renew_lease = nfs4_proc_renew, | ||
4935 | }; | ||
4936 | |||
4937 | #if defined(CONFIG_NFS_V4_1) | ||
4938 | struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = { | ||
4939 | .sched_state_renewal = nfs41_proc_async_sequence, | ||
4940 | .get_state_renewal_cred_locked = nfs4_get_machine_cred_locked, | ||
4941 | .renew_lease = nfs4_proc_sequence, | ||
4942 | }; | ||
4943 | #endif | ||
4944 | |||
4945 | /* | ||
4946 | * Per minor version reboot and network partition recovery ops | ||
4947 | */ | ||
4948 | |||
4949 | struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[] = { | ||
4950 | &nfs40_reboot_recovery_ops, | ||
4951 | #if defined(CONFIG_NFS_V4_1) | ||
4952 | &nfs41_reboot_recovery_ops, | ||
4953 | #endif | ||
4954 | }; | ||
4955 | |||
4956 | struct nfs4_state_recovery_ops *nfs4_nograce_recovery_ops[] = { | ||
4957 | &nfs40_nograce_recovery_ops, | ||
4958 | #if defined(CONFIG_NFS_V4_1) | ||
4959 | &nfs41_nograce_recovery_ops, | ||
4960 | #endif | ||
4961 | }; | ||
4962 | |||
4963 | struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[] = { | ||
4964 | &nfs40_state_renewal_ops, | ||
4965 | #if defined(CONFIG_NFS_V4_1) | ||
4966 | &nfs41_state_renewal_ops, | ||
4967 | #endif | ||
3738 | }; | 4968 | }; |
3739 | 4969 | ||
3740 | static const struct inode_operations nfs4_file_inode_operations = { | 4970 | static const struct inode_operations nfs4_file_inode_operations = { |