diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 820 |
1 files changed, 229 insertions, 591 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5eec4429970c..493f0f41c554 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/mount.h> | 52 | #include <linux/mount.h> |
53 | #include <linux/module.h> | 53 | #include <linux/module.h> |
54 | #include <linux/nfs_idmap.h> | 54 | #include <linux/nfs_idmap.h> |
55 | #include <linux/sunrpc/bc_xprt.h> | ||
56 | #include <linux/xattr.h> | 55 | #include <linux/xattr.h> |
57 | #include <linux/utsname.h> | 56 | #include <linux/utsname.h> |
58 | #include <linux/freezer.h> | 57 | #include <linux/freezer.h> |
@@ -64,14 +63,14 @@ | |||
64 | #include "callback.h" | 63 | #include "callback.h" |
65 | #include "pnfs.h" | 64 | #include "pnfs.h" |
66 | #include "netns.h" | 65 | #include "netns.h" |
66 | #include "nfs4session.h" | ||
67 | |||
67 | 68 | ||
68 | #define NFSDBG_FACILITY NFSDBG_PROC | 69 | #define NFSDBG_FACILITY NFSDBG_PROC |
69 | 70 | ||
70 | #define NFS4_POLL_RETRY_MIN (HZ/10) | 71 | #define NFS4_POLL_RETRY_MIN (HZ/10) |
71 | #define NFS4_POLL_RETRY_MAX (15*HZ) | 72 | #define NFS4_POLL_RETRY_MAX (15*HZ) |
72 | 73 | ||
73 | #define NFS4_MAX_LOOP_ON_RECOVER (10) | ||
74 | |||
75 | struct nfs4_opendata; | 74 | struct nfs4_opendata; |
76 | static int _nfs4_proc_open(struct nfs4_opendata *data); | 75 | static int _nfs4_proc_open(struct nfs4_opendata *data); |
77 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 76 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
@@ -206,7 +205,6 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent | |||
206 | { | 205 | { |
207 | __be32 *start, *p; | 206 | __be32 *start, *p; |
208 | 207 | ||
209 | BUG_ON(readdir->count < 80); | ||
210 | if (cookie > 2) { | 208 | if (cookie > 2) { |
211 | readdir->cookie = cookie; | 209 | readdir->cookie = cookie; |
212 | memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier)); | 210 | memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier)); |
@@ -256,22 +254,6 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent | |||
256 | kunmap_atomic(start); | 254 | kunmap_atomic(start); |
257 | } | 255 | } |
258 | 256 | ||
259 | static int nfs4_wait_clnt_recover(struct nfs_client *clp) | ||
260 | { | ||
261 | int res; | ||
262 | |||
263 | might_sleep(); | ||
264 | |||
265 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, | ||
266 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
267 | if (res) | ||
268 | return res; | ||
269 | |||
270 | if (clp->cl_cons_state < 0) | ||
271 | return clp->cl_cons_state; | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | 257 | static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) |
276 | { | 258 | { |
277 | int res = 0; | 259 | int res = 0; |
@@ -351,7 +333,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
351 | } | 333 | } |
352 | case -NFS4ERR_GRACE: | 334 | case -NFS4ERR_GRACE: |
353 | case -NFS4ERR_DELAY: | 335 | case -NFS4ERR_DELAY: |
354 | case -EKEYEXPIRED: | ||
355 | ret = nfs4_delay(server->client, &exception->timeout); | 336 | ret = nfs4_delay(server->client, &exception->timeout); |
356 | if (ret != 0) | 337 | if (ret != 0) |
357 | break; | 338 | break; |
@@ -397,144 +378,136 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp | |||
397 | 378 | ||
398 | #if defined(CONFIG_NFS_V4_1) | 379 | #if defined(CONFIG_NFS_V4_1) |
399 | 380 | ||
400 | /* | ||
401 | * nfs4_free_slot - free a slot and efficiently update slot table. | ||
402 | * | ||
403 | * freeing a slot is trivially done by clearing its respective bit | ||
404 | * in the bitmap. | ||
405 | * If the freed slotid equals highest_used_slotid we want to update it | ||
406 | * so that the server would be able to size down the slot table if needed, | ||
407 | * otherwise we know that the highest_used_slotid is still in use. | ||
408 | * When updating highest_used_slotid there may be "holes" in the bitmap | ||
409 | * so we need to scan down from highest_used_slotid to 0 looking for the now | ||
410 | * highest slotid in use. | ||
411 | * If none found, highest_used_slotid is set to NFS4_NO_SLOT. | ||
412 | * | ||
413 | * Must be called while holding tbl->slot_tbl_lock | ||
414 | */ | ||
415 | static void | ||
416 | nfs4_free_slot(struct nfs4_slot_table *tbl, u32 slotid) | ||
417 | { | ||
418 | BUG_ON(slotid >= NFS4_MAX_SLOT_TABLE); | ||
419 | /* clear used bit in bitmap */ | ||
420 | __clear_bit(slotid, tbl->used_slots); | ||
421 | |||
422 | /* update highest_used_slotid when it is freed */ | ||
423 | if (slotid == tbl->highest_used_slotid) { | ||
424 | slotid = find_last_bit(tbl->used_slots, tbl->max_slots); | ||
425 | if (slotid < tbl->max_slots) | ||
426 | tbl->highest_used_slotid = slotid; | ||
427 | else | ||
428 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
429 | } | ||
430 | dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, | ||
431 | slotid, tbl->highest_used_slotid); | ||
432 | } | ||
433 | |||
434 | bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy) | ||
435 | { | ||
436 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
437 | return true; | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * Signal state manager thread if session fore channel is drained | ||
442 | */ | ||
443 | static void nfs4_check_drain_fc_complete(struct nfs4_session *ses) | ||
444 | { | ||
445 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { | ||
446 | rpc_wake_up_first(&ses->fc_slot_table.slot_tbl_waitq, | ||
447 | nfs4_set_task_privileged, NULL); | ||
448 | return; | ||
449 | } | ||
450 | |||
451 | if (ses->fc_slot_table.highest_used_slotid != NFS4_NO_SLOT) | ||
452 | return; | ||
453 | |||
454 | dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__); | ||
455 | complete(&ses->fc_slot_table.complete); | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * Signal state manager thread if session back channel is drained | ||
460 | */ | ||
461 | void nfs4_check_drain_bc_complete(struct nfs4_session *ses) | ||
462 | { | ||
463 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) || | ||
464 | ses->bc_slot_table.highest_used_slotid != NFS4_NO_SLOT) | ||
465 | return; | ||
466 | dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__); | ||
467 | complete(&ses->bc_slot_table.complete); | ||
468 | } | ||
469 | |||
470 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | 381 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) |
471 | { | 382 | { |
383 | struct nfs4_session *session; | ||
472 | struct nfs4_slot_table *tbl; | 384 | struct nfs4_slot_table *tbl; |
385 | bool send_new_highest_used_slotid = false; | ||
473 | 386 | ||
474 | tbl = &res->sr_session->fc_slot_table; | ||
475 | if (!res->sr_slot) { | 387 | if (!res->sr_slot) { |
476 | /* just wake up the next guy waiting since | 388 | /* just wake up the next guy waiting since |
477 | * we may have not consumed a slot after all */ | 389 | * we may have not consumed a slot after all */ |
478 | dprintk("%s: No slot\n", __func__); | 390 | dprintk("%s: No slot\n", __func__); |
479 | return; | 391 | return; |
480 | } | 392 | } |
393 | tbl = res->sr_slot->table; | ||
394 | session = tbl->session; | ||
481 | 395 | ||
482 | spin_lock(&tbl->slot_tbl_lock); | 396 | spin_lock(&tbl->slot_tbl_lock); |
483 | nfs4_free_slot(tbl, res->sr_slot - tbl->slots); | 397 | /* Be nice to the server: try to ensure that the last transmitted |
484 | nfs4_check_drain_fc_complete(res->sr_session); | 398 | * value for highest_user_slotid <= target_highest_slotid |
399 | */ | ||
400 | if (tbl->highest_used_slotid > tbl->target_highest_slotid) | ||
401 | send_new_highest_used_slotid = true; | ||
402 | |||
403 | if (nfs41_wake_and_assign_slot(tbl, res->sr_slot)) { | ||
404 | send_new_highest_used_slotid = false; | ||
405 | goto out_unlock; | ||
406 | } | ||
407 | nfs4_free_slot(tbl, res->sr_slot); | ||
408 | |||
409 | if (tbl->highest_used_slotid != NFS4_NO_SLOT) | ||
410 | send_new_highest_used_slotid = false; | ||
411 | out_unlock: | ||
485 | spin_unlock(&tbl->slot_tbl_lock); | 412 | spin_unlock(&tbl->slot_tbl_lock); |
486 | res->sr_slot = NULL; | 413 | res->sr_slot = NULL; |
414 | if (send_new_highest_used_slotid) | ||
415 | nfs41_server_notify_highest_slotid_update(session->clp); | ||
487 | } | 416 | } |
488 | 417 | ||
489 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) | 418 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
490 | { | 419 | { |
491 | unsigned long timestamp; | 420 | struct nfs4_session *session; |
421 | struct nfs4_slot *slot; | ||
492 | struct nfs_client *clp; | 422 | struct nfs_client *clp; |
493 | 423 | bool interrupted = false; | |
494 | /* | 424 | int ret = 1; |
495 | * sr_status remains 1 if an RPC level error occurred. The server | ||
496 | * may or may not have processed the sequence operation.. | ||
497 | * Proceed as if the server received and processed the sequence | ||
498 | * operation. | ||
499 | */ | ||
500 | if (res->sr_status == 1) | ||
501 | res->sr_status = NFS_OK; | ||
502 | 425 | ||
503 | /* don't increment the sequence number if the task wasn't sent */ | 426 | /* don't increment the sequence number if the task wasn't sent */ |
504 | if (!RPC_WAS_SENT(task)) | 427 | if (!RPC_WAS_SENT(task)) |
505 | goto out; | 428 | goto out; |
506 | 429 | ||
430 | slot = res->sr_slot; | ||
431 | session = slot->table->session; | ||
432 | |||
433 | if (slot->interrupted) { | ||
434 | slot->interrupted = 0; | ||
435 | interrupted = true; | ||
436 | } | ||
437 | |||
507 | /* Check the SEQUENCE operation status */ | 438 | /* Check the SEQUENCE operation status */ |
508 | switch (res->sr_status) { | 439 | switch (res->sr_status) { |
509 | case 0: | 440 | case 0: |
510 | /* Update the slot's sequence and clientid lease timer */ | 441 | /* Update the slot's sequence and clientid lease timer */ |
511 | ++res->sr_slot->seq_nr; | 442 | ++slot->seq_nr; |
512 | timestamp = res->sr_renewal_time; | 443 | clp = session->clp; |
513 | clp = res->sr_session->clp; | 444 | do_renew_lease(clp, res->sr_timestamp); |
514 | do_renew_lease(clp, timestamp); | ||
515 | /* Check sequence flags */ | 445 | /* Check sequence flags */ |
516 | if (res->sr_status_flags != 0) | 446 | if (res->sr_status_flags != 0) |
517 | nfs4_schedule_lease_recovery(clp); | 447 | nfs4_schedule_lease_recovery(clp); |
448 | nfs41_update_target_slotid(slot->table, slot, res); | ||
518 | break; | 449 | break; |
450 | case 1: | ||
451 | /* | ||
452 | * sr_status remains 1 if an RPC level error occurred. | ||
453 | * The server may or may not have processed the sequence | ||
454 | * operation.. | ||
455 | * Mark the slot as having hosted an interrupted RPC call. | ||
456 | */ | ||
457 | slot->interrupted = 1; | ||
458 | goto out; | ||
519 | case -NFS4ERR_DELAY: | 459 | case -NFS4ERR_DELAY: |
520 | /* The server detected a resend of the RPC call and | 460 | /* The server detected a resend of the RPC call and |
521 | * returned NFS4ERR_DELAY as per Section 2.10.6.2 | 461 | * returned NFS4ERR_DELAY as per Section 2.10.6.2 |
522 | * of RFC5661. | 462 | * of RFC5661. |
523 | */ | 463 | */ |
524 | dprintk("%s: slot=%td seq=%d: Operation in progress\n", | 464 | dprintk("%s: slot=%u seq=%u: Operation in progress\n", |
525 | __func__, | 465 | __func__, |
526 | res->sr_slot - res->sr_session->fc_slot_table.slots, | 466 | slot->slot_nr, |
527 | res->sr_slot->seq_nr); | 467 | slot->seq_nr); |
528 | goto out_retry; | 468 | goto out_retry; |
469 | case -NFS4ERR_BADSLOT: | ||
470 | /* | ||
471 | * The slot id we used was probably retired. Try again | ||
472 | * using a different slot id. | ||
473 | */ | ||
474 | goto retry_nowait; | ||
475 | case -NFS4ERR_SEQ_MISORDERED: | ||
476 | /* | ||
477 | * Was the last operation on this sequence interrupted? | ||
478 | * If so, retry after bumping the sequence number. | ||
479 | */ | ||
480 | if (interrupted) { | ||
481 | ++slot->seq_nr; | ||
482 | goto retry_nowait; | ||
483 | } | ||
484 | /* | ||
485 | * Could this slot have been previously retired? | ||
486 | * If so, then the server may be expecting seq_nr = 1! | ||
487 | */ | ||
488 | if (slot->seq_nr != 1) { | ||
489 | slot->seq_nr = 1; | ||
490 | goto retry_nowait; | ||
491 | } | ||
492 | break; | ||
493 | case -NFS4ERR_SEQ_FALSE_RETRY: | ||
494 | ++slot->seq_nr; | ||
495 | goto retry_nowait; | ||
529 | default: | 496 | default: |
530 | /* Just update the slot sequence no. */ | 497 | /* Just update the slot sequence no. */ |
531 | ++res->sr_slot->seq_nr; | 498 | ++slot->seq_nr; |
532 | } | 499 | } |
533 | out: | 500 | out: |
534 | /* The session may be reset by one of the error handlers. */ | 501 | /* The session may be reset by one of the error handlers. */ |
535 | dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); | 502 | dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); |
536 | nfs41_sequence_free_slot(res); | 503 | nfs41_sequence_free_slot(res); |
537 | return 1; | 504 | return ret; |
505 | retry_nowait: | ||
506 | if (rpc_restart_call_prepare(task)) { | ||
507 | task->tk_status = 0; | ||
508 | ret = 0; | ||
509 | } | ||
510 | goto out; | ||
538 | out_retry: | 511 | out_retry: |
539 | if (!rpc_restart_call(task)) | 512 | if (!rpc_restart_call(task)) |
540 | goto out; | 513 | goto out; |
@@ -545,55 +518,27 @@ out_retry: | |||
545 | static int nfs4_sequence_done(struct rpc_task *task, | 518 | static int nfs4_sequence_done(struct rpc_task *task, |
546 | struct nfs4_sequence_res *res) | 519 | struct nfs4_sequence_res *res) |
547 | { | 520 | { |
548 | if (res->sr_session == NULL) | 521 | if (res->sr_slot == NULL) |
549 | return 1; | 522 | return 1; |
550 | return nfs41_sequence_done(task, res); | 523 | return nfs41_sequence_done(task, res); |
551 | } | 524 | } |
552 | 525 | ||
553 | /* | ||
554 | * nfs4_find_slot - efficiently look for a free slot | ||
555 | * | ||
556 | * nfs4_find_slot looks for an unset bit in the used_slots bitmap. | ||
557 | * If found, we mark the slot as used, update the highest_used_slotid, | ||
558 | * and respectively set up the sequence operation args. | ||
559 | * The slot number is returned if found, or NFS4_NO_SLOT otherwise. | ||
560 | * | ||
561 | * Note: must be called with under the slot_tbl_lock. | ||
562 | */ | ||
563 | static u32 | ||
564 | nfs4_find_slot(struct nfs4_slot_table *tbl) | ||
565 | { | ||
566 | u32 slotid; | ||
567 | u32 ret_id = NFS4_NO_SLOT; | ||
568 | |||
569 | dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n", | ||
570 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, | ||
571 | tbl->max_slots); | ||
572 | slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots); | ||
573 | if (slotid >= tbl->max_slots) | ||
574 | goto out; | ||
575 | __set_bit(slotid, tbl->used_slots); | ||
576 | if (slotid > tbl->highest_used_slotid || | ||
577 | tbl->highest_used_slotid == NFS4_NO_SLOT) | ||
578 | tbl->highest_used_slotid = slotid; | ||
579 | ret_id = slotid; | ||
580 | out: | ||
581 | dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n", | ||
582 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id); | ||
583 | return ret_id; | ||
584 | } | ||
585 | |||
586 | static void nfs41_init_sequence(struct nfs4_sequence_args *args, | 526 | static void nfs41_init_sequence(struct nfs4_sequence_args *args, |
587 | struct nfs4_sequence_res *res, int cache_reply) | 527 | struct nfs4_sequence_res *res, int cache_reply) |
588 | { | 528 | { |
589 | args->sa_session = NULL; | 529 | args->sa_slot = NULL; |
590 | args->sa_cache_this = 0; | 530 | args->sa_cache_this = 0; |
531 | args->sa_privileged = 0; | ||
591 | if (cache_reply) | 532 | if (cache_reply) |
592 | args->sa_cache_this = 1; | 533 | args->sa_cache_this = 1; |
593 | res->sr_session = NULL; | ||
594 | res->sr_slot = NULL; | 534 | res->sr_slot = NULL; |
595 | } | 535 | } |
596 | 536 | ||
537 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
538 | { | ||
539 | args->sa_privileged = 1; | ||
540 | } | ||
541 | |||
597 | int nfs41_setup_sequence(struct nfs4_session *session, | 542 | int nfs41_setup_sequence(struct nfs4_session *session, |
598 | struct nfs4_sequence_args *args, | 543 | struct nfs4_sequence_args *args, |
599 | struct nfs4_sequence_res *res, | 544 | struct nfs4_sequence_res *res, |
@@ -601,59 +546,59 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
601 | { | 546 | { |
602 | struct nfs4_slot *slot; | 547 | struct nfs4_slot *slot; |
603 | struct nfs4_slot_table *tbl; | 548 | struct nfs4_slot_table *tbl; |
604 | u32 slotid; | ||
605 | 549 | ||
606 | dprintk("--> %s\n", __func__); | 550 | dprintk("--> %s\n", __func__); |
607 | /* slot already allocated? */ | 551 | /* slot already allocated? */ |
608 | if (res->sr_slot != NULL) | 552 | if (res->sr_slot != NULL) |
609 | return 0; | 553 | goto out_success; |
610 | 554 | ||
611 | tbl = &session->fc_slot_table; | 555 | tbl = &session->fc_slot_table; |
612 | 556 | ||
557 | task->tk_timeout = 0; | ||
558 | |||
613 | spin_lock(&tbl->slot_tbl_lock); | 559 | spin_lock(&tbl->slot_tbl_lock); |
614 | if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) && | 560 | if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) && |
615 | !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { | 561 | !args->sa_privileged) { |
616 | /* The state manager will wait until the slot table is empty */ | 562 | /* The state manager will wait until the slot table is empty */ |
617 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
618 | spin_unlock(&tbl->slot_tbl_lock); | ||
619 | dprintk("%s session is draining\n", __func__); | 563 | dprintk("%s session is draining\n", __func__); |
620 | return -EAGAIN; | 564 | goto out_sleep; |
621 | } | 565 | } |
622 | 566 | ||
623 | if (!rpc_queue_empty(&tbl->slot_tbl_waitq) && | 567 | slot = nfs4_alloc_slot(tbl); |
624 | !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { | 568 | if (IS_ERR(slot)) { |
625 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | 569 | /* If out of memory, try again in 1/4 second */ |
626 | spin_unlock(&tbl->slot_tbl_lock); | 570 | if (slot == ERR_PTR(-ENOMEM)) |
627 | dprintk("%s enforce FIFO order\n", __func__); | 571 | task->tk_timeout = HZ >> 2; |
628 | return -EAGAIN; | ||
629 | } | ||
630 | |||
631 | slotid = nfs4_find_slot(tbl); | ||
632 | if (slotid == NFS4_NO_SLOT) { | ||
633 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
634 | spin_unlock(&tbl->slot_tbl_lock); | ||
635 | dprintk("<-- %s: no free slots\n", __func__); | 572 | dprintk("<-- %s: no free slots\n", __func__); |
636 | return -EAGAIN; | 573 | goto out_sleep; |
637 | } | 574 | } |
638 | spin_unlock(&tbl->slot_tbl_lock); | 575 | spin_unlock(&tbl->slot_tbl_lock); |
639 | 576 | ||
640 | rpc_task_set_priority(task, RPC_PRIORITY_NORMAL); | 577 | args->sa_slot = slot; |
641 | slot = tbl->slots + slotid; | ||
642 | args->sa_session = session; | ||
643 | args->sa_slotid = slotid; | ||
644 | 578 | ||
645 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); | 579 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, |
580 | slot->slot_nr, slot->seq_nr); | ||
646 | 581 | ||
647 | res->sr_session = session; | ||
648 | res->sr_slot = slot; | 582 | res->sr_slot = slot; |
649 | res->sr_renewal_time = jiffies; | 583 | res->sr_timestamp = jiffies; |
650 | res->sr_status_flags = 0; | 584 | res->sr_status_flags = 0; |
651 | /* | 585 | /* |
652 | * sr_status is only set in decode_sequence, and so will remain | 586 | * sr_status is only set in decode_sequence, and so will remain |
653 | * set to 1 if an rpc level failure occurs. | 587 | * set to 1 if an rpc level failure occurs. |
654 | */ | 588 | */ |
655 | res->sr_status = 1; | 589 | res->sr_status = 1; |
590 | out_success: | ||
591 | rpc_call_start(task); | ||
656 | return 0; | 592 | return 0; |
593 | out_sleep: | ||
594 | /* Privileged tasks are queued with top priority */ | ||
595 | if (args->sa_privileged) | ||
596 | rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task, | ||
597 | NULL, RPC_PRIORITY_PRIVILEGED); | ||
598 | else | ||
599 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
600 | spin_unlock(&tbl->slot_tbl_lock); | ||
601 | return -EAGAIN; | ||
657 | } | 602 | } |
658 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); | 603 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); |
659 | 604 | ||
@@ -665,12 +610,14 @@ int nfs4_setup_sequence(const struct nfs_server *server, | |||
665 | struct nfs4_session *session = nfs4_get_session(server); | 610 | struct nfs4_session *session = nfs4_get_session(server); |
666 | int ret = 0; | 611 | int ret = 0; |
667 | 612 | ||
668 | if (session == NULL) | 613 | if (session == NULL) { |
614 | rpc_call_start(task); | ||
669 | goto out; | 615 | goto out; |
616 | } | ||
670 | 617 | ||
671 | dprintk("--> %s clp %p session %p sr_slot %td\n", | 618 | dprintk("--> %s clp %p session %p sr_slot %d\n", |
672 | __func__, session->clp, session, res->sr_slot ? | 619 | __func__, session->clp, session, res->sr_slot ? |
673 | res->sr_slot - session->fc_slot_table.slots : -1); | 620 | res->sr_slot->slot_nr : -1); |
674 | 621 | ||
675 | ret = nfs41_setup_sequence(session, args, res, task); | 622 | ret = nfs41_setup_sequence(session, args, res, task); |
676 | out: | 623 | out: |
@@ -687,19 +634,11 @@ struct nfs41_call_sync_data { | |||
687 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | 634 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) |
688 | { | 635 | { |
689 | struct nfs41_call_sync_data *data = calldata; | 636 | struct nfs41_call_sync_data *data = calldata; |
637 | struct nfs4_session *session = nfs4_get_session(data->seq_server); | ||
690 | 638 | ||
691 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); | 639 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); |
692 | 640 | ||
693 | if (nfs4_setup_sequence(data->seq_server, data->seq_args, | 641 | nfs41_setup_sequence(session, data->seq_args, data->seq_res, task); |
694 | data->seq_res, task)) | ||
695 | return; | ||
696 | rpc_call_start(task); | ||
697 | } | ||
698 | |||
699 | static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata) | ||
700 | { | ||
701 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
702 | nfs41_call_sync_prepare(task, calldata); | ||
703 | } | 642 | } |
704 | 643 | ||
705 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) | 644 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) |
@@ -714,17 +653,11 @@ static const struct rpc_call_ops nfs41_call_sync_ops = { | |||
714 | .rpc_call_done = nfs41_call_sync_done, | 653 | .rpc_call_done = nfs41_call_sync_done, |
715 | }; | 654 | }; |
716 | 655 | ||
717 | static const struct rpc_call_ops nfs41_call_priv_sync_ops = { | ||
718 | .rpc_call_prepare = nfs41_call_priv_sync_prepare, | ||
719 | .rpc_call_done = nfs41_call_sync_done, | ||
720 | }; | ||
721 | |||
722 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | 656 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, |
723 | struct nfs_server *server, | 657 | struct nfs_server *server, |
724 | struct rpc_message *msg, | 658 | struct rpc_message *msg, |
725 | struct nfs4_sequence_args *args, | 659 | struct nfs4_sequence_args *args, |
726 | struct nfs4_sequence_res *res, | 660 | struct nfs4_sequence_res *res) |
727 | int privileged) | ||
728 | { | 661 | { |
729 | int ret; | 662 | int ret; |
730 | struct rpc_task *task; | 663 | struct rpc_task *task; |
@@ -740,8 +673,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
740 | .callback_data = &data | 673 | .callback_data = &data |
741 | }; | 674 | }; |
742 | 675 | ||
743 | if (privileged) | ||
744 | task_setup.callback_ops = &nfs41_call_priv_sync_ops; | ||
745 | task = rpc_run_task(&task_setup); | 676 | task = rpc_run_task(&task_setup); |
746 | if (IS_ERR(task)) | 677 | if (IS_ERR(task)) |
747 | ret = PTR_ERR(task); | 678 | ret = PTR_ERR(task); |
@@ -752,24 +683,18 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
752 | return ret; | 683 | return ret; |
753 | } | 684 | } |
754 | 685 | ||
755 | int _nfs4_call_sync_session(struct rpc_clnt *clnt, | ||
756 | struct nfs_server *server, | ||
757 | struct rpc_message *msg, | ||
758 | struct nfs4_sequence_args *args, | ||
759 | struct nfs4_sequence_res *res, | ||
760 | int cache_reply) | ||
761 | { | ||
762 | nfs41_init_sequence(args, res, cache_reply); | ||
763 | return nfs4_call_sync_sequence(clnt, server, msg, args, res, 0); | ||
764 | } | ||
765 | |||
766 | #else | 686 | #else |
767 | static inline | 687 | static |
768 | void nfs41_init_sequence(struct nfs4_sequence_args *args, | 688 | void nfs41_init_sequence(struct nfs4_sequence_args *args, |
769 | struct nfs4_sequence_res *res, int cache_reply) | 689 | struct nfs4_sequence_res *res, int cache_reply) |
770 | { | 690 | { |
771 | } | 691 | } |
772 | 692 | ||
693 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
694 | { | ||
695 | } | ||
696 | |||
697 | |||
773 | static int nfs4_sequence_done(struct rpc_task *task, | 698 | static int nfs4_sequence_done(struct rpc_task *task, |
774 | struct nfs4_sequence_res *res) | 699 | struct nfs4_sequence_res *res) |
775 | { | 700 | { |
@@ -777,18 +702,17 @@ static int nfs4_sequence_done(struct rpc_task *task, | |||
777 | } | 702 | } |
778 | #endif /* CONFIG_NFS_V4_1 */ | 703 | #endif /* CONFIG_NFS_V4_1 */ |
779 | 704 | ||
705 | static | ||
780 | int _nfs4_call_sync(struct rpc_clnt *clnt, | 706 | int _nfs4_call_sync(struct rpc_clnt *clnt, |
781 | struct nfs_server *server, | 707 | struct nfs_server *server, |
782 | struct rpc_message *msg, | 708 | struct rpc_message *msg, |
783 | struct nfs4_sequence_args *args, | 709 | struct nfs4_sequence_args *args, |
784 | struct nfs4_sequence_res *res, | 710 | struct nfs4_sequence_res *res) |
785 | int cache_reply) | ||
786 | { | 711 | { |
787 | nfs41_init_sequence(args, res, cache_reply); | ||
788 | return rpc_call_sync(clnt, msg, 0); | 712 | return rpc_call_sync(clnt, msg, 0); |
789 | } | 713 | } |
790 | 714 | ||
791 | static inline | 715 | static |
792 | int nfs4_call_sync(struct rpc_clnt *clnt, | 716 | int nfs4_call_sync(struct rpc_clnt *clnt, |
793 | struct nfs_server *server, | 717 | struct nfs_server *server, |
794 | struct rpc_message *msg, | 718 | struct rpc_message *msg, |
@@ -796,8 +720,9 @@ int nfs4_call_sync(struct rpc_clnt *clnt, | |||
796 | struct nfs4_sequence_res *res, | 720 | struct nfs4_sequence_res *res, |
797 | int cache_reply) | 721 | int cache_reply) |
798 | { | 722 | { |
723 | nfs41_init_sequence(args, res, cache_reply); | ||
799 | return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, | 724 | return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, |
800 | args, res, cache_reply); | 725 | args, res); |
801 | } | 726 | } |
802 | 727 | ||
803 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | 728 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) |
@@ -1445,13 +1370,6 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1445 | nfs_inode_find_state_and_recover(state->inode, | 1370 | nfs_inode_find_state_and_recover(state->inode, |
1446 | stateid); | 1371 | stateid); |
1447 | nfs4_schedule_stateid_recovery(server, state); | 1372 | nfs4_schedule_stateid_recovery(server, state); |
1448 | case -EKEYEXPIRED: | ||
1449 | /* | ||
1450 | * User RPCSEC_GSS context has expired. | ||
1451 | * We cannot recover this stateid now, so | ||
1452 | * skip it and allow recovery thread to | ||
1453 | * proceed. | ||
1454 | */ | ||
1455 | case -ENOMEM: | 1373 | case -ENOMEM: |
1456 | err = 0; | 1374 | err = 0; |
1457 | goto out; | 1375 | goto out; |
@@ -1574,20 +1492,12 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1574 | &data->o_res.seq_res, | 1492 | &data->o_res.seq_res, |
1575 | task) != 0) | 1493 | task) != 0) |
1576 | nfs_release_seqid(data->o_arg.seqid); | 1494 | nfs_release_seqid(data->o_arg.seqid); |
1577 | else | ||
1578 | rpc_call_start(task); | ||
1579 | return; | 1495 | return; |
1580 | unlock_no_action: | 1496 | unlock_no_action: |
1581 | rcu_read_unlock(); | 1497 | rcu_read_unlock(); |
1582 | out_no_action: | 1498 | out_no_action: |
1583 | task->tk_action = NULL; | 1499 | task->tk_action = NULL; |
1584 | 1500 | nfs4_sequence_done(task, &data->o_res.seq_res); | |
1585 | } | ||
1586 | |||
1587 | static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata) | ||
1588 | { | ||
1589 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
1590 | nfs4_open_prepare(task, calldata); | ||
1591 | } | 1501 | } |
1592 | 1502 | ||
1593 | static void nfs4_open_done(struct rpc_task *task, void *calldata) | 1503 | static void nfs4_open_done(struct rpc_task *task, void *calldata) |
@@ -1648,12 +1558,6 @@ static const struct rpc_call_ops nfs4_open_ops = { | |||
1648 | .rpc_release = nfs4_open_release, | 1558 | .rpc_release = nfs4_open_release, |
1649 | }; | 1559 | }; |
1650 | 1560 | ||
1651 | static const struct rpc_call_ops nfs4_recover_open_ops = { | ||
1652 | .rpc_call_prepare = nfs4_recover_open_prepare, | ||
1653 | .rpc_call_done = nfs4_open_done, | ||
1654 | .rpc_release = nfs4_open_release, | ||
1655 | }; | ||
1656 | |||
1657 | static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) | 1561 | static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) |
1658 | { | 1562 | { |
1659 | struct inode *dir = data->dir->d_inode; | 1563 | struct inode *dir = data->dir->d_inode; |
@@ -1683,7 +1587,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) | |||
1683 | data->rpc_status = 0; | 1587 | data->rpc_status = 0; |
1684 | data->cancelled = 0; | 1588 | data->cancelled = 0; |
1685 | if (isrecover) | 1589 | if (isrecover) |
1686 | task_setup_data.callback_ops = &nfs4_recover_open_ops; | 1590 | nfs4_set_sequence_privileged(&o_arg->seq_args); |
1687 | task = rpc_run_task(&task_setup_data); | 1591 | task = rpc_run_task(&task_setup_data); |
1688 | if (IS_ERR(task)) | 1592 | if (IS_ERR(task)) |
1689 | return PTR_ERR(task); | 1593 | return PTR_ERR(task); |
@@ -1789,24 +1693,6 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
1789 | return 0; | 1693 | return 0; |
1790 | } | 1694 | } |
1791 | 1695 | ||
1792 | static int nfs4_client_recover_expired_lease(struct nfs_client *clp) | ||
1793 | { | ||
1794 | unsigned int loop; | ||
1795 | int ret; | ||
1796 | |||
1797 | for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { | ||
1798 | ret = nfs4_wait_clnt_recover(clp); | ||
1799 | if (ret != 0) | ||
1800 | break; | ||
1801 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && | ||
1802 | !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) | ||
1803 | break; | ||
1804 | nfs4_schedule_state_manager(clp); | ||
1805 | ret = -EIO; | ||
1806 | } | ||
1807 | return ret; | ||
1808 | } | ||
1809 | |||
1810 | static int nfs4_recover_expired_lease(struct nfs_server *server) | 1696 | static int nfs4_recover_expired_lease(struct nfs_server *server) |
1811 | { | 1697 | { |
1812 | return nfs4_client_recover_expired_lease(server->nfs_client); | 1698 | return nfs4_client_recover_expired_lease(server->nfs_client); |
@@ -2282,6 +2168,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2282 | if (!call_close) { | 2168 | if (!call_close) { |
2283 | /* Note: exit _without_ calling nfs4_close_done */ | 2169 | /* Note: exit _without_ calling nfs4_close_done */ |
2284 | task->tk_action = NULL; | 2170 | task->tk_action = NULL; |
2171 | nfs4_sequence_done(task, &calldata->res.seq_res); | ||
2285 | goto out; | 2172 | goto out; |
2286 | } | 2173 | } |
2287 | 2174 | ||
@@ -2299,8 +2186,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2299 | &calldata->res.seq_res, | 2186 | &calldata->res.seq_res, |
2300 | task) != 0) | 2187 | task) != 0) |
2301 | nfs_release_seqid(calldata->arg.seqid); | 2188 | nfs_release_seqid(calldata->arg.seqid); |
2302 | else | ||
2303 | rpc_call_start(task); | ||
2304 | out: | 2189 | out: |
2305 | dprintk("%s: done!\n", __func__); | 2190 | dprintk("%s: done!\n", __func__); |
2306 | } | 2191 | } |
@@ -2533,7 +2418,8 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2533 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; | 2418 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; |
2534 | 2419 | ||
2535 | len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array)); | 2420 | len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array)); |
2536 | BUG_ON(len < 0); | 2421 | if (len < 0) |
2422 | return len; | ||
2537 | 2423 | ||
2538 | for (i = 0; i < len; i++) { | 2424 | for (i = 0; i < len; i++) { |
2539 | /* AUTH_UNIX is the default flavor if none was specified, | 2425 | /* AUTH_UNIX is the default flavor if none was specified, |
@@ -3038,12 +2924,10 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
3038 | 2924 | ||
3039 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) | 2925 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) |
3040 | { | 2926 | { |
3041 | if (nfs4_setup_sequence(NFS_SERVER(data->dir), | 2927 | nfs4_setup_sequence(NFS_SERVER(data->dir), |
3042 | &data->args.seq_args, | 2928 | &data->args.seq_args, |
3043 | &data->res.seq_res, | 2929 | &data->res.seq_res, |
3044 | task)) | 2930 | task); |
3045 | return; | ||
3046 | rpc_call_start(task); | ||
3047 | } | 2931 | } |
3048 | 2932 | ||
3049 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | 2933 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) |
@@ -3071,12 +2955,10 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) | |||
3071 | 2955 | ||
3072 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) | 2956 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) |
3073 | { | 2957 | { |
3074 | if (nfs4_setup_sequence(NFS_SERVER(data->old_dir), | 2958 | nfs4_setup_sequence(NFS_SERVER(data->old_dir), |
3075 | &data->args.seq_args, | 2959 | &data->args.seq_args, |
3076 | &data->res.seq_res, | 2960 | &data->res.seq_res, |
3077 | task)) | 2961 | task); |
3078 | return; | ||
3079 | rpc_call_start(task); | ||
3080 | } | 2962 | } |
3081 | 2963 | ||
3082 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | 2964 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, |
@@ -3362,9 +3244,6 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3362 | int mode = sattr->ia_mode; | 3244 | int mode = sattr->ia_mode; |
3363 | int status = -ENOMEM; | 3245 | int status = -ENOMEM; |
3364 | 3246 | ||
3365 | BUG_ON(!(sattr->ia_valid & ATTR_MODE)); | ||
3366 | BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); | ||
3367 | |||
3368 | data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK); | 3247 | data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK); |
3369 | if (data == NULL) | 3248 | if (data == NULL) |
3370 | goto out; | 3249 | goto out; |
@@ -3380,10 +3259,13 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3380 | data->arg.ftype = NF4CHR; | 3259 | data->arg.ftype = NF4CHR; |
3381 | data->arg.u.device.specdata1 = MAJOR(rdev); | 3260 | data->arg.u.device.specdata1 = MAJOR(rdev); |
3382 | data->arg.u.device.specdata2 = MINOR(rdev); | 3261 | data->arg.u.device.specdata2 = MINOR(rdev); |
3262 | } else if (!S_ISSOCK(mode)) { | ||
3263 | status = -EINVAL; | ||
3264 | goto out_free; | ||
3383 | } | 3265 | } |
3384 | 3266 | ||
3385 | status = nfs4_do_create(dir, dentry, data); | 3267 | status = nfs4_do_create(dir, dentry, data); |
3386 | 3268 | out_free: | |
3387 | nfs4_free_createdata(data); | 3269 | nfs4_free_createdata(data); |
3388 | out: | 3270 | out: |
3389 | return status; | 3271 | return status; |
@@ -3565,12 +3447,10 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message | |||
3565 | 3447 | ||
3566 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | 3448 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) |
3567 | { | 3449 | { |
3568 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | 3450 | nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3569 | &data->args.seq_args, | 3451 | &data->args.seq_args, |
3570 | &data->res.seq_res, | 3452 | &data->res.seq_res, |
3571 | task)) | 3453 | task); |
3572 | return; | ||
3573 | rpc_call_start(task); | ||
3574 | } | 3454 | } |
3575 | 3455 | ||
3576 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) | 3456 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) |
@@ -3631,22 +3511,18 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
3631 | 3511 | ||
3632 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | 3512 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) |
3633 | { | 3513 | { |
3634 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | 3514 | nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3635 | &data->args.seq_args, | 3515 | &data->args.seq_args, |
3636 | &data->res.seq_res, | 3516 | &data->res.seq_res, |
3637 | task)) | 3517 | task); |
3638 | return; | ||
3639 | rpc_call_start(task); | ||
3640 | } | 3518 | } |
3641 | 3519 | ||
3642 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) | 3520 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) |
3643 | { | 3521 | { |
3644 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), | 3522 | nfs4_setup_sequence(NFS_SERVER(data->inode), |
3645 | &data->args.seq_args, | 3523 | &data->args.seq_args, |
3646 | &data->res.seq_res, | 3524 | &data->res.seq_res, |
3647 | task)) | 3525 | task); |
3648 | return; | ||
3649 | rpc_call_start(task); | ||
3650 | } | 3526 | } |
3651 | 3527 | ||
3652 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data) | 3528 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data) |
@@ -3937,8 +3813,13 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3937 | goto out_free; | 3813 | goto out_free; |
3938 | } | 3814 | } |
3939 | nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); | 3815 | nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); |
3940 | if (buf) | 3816 | if (buf) { |
3817 | if (res.acl_len > buflen) { | ||
3818 | ret = -ERANGE; | ||
3819 | goto out_free; | ||
3820 | } | ||
3941 | _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); | 3821 | _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); |
3822 | } | ||
3942 | out_ok: | 3823 | out_ok: |
3943 | ret = res.acl_len; | 3824 | ret = res.acl_len; |
3944 | out_free: | 3825 | out_free: |
@@ -4085,7 +3966,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
4085 | case -NFS4ERR_DELAY: | 3966 | case -NFS4ERR_DELAY: |
4086 | nfs_inc_server_stats(server, NFSIOS_DELAY); | 3967 | nfs_inc_server_stats(server, NFSIOS_DELAY); |
4087 | case -NFS4ERR_GRACE: | 3968 | case -NFS4ERR_GRACE: |
4088 | case -EKEYEXPIRED: | ||
4089 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3969 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
4090 | task->tk_status = 0; | 3970 | task->tk_status = 0; |
4091 | return -EAGAIN; | 3971 | return -EAGAIN; |
@@ -4293,11 +4173,10 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | |||
4293 | 4173 | ||
4294 | d_data = (struct nfs4_delegreturndata *)data; | 4174 | d_data = (struct nfs4_delegreturndata *)data; |
4295 | 4175 | ||
4296 | if (nfs4_setup_sequence(d_data->res.server, | 4176 | nfs4_setup_sequence(d_data->res.server, |
4297 | &d_data->args.seq_args, | 4177 | &d_data->args.seq_args, |
4298 | &d_data->res.seq_res, task)) | 4178 | &d_data->res.seq_res, |
4299 | return; | 4179 | task); |
4300 | rpc_call_start(task); | ||
4301 | } | 4180 | } |
4302 | #endif /* CONFIG_NFS_V4_1 */ | 4181 | #endif /* CONFIG_NFS_V4_1 */ |
4303 | 4182 | ||
@@ -4543,6 +4422,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
4543 | if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) { | 4422 | if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) { |
4544 | /* Note: exit _without_ running nfs4_locku_done */ | 4423 | /* Note: exit _without_ running nfs4_locku_done */ |
4545 | task->tk_action = NULL; | 4424 | task->tk_action = NULL; |
4425 | nfs4_sequence_done(task, &calldata->res.seq_res); | ||
4546 | return; | 4426 | return; |
4547 | } | 4427 | } |
4548 | calldata->timestamp = jiffies; | 4428 | calldata->timestamp = jiffies; |
@@ -4551,8 +4431,6 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
4551 | &calldata->res.seq_res, | 4431 | &calldata->res.seq_res, |
4552 | task) != 0) | 4432 | task) != 0) |
4553 | nfs_release_seqid(calldata->arg.seqid); | 4433 | nfs_release_seqid(calldata->arg.seqid); |
4554 | else | ||
4555 | rpc_call_start(task); | ||
4556 | } | 4434 | } |
4557 | 4435 | ||
4558 | static const struct rpc_call_ops nfs4_locku_ops = { | 4436 | static const struct rpc_call_ops nfs4_locku_ops = { |
@@ -4696,8 +4574,9 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
4696 | return; | 4574 | return; |
4697 | /* Do we need to do an open_to_lock_owner? */ | 4575 | /* Do we need to do an open_to_lock_owner? */ |
4698 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { | 4576 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { |
4699 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) | 4577 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) { |
4700 | goto out_release_lock_seqid; | 4578 | goto out_release_lock_seqid; |
4579 | } | ||
4701 | data->arg.open_stateid = &state->stateid; | 4580 | data->arg.open_stateid = &state->stateid; |
4702 | data->arg.new_lock_owner = 1; | 4581 | data->arg.new_lock_owner = 1; |
4703 | data->res.open_seqid = data->arg.open_seqid; | 4582 | data->res.open_seqid = data->arg.open_seqid; |
@@ -4707,20 +4586,12 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
4707 | if (nfs4_setup_sequence(data->server, | 4586 | if (nfs4_setup_sequence(data->server, |
4708 | &data->arg.seq_args, | 4587 | &data->arg.seq_args, |
4709 | &data->res.seq_res, | 4588 | &data->res.seq_res, |
4710 | task) == 0) { | 4589 | task) == 0) |
4711 | rpc_call_start(task); | ||
4712 | return; | 4590 | return; |
4713 | } | ||
4714 | nfs_release_seqid(data->arg.open_seqid); | 4591 | nfs_release_seqid(data->arg.open_seqid); |
4715 | out_release_lock_seqid: | 4592 | out_release_lock_seqid: |
4716 | nfs_release_seqid(data->arg.lock_seqid); | 4593 | nfs_release_seqid(data->arg.lock_seqid); |
4717 | dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); | 4594 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); |
4718 | } | ||
4719 | |||
4720 | static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) | ||
4721 | { | ||
4722 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
4723 | nfs4_lock_prepare(task, calldata); | ||
4724 | } | 4595 | } |
4725 | 4596 | ||
4726 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) | 4597 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) |
@@ -4775,12 +4646,6 @@ static const struct rpc_call_ops nfs4_lock_ops = { | |||
4775 | .rpc_release = nfs4_lock_release, | 4646 | .rpc_release = nfs4_lock_release, |
4776 | }; | 4647 | }; |
4777 | 4648 | ||
4778 | static const struct rpc_call_ops nfs4_recover_lock_ops = { | ||
4779 | .rpc_call_prepare = nfs4_recover_lock_prepare, | ||
4780 | .rpc_call_done = nfs4_lock_done, | ||
4781 | .rpc_release = nfs4_lock_release, | ||
4782 | }; | ||
4783 | |||
4784 | static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) | 4649 | static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) |
4785 | { | 4650 | { |
4786 | switch (error) { | 4651 | switch (error) { |
@@ -4823,15 +4688,15 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
4823 | return -ENOMEM; | 4688 | return -ENOMEM; |
4824 | if (IS_SETLKW(cmd)) | 4689 | if (IS_SETLKW(cmd)) |
4825 | data->arg.block = 1; | 4690 | data->arg.block = 1; |
4826 | if (recovery_type > NFS_LOCK_NEW) { | ||
4827 | if (recovery_type == NFS_LOCK_RECLAIM) | ||
4828 | data->arg.reclaim = NFS_LOCK_RECLAIM; | ||
4829 | task_setup_data.callback_ops = &nfs4_recover_lock_ops; | ||
4830 | } | ||
4831 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); | 4691 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); |
4832 | msg.rpc_argp = &data->arg; | 4692 | msg.rpc_argp = &data->arg; |
4833 | msg.rpc_resp = &data->res; | 4693 | msg.rpc_resp = &data->res; |
4834 | task_setup_data.callback_data = data; | 4694 | task_setup_data.callback_data = data; |
4695 | if (recovery_type > NFS_LOCK_NEW) { | ||
4696 | if (recovery_type == NFS_LOCK_RECLAIM) | ||
4697 | data->arg.reclaim = NFS_LOCK_RECLAIM; | ||
4698 | nfs4_set_sequence_privileged(&data->arg.seq_args); | ||
4699 | } | ||
4835 | task = rpc_run_task(&task_setup_data); | 4700 | task = rpc_run_task(&task_setup_data); |
4836 | if (IS_ERR(task)) | 4701 | if (IS_ERR(task)) |
4837 | return PTR_ERR(task); | 4702 | return PTR_ERR(task); |
@@ -5100,15 +4965,6 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
5100 | nfs4_schedule_stateid_recovery(server, state); | 4965 | nfs4_schedule_stateid_recovery(server, state); |
5101 | err = 0; | 4966 | err = 0; |
5102 | goto out; | 4967 | goto out; |
5103 | case -EKEYEXPIRED: | ||
5104 | /* | ||
5105 | * User RPCSEC_GSS context has expired. | ||
5106 | * We cannot recover this stateid now, so | ||
5107 | * skip it and allow recovery thread to | ||
5108 | * proceed. | ||
5109 | */ | ||
5110 | err = 0; | ||
5111 | goto out; | ||
5112 | case -ENOMEM: | 4968 | case -ENOMEM: |
5113 | case -NFS4ERR_DENIED: | 4969 | case -NFS4ERR_DENIED: |
5114 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | 4970 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
@@ -5357,7 +5213,6 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred | |||
5357 | }; | 5213 | }; |
5358 | 5214 | ||
5359 | dprintk("--> %s\n", __func__); | 5215 | dprintk("--> %s\n", __func__); |
5360 | BUG_ON(clp == NULL); | ||
5361 | 5216 | ||
5362 | res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | 5217 | res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); |
5363 | if (unlikely(res.session == NULL)) { | 5218 | if (unlikely(res.session == NULL)) { |
@@ -5569,20 +5424,16 @@ struct nfs4_get_lease_time_data { | |||
5569 | static void nfs4_get_lease_time_prepare(struct rpc_task *task, | 5424 | static void nfs4_get_lease_time_prepare(struct rpc_task *task, |
5570 | void *calldata) | 5425 | void *calldata) |
5571 | { | 5426 | { |
5572 | int ret; | ||
5573 | struct nfs4_get_lease_time_data *data = | 5427 | struct nfs4_get_lease_time_data *data = |
5574 | (struct nfs4_get_lease_time_data *)calldata; | 5428 | (struct nfs4_get_lease_time_data *)calldata; |
5575 | 5429 | ||
5576 | dprintk("--> %s\n", __func__); | 5430 | dprintk("--> %s\n", __func__); |
5577 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
5578 | /* just setup sequence, do not trigger session recovery | 5431 | /* just setup sequence, do not trigger session recovery |
5579 | since we're invoked within one */ | 5432 | since we're invoked within one */ |
5580 | ret = nfs41_setup_sequence(data->clp->cl_session, | 5433 | nfs41_setup_sequence(data->clp->cl_session, |
5581 | &data->args->la_seq_args, | 5434 | &data->args->la_seq_args, |
5582 | &data->res->lr_seq_res, task); | 5435 | &data->res->lr_seq_res, |
5583 | 5436 | task); | |
5584 | BUG_ON(ret == -EAGAIN); | ||
5585 | rpc_call_start(task); | ||
5586 | dprintk("<-- %s\n", __func__); | 5437 | dprintk("<-- %s\n", __func__); |
5587 | } | 5438 | } |
5588 | 5439 | ||
@@ -5644,6 +5495,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
5644 | int status; | 5495 | int status; |
5645 | 5496 | ||
5646 | nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); | 5497 | nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); |
5498 | nfs4_set_sequence_privileged(&args.la_seq_args); | ||
5647 | dprintk("--> %s\n", __func__); | 5499 | dprintk("--> %s\n", __func__); |
5648 | task = rpc_run_task(&task_setup); | 5500 | task = rpc_run_task(&task_setup); |
5649 | 5501 | ||
@@ -5658,145 +5510,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
5658 | return status; | 5510 | return status; |
5659 | } | 5511 | } |
5660 | 5512 | ||
5661 | static struct nfs4_slot *nfs4_alloc_slots(u32 max_slots, gfp_t gfp_flags) | ||
5662 | { | ||
5663 | return kcalloc(max_slots, sizeof(struct nfs4_slot), gfp_flags); | ||
5664 | } | ||
5665 | |||
5666 | static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl, | ||
5667 | struct nfs4_slot *new, | ||
5668 | u32 max_slots, | ||
5669 | u32 ivalue) | ||
5670 | { | ||
5671 | struct nfs4_slot *old = NULL; | ||
5672 | u32 i; | ||
5673 | |||
5674 | spin_lock(&tbl->slot_tbl_lock); | ||
5675 | if (new) { | ||
5676 | old = tbl->slots; | ||
5677 | tbl->slots = new; | ||
5678 | tbl->max_slots = max_slots; | ||
5679 | } | ||
5680 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
5681 | for (i = 0; i < tbl->max_slots; i++) | ||
5682 | tbl->slots[i].seq_nr = ivalue; | ||
5683 | spin_unlock(&tbl->slot_tbl_lock); | ||
5684 | kfree(old); | ||
5685 | } | ||
5686 | |||
5687 | /* | ||
5688 | * (re)Initialise a slot table | ||
5689 | */ | ||
5690 | static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs, | ||
5691 | u32 ivalue) | ||
5692 | { | ||
5693 | struct nfs4_slot *new = NULL; | ||
5694 | int ret = -ENOMEM; | ||
5695 | |||
5696 | dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, | ||
5697 | max_reqs, tbl->max_slots); | ||
5698 | |||
5699 | /* Does the newly negotiated max_reqs match the existing slot table? */ | ||
5700 | if (max_reqs != tbl->max_slots) { | ||
5701 | new = nfs4_alloc_slots(max_reqs, GFP_NOFS); | ||
5702 | if (!new) | ||
5703 | goto out; | ||
5704 | } | ||
5705 | ret = 0; | ||
5706 | |||
5707 | nfs4_add_and_init_slots(tbl, new, max_reqs, ivalue); | ||
5708 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | ||
5709 | tbl, tbl->slots, tbl->max_slots); | ||
5710 | out: | ||
5711 | dprintk("<-- %s: return %d\n", __func__, ret); | ||
5712 | return ret; | ||
5713 | } | ||
5714 | |||
5715 | /* Destroy the slot table */ | ||
5716 | static void nfs4_destroy_slot_tables(struct nfs4_session *session) | ||
5717 | { | ||
5718 | if (session->fc_slot_table.slots != NULL) { | ||
5719 | kfree(session->fc_slot_table.slots); | ||
5720 | session->fc_slot_table.slots = NULL; | ||
5721 | } | ||
5722 | if (session->bc_slot_table.slots != NULL) { | ||
5723 | kfree(session->bc_slot_table.slots); | ||
5724 | session->bc_slot_table.slots = NULL; | ||
5725 | } | ||
5726 | return; | ||
5727 | } | ||
5728 | |||
5729 | /* | ||
5730 | * Initialize or reset the forechannel and backchannel tables | ||
5731 | */ | ||
5732 | static int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | ||
5733 | { | ||
5734 | struct nfs4_slot_table *tbl; | ||
5735 | int status; | ||
5736 | |||
5737 | dprintk("--> %s\n", __func__); | ||
5738 | /* Fore channel */ | ||
5739 | tbl = &ses->fc_slot_table; | ||
5740 | status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); | ||
5741 | if (status) /* -ENOMEM */ | ||
5742 | return status; | ||
5743 | /* Back channel */ | ||
5744 | tbl = &ses->bc_slot_table; | ||
5745 | status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0); | ||
5746 | if (status && tbl->slots == NULL) | ||
5747 | /* Fore and back channel share a connection so get | ||
5748 | * both slot tables or neither */ | ||
5749 | nfs4_destroy_slot_tables(ses); | ||
5750 | return status; | ||
5751 | } | ||
5752 | |||
5753 | struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | ||
5754 | { | ||
5755 | struct nfs4_session *session; | ||
5756 | struct nfs4_slot_table *tbl; | ||
5757 | |||
5758 | session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | ||
5759 | if (!session) | ||
5760 | return NULL; | ||
5761 | |||
5762 | tbl = &session->fc_slot_table; | ||
5763 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
5764 | spin_lock_init(&tbl->slot_tbl_lock); | ||
5765 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); | ||
5766 | init_completion(&tbl->complete); | ||
5767 | |||
5768 | tbl = &session->bc_slot_table; | ||
5769 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
5770 | spin_lock_init(&tbl->slot_tbl_lock); | ||
5771 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); | ||
5772 | init_completion(&tbl->complete); | ||
5773 | |||
5774 | session->session_state = 1<<NFS4_SESSION_INITING; | ||
5775 | |||
5776 | session->clp = clp; | ||
5777 | return session; | ||
5778 | } | ||
5779 | |||
5780 | void nfs4_destroy_session(struct nfs4_session *session) | ||
5781 | { | ||
5782 | struct rpc_xprt *xprt; | ||
5783 | struct rpc_cred *cred; | ||
5784 | |||
5785 | cred = nfs4_get_exchange_id_cred(session->clp); | ||
5786 | nfs4_proc_destroy_session(session, cred); | ||
5787 | if (cred) | ||
5788 | put_rpccred(cred); | ||
5789 | |||
5790 | rcu_read_lock(); | ||
5791 | xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); | ||
5792 | rcu_read_unlock(); | ||
5793 | dprintk("%s Destroy backchannel for xprt %p\n", | ||
5794 | __func__, xprt); | ||
5795 | xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); | ||
5796 | nfs4_destroy_slot_tables(session); | ||
5797 | kfree(session); | ||
5798 | } | ||
5799 | |||
5800 | /* | 5513 | /* |
5801 | * Initialize the values to be used by the client in CREATE_SESSION | 5514 | * Initialize the values to be used by the client in CREATE_SESSION |
5802 | * If nfs4_init_session set the fore channel request and response sizes, | 5515 | * If nfs4_init_session set the fore channel request and response sizes, |
@@ -5809,8 +5522,8 @@ void nfs4_destroy_session(struct nfs4_session *session) | |||
5809 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | 5522 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) |
5810 | { | 5523 | { |
5811 | struct nfs4_session *session = args->client->cl_session; | 5524 | struct nfs4_session *session = args->client->cl_session; |
5812 | unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz, | 5525 | unsigned int mxrqst_sz = session->fc_target_max_rqst_sz, |
5813 | mxresp_sz = session->fc_attrs.max_resp_sz; | 5526 | mxresp_sz = session->fc_target_max_resp_sz; |
5814 | 5527 | ||
5815 | if (mxrqst_sz == 0) | 5528 | if (mxrqst_sz == 0) |
5816 | mxrqst_sz = NFS_MAX_FILE_IO_SIZE; | 5529 | mxrqst_sz = NFS_MAX_FILE_IO_SIZE; |
@@ -5919,10 +5632,9 @@ static int _nfs4_proc_create_session(struct nfs_client *clp, | |||
5919 | 5632 | ||
5920 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 5633 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5921 | 5634 | ||
5922 | if (!status) | 5635 | if (!status) { |
5923 | /* Verify the session's negotiated channel_attrs values */ | 5636 | /* Verify the session's negotiated channel_attrs values */ |
5924 | status = nfs4_verify_channel_attrs(&args, session); | 5637 | status = nfs4_verify_channel_attrs(&args, session); |
5925 | if (!status) { | ||
5926 | /* Increment the clientid slot sequence id */ | 5638 | /* Increment the clientid slot sequence id */ |
5927 | clp->cl_seqid++; | 5639 | clp->cl_seqid++; |
5928 | } | 5640 | } |
@@ -5992,83 +5704,6 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, | |||
5992 | } | 5704 | } |
5993 | 5705 | ||
5994 | /* | 5706 | /* |
5995 | * With sessions, the client is not marked ready until after a | ||
5996 | * successful EXCHANGE_ID and CREATE_SESSION. | ||
5997 | * | ||
5998 | * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate | ||
5999 | * other versions of NFS can be tried. | ||
6000 | */ | ||
6001 | static int nfs41_check_session_ready(struct nfs_client *clp) | ||
6002 | { | ||
6003 | int ret; | ||
6004 | |||
6005 | if (clp->cl_cons_state == NFS_CS_SESSION_INITING) { | ||
6006 | ret = nfs4_client_recover_expired_lease(clp); | ||
6007 | if (ret) | ||
6008 | return ret; | ||
6009 | } | ||
6010 | if (clp->cl_cons_state < NFS_CS_READY) | ||
6011 | return -EPROTONOSUPPORT; | ||
6012 | smp_rmb(); | ||
6013 | return 0; | ||
6014 | } | ||
6015 | |||
6016 | int nfs4_init_session(struct nfs_server *server) | ||
6017 | { | ||
6018 | struct nfs_client *clp = server->nfs_client; | ||
6019 | struct nfs4_session *session; | ||
6020 | unsigned int rsize, wsize; | ||
6021 | |||
6022 | if (!nfs4_has_session(clp)) | ||
6023 | return 0; | ||
6024 | |||
6025 | session = clp->cl_session; | ||
6026 | spin_lock(&clp->cl_lock); | ||
6027 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { | ||
6028 | |||
6029 | rsize = server->rsize; | ||
6030 | if (rsize == 0) | ||
6031 | rsize = NFS_MAX_FILE_IO_SIZE; | ||
6032 | wsize = server->wsize; | ||
6033 | if (wsize == 0) | ||
6034 | wsize = NFS_MAX_FILE_IO_SIZE; | ||
6035 | |||
6036 | session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; | ||
6037 | session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; | ||
6038 | } | ||
6039 | spin_unlock(&clp->cl_lock); | ||
6040 | |||
6041 | return nfs41_check_session_ready(clp); | ||
6042 | } | ||
6043 | |||
6044 | int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time) | ||
6045 | { | ||
6046 | struct nfs4_session *session = clp->cl_session; | ||
6047 | int ret; | ||
6048 | |||
6049 | spin_lock(&clp->cl_lock); | ||
6050 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { | ||
6051 | /* | ||
6052 | * Do not set NFS_CS_CHECK_LEASE_TIME instead set the | ||
6053 | * DS lease to be equal to the MDS lease. | ||
6054 | */ | ||
6055 | clp->cl_lease_time = lease_time; | ||
6056 | clp->cl_last_renewal = jiffies; | ||
6057 | } | ||
6058 | spin_unlock(&clp->cl_lock); | ||
6059 | |||
6060 | ret = nfs41_check_session_ready(clp); | ||
6061 | if (ret) | ||
6062 | return ret; | ||
6063 | /* Test for the DS role */ | ||
6064 | if (!is_ds_client(clp)) | ||
6065 | return -ENODEV; | ||
6066 | return 0; | ||
6067 | } | ||
6068 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | ||
6069 | |||
6070 | |||
6071 | /* | ||
6072 | * Renew the cl_session lease. | 5707 | * Renew the cl_session lease. |
6073 | */ | 5708 | */ |
6074 | struct nfs4_sequence_data { | 5709 | struct nfs4_sequence_data { |
@@ -6133,9 +5768,7 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data) | |||
6133 | args = task->tk_msg.rpc_argp; | 5768 | args = task->tk_msg.rpc_argp; |
6134 | res = task->tk_msg.rpc_resp; | 5769 | res = task->tk_msg.rpc_resp; |
6135 | 5770 | ||
6136 | if (nfs41_setup_sequence(clp->cl_session, args, res, task)) | 5771 | nfs41_setup_sequence(clp->cl_session, args, res, task); |
6137 | return; | ||
6138 | rpc_call_start(task); | ||
6139 | } | 5772 | } |
6140 | 5773 | ||
6141 | static const struct rpc_call_ops nfs41_sequence_ops = { | 5774 | static const struct rpc_call_ops nfs41_sequence_ops = { |
@@ -6144,7 +5777,9 @@ static const struct rpc_call_ops nfs41_sequence_ops = { | |||
6144 | .rpc_release = nfs41_sequence_release, | 5777 | .rpc_release = nfs41_sequence_release, |
6145 | }; | 5778 | }; |
6146 | 5779 | ||
6147 | static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | 5780 | static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, |
5781 | struct rpc_cred *cred, | ||
5782 | bool is_privileged) | ||
6148 | { | 5783 | { |
6149 | struct nfs4_sequence_data *calldata; | 5784 | struct nfs4_sequence_data *calldata; |
6150 | struct rpc_message msg = { | 5785 | struct rpc_message msg = { |
@@ -6166,6 +5801,8 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ | |||
6166 | return ERR_PTR(-ENOMEM); | 5801 | return ERR_PTR(-ENOMEM); |
6167 | } | 5802 | } |
6168 | nfs41_init_sequence(&calldata->args, &calldata->res, 0); | 5803 | nfs41_init_sequence(&calldata->args, &calldata->res, 0); |
5804 | if (is_privileged) | ||
5805 | nfs4_set_sequence_privileged(&calldata->args); | ||
6169 | msg.rpc_argp = &calldata->args; | 5806 | msg.rpc_argp = &calldata->args; |
6170 | msg.rpc_resp = &calldata->res; | 5807 | msg.rpc_resp = &calldata->res; |
6171 | calldata->clp = clp; | 5808 | calldata->clp = clp; |
@@ -6181,7 +5818,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr | |||
6181 | 5818 | ||
6182 | if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) | 5819 | if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) |
6183 | return 0; | 5820 | return 0; |
6184 | task = _nfs41_proc_sequence(clp, cred); | 5821 | task = _nfs41_proc_sequence(clp, cred, false); |
6185 | if (IS_ERR(task)) | 5822 | if (IS_ERR(task)) |
6186 | ret = PTR_ERR(task); | 5823 | ret = PTR_ERR(task); |
6187 | else | 5824 | else |
@@ -6195,7 +5832,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | |||
6195 | struct rpc_task *task; | 5832 | struct rpc_task *task; |
6196 | int ret; | 5833 | int ret; |
6197 | 5834 | ||
6198 | task = _nfs41_proc_sequence(clp, cred); | 5835 | task = _nfs41_proc_sequence(clp, cred, true); |
6199 | if (IS_ERR(task)) { | 5836 | if (IS_ERR(task)) { |
6200 | ret = PTR_ERR(task); | 5837 | ret = PTR_ERR(task); |
6201 | goto out; | 5838 | goto out; |
@@ -6224,13 +5861,10 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data) | |||
6224 | { | 5861 | { |
6225 | struct nfs4_reclaim_complete_data *calldata = data; | 5862 | struct nfs4_reclaim_complete_data *calldata = data; |
6226 | 5863 | ||
6227 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | 5864 | nfs41_setup_sequence(calldata->clp->cl_session, |
6228 | if (nfs41_setup_sequence(calldata->clp->cl_session, | 5865 | &calldata->arg.seq_args, |
6229 | &calldata->arg.seq_args, | 5866 | &calldata->res.seq_res, |
6230 | &calldata->res.seq_res, task)) | 5867 | task); |
6231 | return; | ||
6232 | |||
6233 | rpc_call_start(task); | ||
6234 | } | 5868 | } |
6235 | 5869 | ||
6236 | static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp) | 5870 | static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp) |
@@ -6307,6 +5941,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
6307 | calldata->arg.one_fs = 0; | 5941 | calldata->arg.one_fs = 0; |
6308 | 5942 | ||
6309 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); | 5943 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); |
5944 | nfs4_set_sequence_privileged(&calldata->arg.seq_args); | ||
6310 | msg.rpc_argp = &calldata->arg; | 5945 | msg.rpc_argp = &calldata->arg; |
6311 | msg.rpc_resp = &calldata->res; | 5946 | msg.rpc_resp = &calldata->res; |
6312 | task_setup_data.callback_data = calldata; | 5947 | task_setup_data.callback_data = calldata; |
@@ -6330,6 +5965,7 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | |||
6330 | { | 5965 | { |
6331 | struct nfs4_layoutget *lgp = calldata; | 5966 | struct nfs4_layoutget *lgp = calldata; |
6332 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | 5967 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); |
5968 | struct nfs4_session *session = nfs4_get_session(server); | ||
6333 | 5969 | ||
6334 | dprintk("--> %s\n", __func__); | 5970 | dprintk("--> %s\n", __func__); |
6335 | /* Note the is a race here, where a CB_LAYOUTRECALL can come in | 5971 | /* Note the is a race here, where a CB_LAYOUTRECALL can come in |
@@ -6337,16 +5973,14 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | |||
6337 | * However, that is not so catastrophic, and there seems | 5973 | * However, that is not so catastrophic, and there seems |
6338 | * to be no way to prevent it completely. | 5974 | * to be no way to prevent it completely. |
6339 | */ | 5975 | */ |
6340 | if (nfs4_setup_sequence(server, &lgp->args.seq_args, | 5976 | if (nfs41_setup_sequence(session, &lgp->args.seq_args, |
6341 | &lgp->res.seq_res, task)) | 5977 | &lgp->res.seq_res, task)) |
6342 | return; | 5978 | return; |
6343 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, | 5979 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, |
6344 | NFS_I(lgp->args.inode)->layout, | 5980 | NFS_I(lgp->args.inode)->layout, |
6345 | lgp->args.ctx->state)) { | 5981 | lgp->args.ctx->state)) { |
6346 | rpc_exit(task, NFS4_OK); | 5982 | rpc_exit(task, NFS4_OK); |
6347 | return; | ||
6348 | } | 5983 | } |
6349 | rpc_call_start(task); | ||
6350 | } | 5984 | } |
6351 | 5985 | ||
6352 | static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | 5986 | static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) |
@@ -6359,7 +5993,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
6359 | 5993 | ||
6360 | dprintk("--> %s\n", __func__); | 5994 | dprintk("--> %s\n", __func__); |
6361 | 5995 | ||
6362 | if (!nfs4_sequence_done(task, &lgp->res.seq_res)) | 5996 | if (!nfs41_sequence_done(task, &lgp->res.seq_res)) |
6363 | goto out; | 5997 | goto out; |
6364 | 5998 | ||
6365 | switch (task->tk_status) { | 5999 | switch (task->tk_status) { |
@@ -6510,10 +6144,10 @@ nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata) | |||
6510 | struct nfs4_layoutreturn *lrp = calldata; | 6144 | struct nfs4_layoutreturn *lrp = calldata; |
6511 | 6145 | ||
6512 | dprintk("--> %s\n", __func__); | 6146 | dprintk("--> %s\n", __func__); |
6513 | if (nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args, | 6147 | nfs41_setup_sequence(lrp->clp->cl_session, |
6514 | &lrp->res.seq_res, task)) | 6148 | &lrp->args.seq_args, |
6515 | return; | 6149 | &lrp->res.seq_res, |
6516 | rpc_call_start(task); | 6150 | task); |
6517 | } | 6151 | } |
6518 | 6152 | ||
6519 | static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | 6153 | static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) |
@@ -6523,7 +6157,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
6523 | 6157 | ||
6524 | dprintk("--> %s\n", __func__); | 6158 | dprintk("--> %s\n", __func__); |
6525 | 6159 | ||
6526 | if (!nfs4_sequence_done(task, &lrp->res.seq_res)) | 6160 | if (!nfs41_sequence_done(task, &lrp->res.seq_res)) |
6527 | return; | 6161 | return; |
6528 | 6162 | ||
6529 | server = NFS_SERVER(lrp->args.inode); | 6163 | server = NFS_SERVER(lrp->args.inode); |
@@ -6672,11 +6306,12 @@ static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata) | |||
6672 | { | 6306 | { |
6673 | struct nfs4_layoutcommit_data *data = calldata; | 6307 | struct nfs4_layoutcommit_data *data = calldata; |
6674 | struct nfs_server *server = NFS_SERVER(data->args.inode); | 6308 | struct nfs_server *server = NFS_SERVER(data->args.inode); |
6309 | struct nfs4_session *session = nfs4_get_session(server); | ||
6675 | 6310 | ||
6676 | if (nfs4_setup_sequence(server, &data->args.seq_args, | 6311 | nfs41_setup_sequence(session, |
6677 | &data->res.seq_res, task)) | 6312 | &data->args.seq_args, |
6678 | return; | 6313 | &data->res.seq_res, |
6679 | rpc_call_start(task); | 6314 | task); |
6680 | } | 6315 | } |
6681 | 6316 | ||
6682 | static void | 6317 | static void |
@@ -6685,7 +6320,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | |||
6685 | struct nfs4_layoutcommit_data *data = calldata; | 6320 | struct nfs4_layoutcommit_data *data = calldata; |
6686 | struct nfs_server *server = NFS_SERVER(data->args.inode); | 6321 | struct nfs_server *server = NFS_SERVER(data->args.inode); |
6687 | 6322 | ||
6688 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | 6323 | if (!nfs41_sequence_done(task, &data->res.seq_res)) |
6689 | return; | 6324 | return; |
6690 | 6325 | ||
6691 | switch (task->tk_status) { /* Just ignore these failures */ | 6326 | switch (task->tk_status) { /* Just ignore these failures */ |
@@ -6873,7 +6508,9 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6873 | 6508 | ||
6874 | dprintk("NFS call test_stateid %p\n", stateid); | 6509 | dprintk("NFS call test_stateid %p\n", stateid); |
6875 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 6510 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); |
6876 | status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); | 6511 | nfs4_set_sequence_privileged(&args.seq_args); |
6512 | status = nfs4_call_sync_sequence(server->client, server, &msg, | ||
6513 | &args.seq_args, &res.seq_res); | ||
6877 | if (status != NFS_OK) { | 6514 | if (status != NFS_OK) { |
6878 | dprintk("NFS reply test_stateid: failed, %d\n", status); | 6515 | dprintk("NFS reply test_stateid: failed, %d\n", status); |
6879 | return status; | 6516 | return status; |
@@ -6920,8 +6557,9 @@ static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6920 | 6557 | ||
6921 | dprintk("NFS call free_stateid %p\n", stateid); | 6558 | dprintk("NFS call free_stateid %p\n", stateid); |
6922 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 6559 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); |
6560 | nfs4_set_sequence_privileged(&args.seq_args); | ||
6923 | status = nfs4_call_sync_sequence(server->client, server, &msg, | 6561 | status = nfs4_call_sync_sequence(server->client, server, &msg, |
6924 | &args.seq_args, &res.seq_res, 1); | 6562 | &args.seq_args, &res.seq_res); |
6925 | dprintk("NFS reply free_stateid: %d\n", status); | 6563 | dprintk("NFS reply free_stateid: %d\n", status); |
6926 | return status; | 6564 | return status; |
6927 | } | 6565 | } |
@@ -7041,7 +6679,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
7041 | #if defined(CONFIG_NFS_V4_1) | 6679 | #if defined(CONFIG_NFS_V4_1) |
7042 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | 6680 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { |
7043 | .minor_version = 1, | 6681 | .minor_version = 1, |
7044 | .call_sync = _nfs4_call_sync_session, | 6682 | .call_sync = nfs4_call_sync_sequence, |
7045 | .match_stateid = nfs41_match_stateid, | 6683 | .match_stateid = nfs41_match_stateid, |
7046 | .find_root_sec = nfs41_find_root_sec, | 6684 | .find_root_sec = nfs41_find_root_sec, |
7047 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 6685 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |