diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 687 |
1 files changed, 443 insertions, 244 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f0c849c98fe4..b76dd0efae75 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -72,18 +72,21 @@ | |||
72 | 72 | ||
73 | #define NFS4_MAX_LOOP_ON_RECOVER (10) | 73 | #define NFS4_MAX_LOOP_ON_RECOVER (10) |
74 | 74 | ||
75 | static unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE; | ||
76 | |||
75 | struct nfs4_opendata; | 77 | struct nfs4_opendata; |
76 | static int _nfs4_proc_open(struct nfs4_opendata *data); | 78 | static int _nfs4_proc_open(struct nfs4_opendata *data); |
77 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 79 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
78 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 80 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
79 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 81 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); |
82 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | ||
80 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 83 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); |
81 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 84 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
82 | struct nfs_fattr *fattr, struct iattr *sattr, | 85 | struct nfs_fattr *fattr, struct iattr *sattr, |
83 | struct nfs4_state *state); | 86 | struct nfs4_state *state); |
84 | #ifdef CONFIG_NFS_V4_1 | 87 | #ifdef CONFIG_NFS_V4_1 |
85 | static int nfs41_test_stateid(struct nfs_server *, struct nfs4_state *); | 88 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *); |
86 | static int nfs41_free_stateid(struct nfs_server *, struct nfs4_state *); | 89 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *); |
87 | #endif | 90 | #endif |
88 | /* Prevent leaks of NFSv4 errors into userland */ | 91 | /* Prevent leaks of NFSv4 errors into userland */ |
89 | static int nfs4_map_errors(int err) | 92 | static int nfs4_map_errors(int err) |
@@ -259,15 +262,28 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
259 | { | 262 | { |
260 | struct nfs_client *clp = server->nfs_client; | 263 | struct nfs_client *clp = server->nfs_client; |
261 | struct nfs4_state *state = exception->state; | 264 | struct nfs4_state *state = exception->state; |
265 | struct inode *inode = exception->inode; | ||
262 | int ret = errorcode; | 266 | int ret = errorcode; |
263 | 267 | ||
264 | exception->retry = 0; | 268 | exception->retry = 0; |
265 | switch(errorcode) { | 269 | switch(errorcode) { |
266 | case 0: | 270 | case 0: |
267 | return 0; | 271 | return 0; |
272 | case -NFS4ERR_OPENMODE: | ||
273 | if (nfs_have_delegation(inode, FMODE_READ)) { | ||
274 | nfs_inode_return_delegation(inode); | ||
275 | exception->retry = 1; | ||
276 | return 0; | ||
277 | } | ||
278 | if (state == NULL) | ||
279 | break; | ||
280 | nfs4_schedule_stateid_recovery(server, state); | ||
281 | goto wait_on_recovery; | ||
282 | case -NFS4ERR_DELEG_REVOKED: | ||
268 | case -NFS4ERR_ADMIN_REVOKED: | 283 | case -NFS4ERR_ADMIN_REVOKED: |
269 | case -NFS4ERR_BAD_STATEID: | 284 | case -NFS4ERR_BAD_STATEID: |
270 | case -NFS4ERR_OPENMODE: | 285 | if (state != NULL) |
286 | nfs_remove_bad_delegation(state->inode); | ||
271 | if (state == NULL) | 287 | if (state == NULL) |
272 | break; | 288 | break; |
273 | nfs4_schedule_stateid_recovery(server, state); | 289 | nfs4_schedule_stateid_recovery(server, state); |
@@ -360,16 +376,14 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp | |||
360 | * When updating highest_used_slotid there may be "holes" in the bitmap | 376 | * When updating highest_used_slotid there may be "holes" in the bitmap |
361 | * so we need to scan down from highest_used_slotid to 0 looking for the now | 377 | * so we need to scan down from highest_used_slotid to 0 looking for the now |
362 | * highest slotid in use. | 378 | * highest slotid in use. |
363 | * If none found, highest_used_slotid is set to -1. | 379 | * If none found, highest_used_slotid is set to NFS4_NO_SLOT. |
364 | * | 380 | * |
365 | * Must be called while holding tbl->slot_tbl_lock | 381 | * Must be called while holding tbl->slot_tbl_lock |
366 | */ | 382 | */ |
367 | static void | 383 | static void |
368 | nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid) | 384 | nfs4_free_slot(struct nfs4_slot_table *tbl, u32 slotid) |
369 | { | 385 | { |
370 | int slotid = free_slotid; | 386 | BUG_ON(slotid >= NFS4_MAX_SLOT_TABLE); |
371 | |||
372 | BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE); | ||
373 | /* clear used bit in bitmap */ | 387 | /* clear used bit in bitmap */ |
374 | __clear_bit(slotid, tbl->used_slots); | 388 | __clear_bit(slotid, tbl->used_slots); |
375 | 389 | ||
@@ -379,10 +393,16 @@ nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid) | |||
379 | if (slotid < tbl->max_slots) | 393 | if (slotid < tbl->max_slots) |
380 | tbl->highest_used_slotid = slotid; | 394 | tbl->highest_used_slotid = slotid; |
381 | else | 395 | else |
382 | tbl->highest_used_slotid = -1; | 396 | tbl->highest_used_slotid = NFS4_NO_SLOT; |
383 | } | 397 | } |
384 | dprintk("%s: free_slotid %u highest_used_slotid %d\n", __func__, | 398 | dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, |
385 | free_slotid, tbl->highest_used_slotid); | 399 | slotid, tbl->highest_used_slotid); |
400 | } | ||
401 | |||
402 | bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy) | ||
403 | { | ||
404 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
405 | return true; | ||
386 | } | 406 | } |
387 | 407 | ||
388 | /* | 408 | /* |
@@ -390,16 +410,13 @@ nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid) | |||
390 | */ | 410 | */ |
391 | static void nfs4_check_drain_fc_complete(struct nfs4_session *ses) | 411 | static void nfs4_check_drain_fc_complete(struct nfs4_session *ses) |
392 | { | 412 | { |
393 | struct rpc_task *task; | ||
394 | |||
395 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { | 413 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { |
396 | task = rpc_wake_up_next(&ses->fc_slot_table.slot_tbl_waitq); | 414 | rpc_wake_up_first(&ses->fc_slot_table.slot_tbl_waitq, |
397 | if (task) | 415 | nfs4_set_task_privileged, NULL); |
398 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
399 | return; | 416 | return; |
400 | } | 417 | } |
401 | 418 | ||
402 | if (ses->fc_slot_table.highest_used_slotid != -1) | 419 | if (ses->fc_slot_table.highest_used_slotid != NFS4_NO_SLOT) |
403 | return; | 420 | return; |
404 | 421 | ||
405 | dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__); | 422 | dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__); |
@@ -412,7 +429,7 @@ static void nfs4_check_drain_fc_complete(struct nfs4_session *ses) | |||
412 | void nfs4_check_drain_bc_complete(struct nfs4_session *ses) | 429 | void nfs4_check_drain_bc_complete(struct nfs4_session *ses) |
413 | { | 430 | { |
414 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) || | 431 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) || |
415 | ses->bc_slot_table.highest_used_slotid != -1) | 432 | ses->bc_slot_table.highest_used_slotid != NFS4_NO_SLOT) |
416 | return; | 433 | return; |
417 | dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__); | 434 | dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__); |
418 | complete(&ses->bc_slot_table.complete); | 435 | complete(&ses->bc_slot_table.complete); |
@@ -507,25 +524,25 @@ static int nfs4_sequence_done(struct rpc_task *task, | |||
507 | * nfs4_find_slot looks for an unset bit in the used_slots bitmap. | 524 | * nfs4_find_slot looks for an unset bit in the used_slots bitmap. |
508 | * If found, we mark the slot as used, update the highest_used_slotid, | 525 | * If found, we mark the slot as used, update the highest_used_slotid, |
509 | * and respectively set up the sequence operation args. | 526 | * and respectively set up the sequence operation args. |
510 | * The slot number is returned if found, or NFS4_MAX_SLOT_TABLE otherwise. | 527 | * The slot number is returned if found, or NFS4_NO_SLOT otherwise. |
511 | * | 528 | * |
512 | * Note: must be called with under the slot_tbl_lock. | 529 | * Note: must be called with under the slot_tbl_lock. |
513 | */ | 530 | */ |
514 | static u8 | 531 | static u32 |
515 | nfs4_find_slot(struct nfs4_slot_table *tbl) | 532 | nfs4_find_slot(struct nfs4_slot_table *tbl) |
516 | { | 533 | { |
517 | int slotid; | 534 | u32 slotid; |
518 | u8 ret_id = NFS4_MAX_SLOT_TABLE; | 535 | u32 ret_id = NFS4_NO_SLOT; |
519 | BUILD_BUG_ON((u8)NFS4_MAX_SLOT_TABLE != (int)NFS4_MAX_SLOT_TABLE); | ||
520 | 536 | ||
521 | dprintk("--> %s used_slots=%04lx highest_used=%d max_slots=%d\n", | 537 | dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n", |
522 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, | 538 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, |
523 | tbl->max_slots); | 539 | tbl->max_slots); |
524 | slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots); | 540 | slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots); |
525 | if (slotid >= tbl->max_slots) | 541 | if (slotid >= tbl->max_slots) |
526 | goto out; | 542 | goto out; |
527 | __set_bit(slotid, tbl->used_slots); | 543 | __set_bit(slotid, tbl->used_slots); |
528 | if (slotid > tbl->highest_used_slotid) | 544 | if (slotid > tbl->highest_used_slotid || |
545 | tbl->highest_used_slotid == NFS4_NO_SLOT) | ||
529 | tbl->highest_used_slotid = slotid; | 546 | tbl->highest_used_slotid = slotid; |
530 | ret_id = slotid; | 547 | ret_id = slotid; |
531 | out: | 548 | out: |
@@ -534,15 +551,25 @@ out: | |||
534 | return ret_id; | 551 | return ret_id; |
535 | } | 552 | } |
536 | 553 | ||
554 | static void nfs41_init_sequence(struct nfs4_sequence_args *args, | ||
555 | struct nfs4_sequence_res *res, int cache_reply) | ||
556 | { | ||
557 | args->sa_session = NULL; | ||
558 | args->sa_cache_this = 0; | ||
559 | if (cache_reply) | ||
560 | args->sa_cache_this = 1; | ||
561 | res->sr_session = NULL; | ||
562 | res->sr_slot = NULL; | ||
563 | } | ||
564 | |||
537 | int nfs41_setup_sequence(struct nfs4_session *session, | 565 | int nfs41_setup_sequence(struct nfs4_session *session, |
538 | struct nfs4_sequence_args *args, | 566 | struct nfs4_sequence_args *args, |
539 | struct nfs4_sequence_res *res, | 567 | struct nfs4_sequence_res *res, |
540 | int cache_reply, | ||
541 | struct rpc_task *task) | 568 | struct rpc_task *task) |
542 | { | 569 | { |
543 | struct nfs4_slot *slot; | 570 | struct nfs4_slot *slot; |
544 | struct nfs4_slot_table *tbl; | 571 | struct nfs4_slot_table *tbl; |
545 | u8 slotid; | 572 | u32 slotid; |
546 | 573 | ||
547 | dprintk("--> %s\n", __func__); | 574 | dprintk("--> %s\n", __func__); |
548 | /* slot already allocated? */ | 575 | /* slot already allocated? */ |
@@ -570,7 +597,7 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
570 | } | 597 | } |
571 | 598 | ||
572 | slotid = nfs4_find_slot(tbl); | 599 | slotid = nfs4_find_slot(tbl); |
573 | if (slotid == NFS4_MAX_SLOT_TABLE) { | 600 | if (slotid == NFS4_NO_SLOT) { |
574 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | 601 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); |
575 | spin_unlock(&tbl->slot_tbl_lock); | 602 | spin_unlock(&tbl->slot_tbl_lock); |
576 | dprintk("<-- %s: no free slots\n", __func__); | 603 | dprintk("<-- %s: no free slots\n", __func__); |
@@ -582,7 +609,6 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
582 | slot = tbl->slots + slotid; | 609 | slot = tbl->slots + slotid; |
583 | args->sa_session = session; | 610 | args->sa_session = session; |
584 | args->sa_slotid = slotid; | 611 | args->sa_slotid = slotid; |
585 | args->sa_cache_this = cache_reply; | ||
586 | 612 | ||
587 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); | 613 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); |
588 | 614 | ||
@@ -602,24 +628,19 @@ EXPORT_SYMBOL_GPL(nfs41_setup_sequence); | |||
602 | int nfs4_setup_sequence(const struct nfs_server *server, | 628 | int nfs4_setup_sequence(const struct nfs_server *server, |
603 | struct nfs4_sequence_args *args, | 629 | struct nfs4_sequence_args *args, |
604 | struct nfs4_sequence_res *res, | 630 | struct nfs4_sequence_res *res, |
605 | int cache_reply, | ||
606 | struct rpc_task *task) | 631 | struct rpc_task *task) |
607 | { | 632 | { |
608 | struct nfs4_session *session = nfs4_get_session(server); | 633 | struct nfs4_session *session = nfs4_get_session(server); |
609 | int ret = 0; | 634 | int ret = 0; |
610 | 635 | ||
611 | if (session == NULL) { | 636 | if (session == NULL) |
612 | args->sa_session = NULL; | ||
613 | res->sr_session = NULL; | ||
614 | goto out; | 637 | goto out; |
615 | } | ||
616 | 638 | ||
617 | dprintk("--> %s clp %p session %p sr_slot %td\n", | 639 | dprintk("--> %s clp %p session %p sr_slot %td\n", |
618 | __func__, session->clp, session, res->sr_slot ? | 640 | __func__, session->clp, session, res->sr_slot ? |
619 | res->sr_slot - session->fc_slot_table.slots : -1); | 641 | res->sr_slot - session->fc_slot_table.slots : -1); |
620 | 642 | ||
621 | ret = nfs41_setup_sequence(session, args, res, cache_reply, | 643 | ret = nfs41_setup_sequence(session, args, res, task); |
622 | task); | ||
623 | out: | 644 | out: |
624 | dprintk("<-- %s status=%d\n", __func__, ret); | 645 | dprintk("<-- %s status=%d\n", __func__, ret); |
625 | return ret; | 646 | return ret; |
@@ -629,7 +650,6 @@ struct nfs41_call_sync_data { | |||
629 | const struct nfs_server *seq_server; | 650 | const struct nfs_server *seq_server; |
630 | struct nfs4_sequence_args *seq_args; | 651 | struct nfs4_sequence_args *seq_args; |
631 | struct nfs4_sequence_res *seq_res; | 652 | struct nfs4_sequence_res *seq_res; |
632 | int cache_reply; | ||
633 | }; | 653 | }; |
634 | 654 | ||
635 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | 655 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) |
@@ -639,7 +659,7 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | |||
639 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); | 659 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); |
640 | 660 | ||
641 | if (nfs4_setup_sequence(data->seq_server, data->seq_args, | 661 | if (nfs4_setup_sequence(data->seq_server, data->seq_args, |
642 | data->seq_res, data->cache_reply, task)) | 662 | data->seq_res, task)) |
643 | return; | 663 | return; |
644 | rpc_call_start(task); | 664 | rpc_call_start(task); |
645 | } | 665 | } |
@@ -657,12 +677,12 @@ static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) | |||
657 | nfs41_sequence_done(task, data->seq_res); | 677 | nfs41_sequence_done(task, data->seq_res); |
658 | } | 678 | } |
659 | 679 | ||
660 | struct rpc_call_ops nfs41_call_sync_ops = { | 680 | static const struct rpc_call_ops nfs41_call_sync_ops = { |
661 | .rpc_call_prepare = nfs41_call_sync_prepare, | 681 | .rpc_call_prepare = nfs41_call_sync_prepare, |
662 | .rpc_call_done = nfs41_call_sync_done, | 682 | .rpc_call_done = nfs41_call_sync_done, |
663 | }; | 683 | }; |
664 | 684 | ||
665 | struct rpc_call_ops nfs41_call_priv_sync_ops = { | 685 | static const struct rpc_call_ops nfs41_call_priv_sync_ops = { |
666 | .rpc_call_prepare = nfs41_call_priv_sync_prepare, | 686 | .rpc_call_prepare = nfs41_call_priv_sync_prepare, |
667 | .rpc_call_done = nfs41_call_sync_done, | 687 | .rpc_call_done = nfs41_call_sync_done, |
668 | }; | 688 | }; |
@@ -672,7 +692,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
672 | struct rpc_message *msg, | 692 | struct rpc_message *msg, |
673 | struct nfs4_sequence_args *args, | 693 | struct nfs4_sequence_args *args, |
674 | struct nfs4_sequence_res *res, | 694 | struct nfs4_sequence_res *res, |
675 | int cache_reply, | ||
676 | int privileged) | 695 | int privileged) |
677 | { | 696 | { |
678 | int ret; | 697 | int ret; |
@@ -681,7 +700,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
681 | .seq_server = server, | 700 | .seq_server = server, |
682 | .seq_args = args, | 701 | .seq_args = args, |
683 | .seq_res = res, | 702 | .seq_res = res, |
684 | .cache_reply = cache_reply, | ||
685 | }; | 703 | }; |
686 | struct rpc_task_setup task_setup = { | 704 | struct rpc_task_setup task_setup = { |
687 | .rpc_client = clnt, | 705 | .rpc_client = clnt, |
@@ -690,7 +708,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
690 | .callback_data = &data | 708 | .callback_data = &data |
691 | }; | 709 | }; |
692 | 710 | ||
693 | res->sr_slot = NULL; | ||
694 | if (privileged) | 711 | if (privileged) |
695 | task_setup.callback_ops = &nfs41_call_priv_sync_ops; | 712 | task_setup.callback_ops = &nfs41_call_priv_sync_ops; |
696 | task = rpc_run_task(&task_setup); | 713 | task = rpc_run_task(&task_setup); |
@@ -710,10 +727,17 @@ int _nfs4_call_sync_session(struct rpc_clnt *clnt, | |||
710 | struct nfs4_sequence_res *res, | 727 | struct nfs4_sequence_res *res, |
711 | int cache_reply) | 728 | int cache_reply) |
712 | { | 729 | { |
713 | return nfs4_call_sync_sequence(clnt, server, msg, args, res, cache_reply, 0); | 730 | nfs41_init_sequence(args, res, cache_reply); |
731 | return nfs4_call_sync_sequence(clnt, server, msg, args, res, 0); | ||
714 | } | 732 | } |
715 | 733 | ||
716 | #else | 734 | #else |
735 | static inline | ||
736 | void nfs41_init_sequence(struct nfs4_sequence_args *args, | ||
737 | struct nfs4_sequence_res *res, int cache_reply) | ||
738 | { | ||
739 | } | ||
740 | |||
717 | static int nfs4_sequence_done(struct rpc_task *task, | 741 | static int nfs4_sequence_done(struct rpc_task *task, |
718 | struct nfs4_sequence_res *res) | 742 | struct nfs4_sequence_res *res) |
719 | { | 743 | { |
@@ -728,7 +752,7 @@ int _nfs4_call_sync(struct rpc_clnt *clnt, | |||
728 | struct nfs4_sequence_res *res, | 752 | struct nfs4_sequence_res *res, |
729 | int cache_reply) | 753 | int cache_reply) |
730 | { | 754 | { |
731 | args->sa_session = res->sr_session = NULL; | 755 | nfs41_init_sequence(args, res, cache_reply); |
732 | return rpc_call_sync(clnt, msg, 0); | 756 | return rpc_call_sync(clnt, msg, 0); |
733 | } | 757 | } |
734 | 758 | ||
@@ -815,20 +839,22 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
815 | p->o_arg.open_flags = flags; | 839 | p->o_arg.open_flags = flags; |
816 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); | 840 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); |
817 | p->o_arg.clientid = server->nfs_client->cl_clientid; | 841 | p->o_arg.clientid = server->nfs_client->cl_clientid; |
818 | p->o_arg.id = sp->so_owner_id.id; | 842 | p->o_arg.id = sp->so_seqid.owner_id; |
819 | p->o_arg.name = &dentry->d_name; | 843 | p->o_arg.name = &dentry->d_name; |
820 | p->o_arg.server = server; | 844 | p->o_arg.server = server; |
821 | p->o_arg.bitmask = server->attr_bitmask; | 845 | p->o_arg.bitmask = server->attr_bitmask; |
822 | p->o_arg.dir_bitmask = server->cache_consistency_bitmask; | 846 | p->o_arg.dir_bitmask = server->cache_consistency_bitmask; |
823 | p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; | 847 | p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; |
824 | if (flags & O_CREAT) { | 848 | if (attrs != NULL && attrs->ia_valid != 0) { |
825 | u32 *s; | 849 | __be32 verf[2]; |
826 | 850 | ||
827 | p->o_arg.u.attrs = &p->attrs; | 851 | p->o_arg.u.attrs = &p->attrs; |
828 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); | 852 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); |
829 | s = (u32 *) p->o_arg.u.verifier.data; | 853 | |
830 | s[0] = jiffies; | 854 | verf[0] = jiffies; |
831 | s[1] = current->pid; | 855 | verf[1] = current->pid; |
856 | memcpy(p->o_arg.u.verifier.data, verf, | ||
857 | sizeof(p->o_arg.u.verifier.data)); | ||
832 | } | 858 | } |
833 | p->c_arg.fh = &p->o_res.fh; | 859 | p->c_arg.fh = &p->o_res.fh; |
834 | p->c_arg.stateid = &p->o_res.stateid; | 860 | p->c_arg.stateid = &p->o_res.stateid; |
@@ -878,7 +904,7 @@ static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode | |||
878 | { | 904 | { |
879 | int ret = 0; | 905 | int ret = 0; |
880 | 906 | ||
881 | if (open_mode & O_EXCL) | 907 | if (open_mode & (O_EXCL|O_TRUNC)) |
882 | goto out; | 908 | goto out; |
883 | switch (mode & (FMODE_READ|FMODE_WRITE)) { | 909 | switch (mode & (FMODE_READ|FMODE_WRITE)) { |
884 | case FMODE_READ: | 910 | case FMODE_READ: |
@@ -927,8 +953,8 @@ static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode) | |||
927 | static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode) | 953 | static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode) |
928 | { | 954 | { |
929 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) | 955 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) |
930 | memcpy(state->stateid.data, stateid->data, sizeof(state->stateid.data)); | 956 | nfs4_stateid_copy(&state->stateid, stateid); |
931 | memcpy(state->open_stateid.data, stateid->data, sizeof(state->open_stateid.data)); | 957 | nfs4_stateid_copy(&state->open_stateid, stateid); |
932 | switch (fmode) { | 958 | switch (fmode) { |
933 | case FMODE_READ: | 959 | case FMODE_READ: |
934 | set_bit(NFS_O_RDONLY_STATE, &state->flags); | 960 | set_bit(NFS_O_RDONLY_STATE, &state->flags); |
@@ -956,7 +982,7 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s | |||
956 | */ | 982 | */ |
957 | write_seqlock(&state->seqlock); | 983 | write_seqlock(&state->seqlock); |
958 | if (deleg_stateid != NULL) { | 984 | if (deleg_stateid != NULL) { |
959 | memcpy(state->stateid.data, deleg_stateid->data, sizeof(state->stateid.data)); | 985 | nfs4_stateid_copy(&state->stateid, deleg_stateid); |
960 | set_bit(NFS_DELEGATED_STATE, &state->flags); | 986 | set_bit(NFS_DELEGATED_STATE, &state->flags); |
961 | } | 987 | } |
962 | if (open_stateid != NULL) | 988 | if (open_stateid != NULL) |
@@ -987,7 +1013,7 @@ static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stat | |||
987 | 1013 | ||
988 | if (delegation == NULL) | 1014 | if (delegation == NULL) |
989 | delegation = &deleg_cur->stateid; | 1015 | delegation = &deleg_cur->stateid; |
990 | else if (memcmp(deleg_cur->stateid.data, delegation->data, NFS4_STATEID_SIZE) != 0) | 1016 | else if (!nfs4_stateid_match(&deleg_cur->stateid, delegation)) |
991 | goto no_delegation_unlock; | 1017 | goto no_delegation_unlock; |
992 | 1018 | ||
993 | nfs_mark_delegation_referenced(deleg_cur); | 1019 | nfs_mark_delegation_referenced(deleg_cur); |
@@ -1026,7 +1052,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | |||
1026 | struct nfs4_state *state = opendata->state; | 1052 | struct nfs4_state *state = opendata->state; |
1027 | struct nfs_inode *nfsi = NFS_I(state->inode); | 1053 | struct nfs_inode *nfsi = NFS_I(state->inode); |
1028 | struct nfs_delegation *delegation; | 1054 | struct nfs_delegation *delegation; |
1029 | int open_mode = opendata->o_arg.open_flags & O_EXCL; | 1055 | int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC); |
1030 | fmode_t fmode = opendata->o_arg.fmode; | 1056 | fmode_t fmode = opendata->o_arg.fmode; |
1031 | nfs4_stateid stateid; | 1057 | nfs4_stateid stateid; |
1032 | int ret = -EAGAIN; | 1058 | int ret = -EAGAIN; |
@@ -1048,7 +1074,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | |||
1048 | break; | 1074 | break; |
1049 | } | 1075 | } |
1050 | /* Save the delegation */ | 1076 | /* Save the delegation */ |
1051 | memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data)); | 1077 | nfs4_stateid_copy(&stateid, &delegation->stateid); |
1052 | rcu_read_unlock(); | 1078 | rcu_read_unlock(); |
1053 | ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); | 1079 | ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); |
1054 | if (ret != 0) | 1080 | if (ret != 0) |
@@ -1090,6 +1116,7 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data | |||
1090 | if (state == NULL) | 1116 | if (state == NULL) |
1091 | goto err_put_inode; | 1117 | goto err_put_inode; |
1092 | if (data->o_res.delegation_type != 0) { | 1118 | if (data->o_res.delegation_type != 0) { |
1119 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | ||
1093 | int delegation_flags = 0; | 1120 | int delegation_flags = 0; |
1094 | 1121 | ||
1095 | rcu_read_lock(); | 1122 | rcu_read_lock(); |
@@ -1101,7 +1128,7 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data | |||
1101 | pr_err_ratelimited("NFS: Broken NFSv4 server %s is " | 1128 | pr_err_ratelimited("NFS: Broken NFSv4 server %s is " |
1102 | "returning a delegation for " | 1129 | "returning a delegation for " |
1103 | "OPEN(CLAIM_DELEGATE_CUR)\n", | 1130 | "OPEN(CLAIM_DELEGATE_CUR)\n", |
1104 | NFS_CLIENT(inode)->cl_server); | 1131 | clp->cl_hostname); |
1105 | } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0) | 1132 | } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0) |
1106 | nfs_inode_set_delegation(state->inode, | 1133 | nfs_inode_set_delegation(state->inode, |
1107 | data->owner->so_cred, | 1134 | data->owner->so_cred, |
@@ -1210,10 +1237,10 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
1210 | * Check if we need to update the current stateid. | 1237 | * Check if we need to update the current stateid. |
1211 | */ | 1238 | */ |
1212 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 && | 1239 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 && |
1213 | memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) { | 1240 | !nfs4_stateid_match(&state->stateid, &state->open_stateid)) { |
1214 | write_seqlock(&state->seqlock); | 1241 | write_seqlock(&state->seqlock); |
1215 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) | 1242 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) |
1216 | memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)); | 1243 | nfs4_stateid_copy(&state->stateid, &state->open_stateid); |
1217 | write_sequnlock(&state->seqlock); | 1244 | write_sequnlock(&state->seqlock); |
1218 | } | 1245 | } |
1219 | return 0; | 1246 | return 0; |
@@ -1282,8 +1309,7 @@ static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs | |||
1282 | if (IS_ERR(opendata)) | 1309 | if (IS_ERR(opendata)) |
1283 | return PTR_ERR(opendata); | 1310 | return PTR_ERR(opendata); |
1284 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; | 1311 | opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; |
1285 | memcpy(opendata->o_arg.u.delegation.data, stateid->data, | 1312 | nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid); |
1286 | sizeof(opendata->o_arg.u.delegation.data)); | ||
1287 | ret = nfs4_open_recover(opendata, state); | 1313 | ret = nfs4_open_recover(opendata, state); |
1288 | nfs4_opendata_put(opendata); | 1314 | nfs4_opendata_put(opendata); |
1289 | return ret; | 1315 | return ret; |
@@ -1319,8 +1345,11 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1319 | * The show must go on: exit, but mark the | 1345 | * The show must go on: exit, but mark the |
1320 | * stateid as needing recovery. | 1346 | * stateid as needing recovery. |
1321 | */ | 1347 | */ |
1348 | case -NFS4ERR_DELEG_REVOKED: | ||
1322 | case -NFS4ERR_ADMIN_REVOKED: | 1349 | case -NFS4ERR_ADMIN_REVOKED: |
1323 | case -NFS4ERR_BAD_STATEID: | 1350 | case -NFS4ERR_BAD_STATEID: |
1351 | nfs_inode_find_state_and_recover(state->inode, | ||
1352 | stateid); | ||
1324 | nfs4_schedule_stateid_recovery(server, state); | 1353 | nfs4_schedule_stateid_recovery(server, state); |
1325 | case -EKEYEXPIRED: | 1354 | case -EKEYEXPIRED: |
1326 | /* | 1355 | /* |
@@ -1345,8 +1374,7 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | |||
1345 | 1374 | ||
1346 | data->rpc_status = task->tk_status; | 1375 | data->rpc_status = task->tk_status; |
1347 | if (data->rpc_status == 0) { | 1376 | if (data->rpc_status == 0) { |
1348 | memcpy(data->o_res.stateid.data, data->c_res.stateid.data, | 1377 | nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid); |
1349 | sizeof(data->o_res.stateid.data)); | ||
1350 | nfs_confirm_seqid(&data->owner->so_seqid, 0); | 1378 | nfs_confirm_seqid(&data->owner->so_seqid, 0); |
1351 | renew_lease(data->o_res.server, data->timestamp); | 1379 | renew_lease(data->o_res.server, data->timestamp); |
1352 | data->rpc_done = 1; | 1380 | data->rpc_done = 1; |
@@ -1440,7 +1468,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1440 | rcu_read_unlock(); | 1468 | rcu_read_unlock(); |
1441 | } | 1469 | } |
1442 | /* Update sequence id. */ | 1470 | /* Update sequence id. */ |
1443 | data->o_arg.id = sp->so_owner_id.id; | 1471 | data->o_arg.id = sp->so_seqid.owner_id; |
1444 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; | 1472 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; |
1445 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { | 1473 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
1446 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 1474 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
@@ -1449,7 +1477,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1449 | data->timestamp = jiffies; | 1477 | data->timestamp = jiffies; |
1450 | if (nfs4_setup_sequence(data->o_arg.server, | 1478 | if (nfs4_setup_sequence(data->o_arg.server, |
1451 | &data->o_arg.seq_args, | 1479 | &data->o_arg.seq_args, |
1452 | &data->o_res.seq_res, 1, task)) | 1480 | &data->o_res.seq_res, task)) |
1453 | return; | 1481 | return; |
1454 | rpc_call_start(task); | 1482 | rpc_call_start(task); |
1455 | return; | 1483 | return; |
@@ -1551,6 +1579,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) | |||
1551 | }; | 1579 | }; |
1552 | int status; | 1580 | int status; |
1553 | 1581 | ||
1582 | nfs41_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1); | ||
1554 | kref_get(&data->kref); | 1583 | kref_get(&data->kref); |
1555 | data->rpc_done = 0; | 1584 | data->rpc_done = 0; |
1556 | data->rpc_status = 0; | 1585 | data->rpc_status = 0; |
@@ -1712,15 +1741,32 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta | |||
1712 | } | 1741 | } |
1713 | 1742 | ||
1714 | #if defined(CONFIG_NFS_V4_1) | 1743 | #if defined(CONFIG_NFS_V4_1) |
1715 | static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) | 1744 | static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *stateid, unsigned int flags) |
1716 | { | 1745 | { |
1717 | int status; | 1746 | int status = NFS_OK; |
1718 | struct nfs_server *server = NFS_SERVER(state->inode); | 1747 | struct nfs_server *server = NFS_SERVER(state->inode); |
1719 | 1748 | ||
1720 | status = nfs41_test_stateid(server, state); | 1749 | if (state->flags & flags) { |
1721 | if (status == NFS_OK) | 1750 | status = nfs41_test_stateid(server, stateid); |
1722 | return 0; | 1751 | if (status != NFS_OK) { |
1723 | nfs41_free_stateid(server, state); | 1752 | nfs41_free_stateid(server, stateid); |
1753 | state->flags &= ~flags; | ||
1754 | } | ||
1755 | } | ||
1756 | return status; | ||
1757 | } | ||
1758 | |||
1759 | static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) | ||
1760 | { | ||
1761 | int deleg_status, open_status; | ||
1762 | int deleg_flags = 1 << NFS_DELEGATED_STATE; | ||
1763 | int open_flags = (1 << NFS_O_RDONLY_STATE) | (1 << NFS_O_WRONLY_STATE) | (1 << NFS_O_RDWR_STATE); | ||
1764 | |||
1765 | deleg_status = nfs41_check_expired_stateid(state, &state->stateid, deleg_flags); | ||
1766 | open_status = nfs41_check_expired_stateid(state, &state->open_stateid, open_flags); | ||
1767 | |||
1768 | if ((deleg_status == NFS_OK) && (open_status == NFS_OK)) | ||
1769 | return NFS_OK; | ||
1724 | return nfs4_open_expired(sp, state); | 1770 | return nfs4_open_expired(sp, state); |
1725 | } | 1771 | } |
1726 | #endif | 1772 | #endif |
@@ -1754,7 +1800,8 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode | |||
1754 | 1800 | ||
1755 | /* Protect against reboot recovery conflicts */ | 1801 | /* Protect against reboot recovery conflicts */ |
1756 | status = -ENOMEM; | 1802 | status = -ENOMEM; |
1757 | if (!(sp = nfs4_get_state_owner(server, cred))) { | 1803 | sp = nfs4_get_state_owner(server, cred, GFP_KERNEL); |
1804 | if (sp == NULL) { | ||
1758 | dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n"); | 1805 | dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n"); |
1759 | goto out_err; | 1806 | goto out_err; |
1760 | } | 1807 | } |
@@ -1829,7 +1876,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, | |||
1829 | * the user though... | 1876 | * the user though... |
1830 | */ | 1877 | */ |
1831 | if (status == -NFS4ERR_BAD_SEQID) { | 1878 | if (status == -NFS4ERR_BAD_SEQID) { |
1832 | printk(KERN_WARNING "NFS: v4 server %s " | 1879 | pr_warn_ratelimited("NFS: v4 server %s " |
1833 | " returned a bad sequence-id error!\n", | 1880 | " returned a bad sequence-id error!\n", |
1834 | NFS_SERVER(dir)->nfs_client->cl_hostname); | 1881 | NFS_SERVER(dir)->nfs_client->cl_hostname); |
1835 | exception.retry = 1; | 1882 | exception.retry = 1; |
@@ -1882,12 +1929,14 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
1882 | 1929 | ||
1883 | nfs_fattr_init(fattr); | 1930 | nfs_fattr_init(fattr); |
1884 | 1931 | ||
1885 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) { | 1932 | if (state != NULL) { |
1933 | nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, | ||
1934 | current->files, current->tgid); | ||
1935 | } else if (nfs4_copy_delegation_stateid(&arg.stateid, inode, | ||
1936 | FMODE_WRITE)) { | ||
1886 | /* Use that stateid */ | 1937 | /* Use that stateid */ |
1887 | } else if (state != NULL) { | ||
1888 | nfs4_copy_stateid(&arg.stateid, state, current->files, current->tgid); | ||
1889 | } else | 1938 | } else |
1890 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); | 1939 | nfs4_stateid_copy(&arg.stateid, &zero_stateid); |
1891 | 1940 | ||
1892 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 1941 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
1893 | if (status == 0 && state != NULL) | 1942 | if (status == 0 && state != NULL) |
@@ -1900,7 +1949,10 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
1900 | struct nfs4_state *state) | 1949 | struct nfs4_state *state) |
1901 | { | 1950 | { |
1902 | struct nfs_server *server = NFS_SERVER(inode); | 1951 | struct nfs_server *server = NFS_SERVER(inode); |
1903 | struct nfs4_exception exception = { }; | 1952 | struct nfs4_exception exception = { |
1953 | .state = state, | ||
1954 | .inode = inode, | ||
1955 | }; | ||
1904 | int err; | 1956 | int err; |
1905 | do { | 1957 | do { |
1906 | err = nfs4_handle_exception(server, | 1958 | err = nfs4_handle_exception(server, |
@@ -1954,6 +2006,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
1954 | struct nfs4_state *state = calldata->state; | 2006 | struct nfs4_state *state = calldata->state; |
1955 | struct nfs_server *server = NFS_SERVER(calldata->inode); | 2007 | struct nfs_server *server = NFS_SERVER(calldata->inode); |
1956 | 2008 | ||
2009 | dprintk("%s: begin!\n", __func__); | ||
1957 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) | 2010 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) |
1958 | return; | 2011 | return; |
1959 | /* hmm. we are done with the inode, and in the process of freeing | 2012 | /* hmm. we are done with the inode, and in the process of freeing |
@@ -1981,6 +2034,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
1981 | } | 2034 | } |
1982 | nfs_release_seqid(calldata->arg.seqid); | 2035 | nfs_release_seqid(calldata->arg.seqid); |
1983 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); | 2036 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); |
2037 | dprintk("%s: done, ret = %d!\n", __func__, task->tk_status); | ||
1984 | } | 2038 | } |
1985 | 2039 | ||
1986 | static void nfs4_close_prepare(struct rpc_task *task, void *data) | 2040 | static void nfs4_close_prepare(struct rpc_task *task, void *data) |
@@ -1989,6 +2043,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
1989 | struct nfs4_state *state = calldata->state; | 2043 | struct nfs4_state *state = calldata->state; |
1990 | int call_close = 0; | 2044 | int call_close = 0; |
1991 | 2045 | ||
2046 | dprintk("%s: begin!\n", __func__); | ||
1992 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) | 2047 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
1993 | return; | 2048 | return; |
1994 | 2049 | ||
@@ -2013,7 +2068,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2013 | if (!call_close) { | 2068 | if (!call_close) { |
2014 | /* Note: exit _without_ calling nfs4_close_done */ | 2069 | /* Note: exit _without_ calling nfs4_close_done */ |
2015 | task->tk_action = NULL; | 2070 | task->tk_action = NULL; |
2016 | return; | 2071 | goto out; |
2017 | } | 2072 | } |
2018 | 2073 | ||
2019 | if (calldata->arg.fmode == 0) { | 2074 | if (calldata->arg.fmode == 0) { |
@@ -2022,17 +2077,20 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2022 | pnfs_roc_drain(calldata->inode, &calldata->roc_barrier)) { | 2077 | pnfs_roc_drain(calldata->inode, &calldata->roc_barrier)) { |
2023 | rpc_sleep_on(&NFS_SERVER(calldata->inode)->roc_rpcwaitq, | 2078 | rpc_sleep_on(&NFS_SERVER(calldata->inode)->roc_rpcwaitq, |
2024 | task, NULL); | 2079 | task, NULL); |
2025 | return; | 2080 | goto out; |
2026 | } | 2081 | } |
2027 | } | 2082 | } |
2028 | 2083 | ||
2029 | nfs_fattr_init(calldata->res.fattr); | 2084 | nfs_fattr_init(calldata->res.fattr); |
2030 | calldata->timestamp = jiffies; | 2085 | calldata->timestamp = jiffies; |
2031 | if (nfs4_setup_sequence(NFS_SERVER(calldata->inode), | 2086 | if (nfs4_setup_sequence(NFS_SERVER(calldata->inode), |
2032 | &calldata->arg.seq_args, &calldata->res.seq_res, | 2087 | &calldata->arg.seq_args, |
2033 | 1, task)) | 2088 | &calldata->res.seq_res, |
2034 | return; | 2089 | task)) |
2090 | goto out; | ||
2035 | rpc_call_start(task); | 2091 | rpc_call_start(task); |
2092 | out: | ||
2093 | dprintk("%s: done!\n", __func__); | ||
2036 | } | 2094 | } |
2037 | 2095 | ||
2038 | static const struct rpc_call_ops nfs4_close_ops = { | 2096 | static const struct rpc_call_ops nfs4_close_ops = { |
@@ -2074,6 +2132,7 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc) | |||
2074 | calldata = kzalloc(sizeof(*calldata), gfp_mask); | 2132 | calldata = kzalloc(sizeof(*calldata), gfp_mask); |
2075 | if (calldata == NULL) | 2133 | if (calldata == NULL) |
2076 | goto out; | 2134 | goto out; |
2135 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1); | ||
2077 | calldata->inode = state->inode; | 2136 | calldata->inode = state->inode; |
2078 | calldata->state = state; | 2137 | calldata->state = state; |
2079 | calldata->arg.fh = NFS_FH(state->inode); | 2138 | calldata->arg.fh = NFS_FH(state->inode); |
@@ -2182,6 +2241,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f | |||
2182 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; | 2241 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; |
2183 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; | 2242 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; |
2184 | server->acl_bitmask = res.acl_bitmask; | 2243 | server->acl_bitmask = res.acl_bitmask; |
2244 | server->fh_expire_type = res.fh_expire_type; | ||
2185 | } | 2245 | } |
2186 | 2246 | ||
2187 | return status; | 2247 | return status; |
@@ -2303,7 +2363,6 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2303 | return nfs4_map_errors(status); | 2363 | return nfs4_map_errors(status); |
2304 | } | 2364 | } |
2305 | 2365 | ||
2306 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | ||
2307 | /* | 2366 | /* |
2308 | * Get locations and (maybe) other attributes of a referral. | 2367 | * Get locations and (maybe) other attributes of a referral. |
2309 | * Note that we'll actually follow the referral later when | 2368 | * Note that we'll actually follow the referral later when |
@@ -2420,6 +2479,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2420 | } | 2479 | } |
2421 | } | 2480 | } |
2422 | 2481 | ||
2482 | /* Deal with open(O_TRUNC) */ | ||
2483 | if (sattr->ia_valid & ATTR_OPEN) | ||
2484 | sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
2485 | |||
2423 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state); | 2486 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state); |
2424 | if (status == 0) | 2487 | if (status == 0) |
2425 | nfs_setattr_update_inode(inode, sattr); | 2488 | nfs_setattr_update_inode(inode, sattr); |
@@ -2494,7 +2557,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2494 | struct nfs_server *server = NFS_SERVER(inode); | 2557 | struct nfs_server *server = NFS_SERVER(inode); |
2495 | struct nfs4_accessargs args = { | 2558 | struct nfs4_accessargs args = { |
2496 | .fh = NFS_FH(inode), | 2559 | .fh = NFS_FH(inode), |
2497 | .bitmask = server->attr_bitmask, | 2560 | .bitmask = server->cache_consistency_bitmask, |
2498 | }; | 2561 | }; |
2499 | struct nfs4_accessres res = { | 2562 | struct nfs4_accessres res = { |
2500 | .server = server, | 2563 | .server = server, |
@@ -2712,8 +2775,18 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
2712 | 2775 | ||
2713 | args->bitmask = server->cache_consistency_bitmask; | 2776 | args->bitmask = server->cache_consistency_bitmask; |
2714 | res->server = server; | 2777 | res->server = server; |
2715 | res->seq_res.sr_slot = NULL; | ||
2716 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 2778 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
2779 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); | ||
2780 | } | ||
2781 | |||
2782 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) | ||
2783 | { | ||
2784 | if (nfs4_setup_sequence(NFS_SERVER(data->dir), | ||
2785 | &data->args.seq_args, | ||
2786 | &data->res.seq_res, | ||
2787 | task)) | ||
2788 | return; | ||
2789 | rpc_call_start(task); | ||
2717 | } | 2790 | } |
2718 | 2791 | ||
2719 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | 2792 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) |
@@ -2738,6 +2811,17 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) | |||
2738 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; | 2811 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; |
2739 | arg->bitmask = server->attr_bitmask; | 2812 | arg->bitmask = server->attr_bitmask; |
2740 | res->server = server; | 2813 | res->server = server; |
2814 | nfs41_init_sequence(&arg->seq_args, &res->seq_res, 1); | ||
2815 | } | ||
2816 | |||
2817 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) | ||
2818 | { | ||
2819 | if (nfs4_setup_sequence(NFS_SERVER(data->old_dir), | ||
2820 | &data->args.seq_args, | ||
2821 | &data->res.seq_res, | ||
2822 | task)) | ||
2823 | return; | ||
2824 | rpc_call_start(task); | ||
2741 | } | 2825 | } |
2742 | 2826 | ||
2743 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | 2827 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, |
@@ -3232,6 +3316,17 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message | |||
3232 | data->timestamp = jiffies; | 3316 | data->timestamp = jiffies; |
3233 | data->read_done_cb = nfs4_read_done_cb; | 3317 | data->read_done_cb = nfs4_read_done_cb; |
3234 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; | 3318 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; |
3319 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | ||
3320 | } | ||
3321 | |||
3322 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | ||
3323 | { | ||
3324 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), | ||
3325 | &data->args.seq_args, | ||
3326 | &data->res.seq_res, | ||
3327 | task)) | ||
3328 | return; | ||
3329 | rpc_call_start(task); | ||
3235 | } | 3330 | } |
3236 | 3331 | ||
3237 | /* Reset the the nfs_read_data to send the read to the MDS. */ | 3332 | /* Reset the the nfs_read_data to send the read to the MDS. */ |
@@ -3305,6 +3400,17 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
3305 | data->timestamp = jiffies; | 3400 | data->timestamp = jiffies; |
3306 | 3401 | ||
3307 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; | 3402 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; |
3403 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | ||
3404 | } | ||
3405 | |||
3406 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | ||
3407 | { | ||
3408 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), | ||
3409 | &data->args.seq_args, | ||
3410 | &data->res.seq_res, | ||
3411 | task)) | ||
3412 | return; | ||
3413 | rpc_call_start(task); | ||
3308 | } | 3414 | } |
3309 | 3415 | ||
3310 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *data) | 3416 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *data) |
@@ -3339,6 +3445,7 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa | |||
3339 | data->write_done_cb = nfs4_commit_done_cb; | 3445 | data->write_done_cb = nfs4_commit_done_cb; |
3340 | data->res.server = server; | 3446 | data->res.server = server; |
3341 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | 3447 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; |
3448 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | ||
3342 | } | 3449 | } |
3343 | 3450 | ||
3344 | struct nfs4_renewdata { | 3451 | struct nfs4_renewdata { |
@@ -3575,8 +3682,8 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3575 | } | 3682 | } |
3576 | if (npages > 1) { | 3683 | if (npages > 1) { |
3577 | /* for decoding across pages */ | 3684 | /* for decoding across pages */ |
3578 | args.acl_scratch = alloc_page(GFP_KERNEL); | 3685 | res.acl_scratch = alloc_page(GFP_KERNEL); |
3579 | if (!args.acl_scratch) | 3686 | if (!res.acl_scratch) |
3580 | goto out_free; | 3687 | goto out_free; |
3581 | } | 3688 | } |
3582 | args.acl_len = npages * PAGE_SIZE; | 3689 | args.acl_len = npages * PAGE_SIZE; |
@@ -3612,8 +3719,8 @@ out_free: | |||
3612 | for (i = 0; i < npages; i++) | 3719 | for (i = 0; i < npages; i++) |
3613 | if (pages[i]) | 3720 | if (pages[i]) |
3614 | __free_page(pages[i]); | 3721 | __free_page(pages[i]); |
3615 | if (args.acl_scratch) | 3722 | if (res.acl_scratch) |
3616 | __free_page(args.acl_scratch); | 3723 | __free_page(res.acl_scratch); |
3617 | return ret; | 3724 | return ret; |
3618 | } | 3725 | } |
3619 | 3726 | ||
@@ -3714,8 +3821,11 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3714 | if (task->tk_status >= 0) | 3821 | if (task->tk_status >= 0) |
3715 | return 0; | 3822 | return 0; |
3716 | switch(task->tk_status) { | 3823 | switch(task->tk_status) { |
3824 | case -NFS4ERR_DELEG_REVOKED: | ||
3717 | case -NFS4ERR_ADMIN_REVOKED: | 3825 | case -NFS4ERR_ADMIN_REVOKED: |
3718 | case -NFS4ERR_BAD_STATEID: | 3826 | case -NFS4ERR_BAD_STATEID: |
3827 | if (state != NULL) | ||
3828 | nfs_remove_bad_delegation(state->inode); | ||
3719 | case -NFS4ERR_OPENMODE: | 3829 | case -NFS4ERR_OPENMODE: |
3720 | if (state == NULL) | 3830 | if (state == NULL) |
3721 | break; | 3831 | break; |
@@ -3764,6 +3874,16 @@ wait_on_recovery: | |||
3764 | return -EAGAIN; | 3874 | return -EAGAIN; |
3765 | } | 3875 | } |
3766 | 3876 | ||
3877 | static void nfs4_construct_boot_verifier(struct nfs_client *clp, | ||
3878 | nfs4_verifier *bootverf) | ||
3879 | { | ||
3880 | __be32 verf[2]; | ||
3881 | |||
3882 | verf[0] = htonl((u32)clp->cl_boot_time.tv_sec); | ||
3883 | verf[1] = htonl((u32)clp->cl_boot_time.tv_nsec); | ||
3884 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); | ||
3885 | } | ||
3886 | |||
3767 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | 3887 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, |
3768 | unsigned short port, struct rpc_cred *cred, | 3888 | unsigned short port, struct rpc_cred *cred, |
3769 | struct nfs4_setclientid_res *res) | 3889 | struct nfs4_setclientid_res *res) |
@@ -3780,15 +3900,13 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3780 | .rpc_resp = res, | 3900 | .rpc_resp = res, |
3781 | .rpc_cred = cred, | 3901 | .rpc_cred = cred, |
3782 | }; | 3902 | }; |
3783 | __be32 *p; | ||
3784 | int loop = 0; | 3903 | int loop = 0; |
3785 | int status; | 3904 | int status; |
3786 | 3905 | ||
3787 | p = (__be32*)sc_verifier.data; | 3906 | nfs4_construct_boot_verifier(clp, &sc_verifier); |
3788 | *p++ = htonl((u32)clp->cl_boot_time.tv_sec); | ||
3789 | *p = htonl((u32)clp->cl_boot_time.tv_nsec); | ||
3790 | 3907 | ||
3791 | for(;;) { | 3908 | for(;;) { |
3909 | rcu_read_lock(); | ||
3792 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, | 3910 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, |
3793 | sizeof(setclientid.sc_name), "%s/%s %s %s %u", | 3911 | sizeof(setclientid.sc_name), "%s/%s %s %s %u", |
3794 | clp->cl_ipaddr, | 3912 | clp->cl_ipaddr, |
@@ -3805,6 +3923,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3805 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, | 3923 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, |
3806 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", | 3924 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", |
3807 | clp->cl_ipaddr, port >> 8, port & 255); | 3925 | clp->cl_ipaddr, port >> 8, port & 255); |
3926 | rcu_read_unlock(); | ||
3808 | 3927 | ||
3809 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 3928 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
3810 | if (status != -NFS4ERR_CLID_INUSE) | 3929 | if (status != -NFS4ERR_CLID_INUSE) |
@@ -3891,7 +4010,7 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | |||
3891 | 4010 | ||
3892 | if (nfs4_setup_sequence(d_data->res.server, | 4011 | if (nfs4_setup_sequence(d_data->res.server, |
3893 | &d_data->args.seq_args, | 4012 | &d_data->args.seq_args, |
3894 | &d_data->res.seq_res, 1, task)) | 4013 | &d_data->res.seq_res, task)) |
3895 | return; | 4014 | return; |
3896 | rpc_call_start(task); | 4015 | rpc_call_start(task); |
3897 | } | 4016 | } |
@@ -3925,11 +4044,12 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3925 | data = kzalloc(sizeof(*data), GFP_NOFS); | 4044 | data = kzalloc(sizeof(*data), GFP_NOFS); |
3926 | if (data == NULL) | 4045 | if (data == NULL) |
3927 | return -ENOMEM; | 4046 | return -ENOMEM; |
4047 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | ||
3928 | data->args.fhandle = &data->fh; | 4048 | data->args.fhandle = &data->fh; |
3929 | data->args.stateid = &data->stateid; | 4049 | data->args.stateid = &data->stateid; |
3930 | data->args.bitmask = server->attr_bitmask; | 4050 | data->args.bitmask = server->attr_bitmask; |
3931 | nfs_copy_fh(&data->fh, NFS_FH(inode)); | 4051 | nfs_copy_fh(&data->fh, NFS_FH(inode)); |
3932 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); | 4052 | nfs4_stateid_copy(&data->stateid, stateid); |
3933 | data->res.fattr = &data->fattr; | 4053 | data->res.fattr = &data->fattr; |
3934 | data->res.server = server; | 4054 | data->res.server = server; |
3935 | nfs_fattr_init(data->res.fattr); | 4055 | nfs_fattr_init(data->res.fattr); |
@@ -4016,7 +4136,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
4016 | if (status != 0) | 4136 | if (status != 0) |
4017 | goto out; | 4137 | goto out; |
4018 | lsp = request->fl_u.nfs4_fl.owner; | 4138 | lsp = request->fl_u.nfs4_fl.owner; |
4019 | arg.lock_owner.id = lsp->ls_id.id; | 4139 | arg.lock_owner.id = lsp->ls_seqid.owner_id; |
4020 | arg.lock_owner.s_dev = server->s_dev; | 4140 | arg.lock_owner.s_dev = server->s_dev; |
4021 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 4141 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
4022 | switch (status) { | 4142 | switch (status) { |
@@ -4112,9 +4232,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
4112 | return; | 4232 | return; |
4113 | switch (task->tk_status) { | 4233 | switch (task->tk_status) { |
4114 | case 0: | 4234 | case 0: |
4115 | memcpy(calldata->lsp->ls_stateid.data, | 4235 | nfs4_stateid_copy(&calldata->lsp->ls_stateid, |
4116 | calldata->res.stateid.data, | 4236 | &calldata->res.stateid); |
4117 | sizeof(calldata->lsp->ls_stateid.data)); | ||
4118 | renew_lease(calldata->server, calldata->timestamp); | 4237 | renew_lease(calldata->server, calldata->timestamp); |
4119 | break; | 4238 | break; |
4120 | case -NFS4ERR_BAD_STATEID: | 4239 | case -NFS4ERR_BAD_STATEID: |
@@ -4142,7 +4261,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
4142 | calldata->timestamp = jiffies; | 4261 | calldata->timestamp = jiffies; |
4143 | if (nfs4_setup_sequence(calldata->server, | 4262 | if (nfs4_setup_sequence(calldata->server, |
4144 | &calldata->arg.seq_args, | 4263 | &calldata->arg.seq_args, |
4145 | &calldata->res.seq_res, 1, task)) | 4264 | &calldata->res.seq_res, task)) |
4146 | return; | 4265 | return; |
4147 | rpc_call_start(task); | 4266 | rpc_call_start(task); |
4148 | } | 4267 | } |
@@ -4182,6 +4301,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
4182 | return ERR_PTR(-ENOMEM); | 4301 | return ERR_PTR(-ENOMEM); |
4183 | } | 4302 | } |
4184 | 4303 | ||
4304 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); | ||
4185 | msg.rpc_argp = &data->arg; | 4305 | msg.rpc_argp = &data->arg; |
4186 | msg.rpc_resp = &data->res; | 4306 | msg.rpc_resp = &data->res; |
4187 | task_setup_data.callback_data = data; | 4307 | task_setup_data.callback_data = data; |
@@ -4261,7 +4381,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
4261 | goto out_free_seqid; | 4381 | goto out_free_seqid; |
4262 | p->arg.lock_stateid = &lsp->ls_stateid; | 4382 | p->arg.lock_stateid = &lsp->ls_stateid; |
4263 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | 4383 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; |
4264 | p->arg.lock_owner.id = lsp->ls_id.id; | 4384 | p->arg.lock_owner.id = lsp->ls_seqid.owner_id; |
4265 | p->arg.lock_owner.s_dev = server->s_dev; | 4385 | p->arg.lock_owner.s_dev = server->s_dev; |
4266 | p->res.lock_seqid = p->arg.lock_seqid; | 4386 | p->res.lock_seqid = p->arg.lock_seqid; |
4267 | p->lsp = lsp; | 4387 | p->lsp = lsp; |
@@ -4297,7 +4417,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
4297 | data->timestamp = jiffies; | 4417 | data->timestamp = jiffies; |
4298 | if (nfs4_setup_sequence(data->server, | 4418 | if (nfs4_setup_sequence(data->server, |
4299 | &data->arg.seq_args, | 4419 | &data->arg.seq_args, |
4300 | &data->res.seq_res, 1, task)) | 4420 | &data->res.seq_res, task)) |
4301 | return; | 4421 | return; |
4302 | rpc_call_start(task); | 4422 | rpc_call_start(task); |
4303 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); | 4423 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); |
@@ -4326,8 +4446,7 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) | |||
4326 | goto out; | 4446 | goto out; |
4327 | } | 4447 | } |
4328 | if (data->rpc_status == 0) { | 4448 | if (data->rpc_status == 0) { |
4329 | memcpy(data->lsp->ls_stateid.data, data->res.stateid.data, | 4449 | nfs4_stateid_copy(&data->lsp->ls_stateid, &data->res.stateid); |
4330 | sizeof(data->lsp->ls_stateid.data)); | ||
4331 | data->lsp->ls_flags |= NFS_LOCK_INITIALIZED; | 4450 | data->lsp->ls_flags |= NFS_LOCK_INITIALIZED; |
4332 | renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp); | 4451 | renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp); |
4333 | } | 4452 | } |
@@ -4415,6 +4534,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
4415 | data->arg.reclaim = NFS_LOCK_RECLAIM; | 4534 | data->arg.reclaim = NFS_LOCK_RECLAIM; |
4416 | task_setup_data.callback_ops = &nfs4_recover_lock_ops; | 4535 | task_setup_data.callback_ops = &nfs4_recover_lock_ops; |
4417 | } | 4536 | } |
4537 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); | ||
4418 | msg.rpc_argp = &data->arg; | 4538 | msg.rpc_argp = &data->arg; |
4419 | msg.rpc_resp = &data->res; | 4539 | msg.rpc_resp = &data->res; |
4420 | task_setup_data.callback_data = data; | 4540 | task_setup_data.callback_data = data; |
@@ -4479,15 +4599,34 @@ out: | |||
4479 | } | 4599 | } |
4480 | 4600 | ||
4481 | #if defined(CONFIG_NFS_V4_1) | 4601 | #if defined(CONFIG_NFS_V4_1) |
4482 | static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *request) | 4602 | static int nfs41_check_expired_locks(struct nfs4_state *state) |
4483 | { | 4603 | { |
4484 | int status; | 4604 | int status, ret = NFS_OK; |
4605 | struct nfs4_lock_state *lsp; | ||
4485 | struct nfs_server *server = NFS_SERVER(state->inode); | 4606 | struct nfs_server *server = NFS_SERVER(state->inode); |
4486 | 4607 | ||
4487 | status = nfs41_test_stateid(server, state); | 4608 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { |
4609 | if (lsp->ls_flags & NFS_LOCK_INITIALIZED) { | ||
4610 | status = nfs41_test_stateid(server, &lsp->ls_stateid); | ||
4611 | if (status != NFS_OK) { | ||
4612 | nfs41_free_stateid(server, &lsp->ls_stateid); | ||
4613 | lsp->ls_flags &= ~NFS_LOCK_INITIALIZED; | ||
4614 | ret = status; | ||
4615 | } | ||
4616 | } | ||
4617 | }; | ||
4618 | |||
4619 | return ret; | ||
4620 | } | ||
4621 | |||
4622 | static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *request) | ||
4623 | { | ||
4624 | int status = NFS_OK; | ||
4625 | |||
4626 | if (test_bit(LK_STATE_IN_USE, &state->flags)) | ||
4627 | status = nfs41_check_expired_locks(state); | ||
4488 | if (status == NFS_OK) | 4628 | if (status == NFS_OK) |
4489 | return 0; | 4629 | return status; |
4490 | nfs41_free_stateid(server, state); | ||
4491 | return nfs4_lock_expired(state, request); | 4630 | return nfs4_lock_expired(state, request); |
4492 | } | 4631 | } |
4493 | #endif | 4632 | #endif |
@@ -4523,7 +4662,8 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock | |||
4523 | /* Note: we always want to sleep here! */ | 4662 | /* Note: we always want to sleep here! */ |
4524 | request->fl_flags = fl_flags | FL_SLEEP; | 4663 | request->fl_flags = fl_flags | FL_SLEEP; |
4525 | if (do_vfs_lock(request->fl_file, request) < 0) | 4664 | if (do_vfs_lock(request->fl_file, request) < 0) |
4526 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __func__); | 4665 | printk(KERN_WARNING "NFS: %s: VFS is out of sync with lock " |
4666 | "manager!\n", __func__); | ||
4527 | out_unlock: | 4667 | out_unlock: |
4528 | up_read(&nfsi->rwsem); | 4668 | up_read(&nfsi->rwsem); |
4529 | out: | 4669 | out: |
@@ -4533,7 +4673,9 @@ out: | |||
4533 | 4673 | ||
4534 | static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) | 4674 | static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) |
4535 | { | 4675 | { |
4536 | struct nfs4_exception exception = { }; | 4676 | struct nfs4_exception exception = { |
4677 | .state = state, | ||
4678 | }; | ||
4537 | int err; | 4679 | int err; |
4538 | 4680 | ||
4539 | do { | 4681 | do { |
@@ -4603,8 +4745,8 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
4603 | err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW); | 4745 | err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW); |
4604 | switch (err) { | 4746 | switch (err) { |
4605 | default: | 4747 | default: |
4606 | printk(KERN_ERR "%s: unhandled error %d.\n", | 4748 | printk(KERN_ERR "NFS: %s: unhandled error " |
4607 | __func__, err); | 4749 | "%d.\n", __func__, err); |
4608 | case 0: | 4750 | case 0: |
4609 | case -ESTALE: | 4751 | case -ESTALE: |
4610 | goto out; | 4752 | goto out; |
@@ -4626,6 +4768,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
4626 | * The show must go on: exit, but mark the | 4768 | * The show must go on: exit, but mark the |
4627 | * stateid as needing recovery. | 4769 | * stateid as needing recovery. |
4628 | */ | 4770 | */ |
4771 | case -NFS4ERR_DELEG_REVOKED: | ||
4629 | case -NFS4ERR_ADMIN_REVOKED: | 4772 | case -NFS4ERR_ADMIN_REVOKED: |
4630 | case -NFS4ERR_BAD_STATEID: | 4773 | case -NFS4ERR_BAD_STATEID: |
4631 | case -NFS4ERR_OPENMODE: | 4774 | case -NFS4ERR_OPENMODE: |
@@ -4655,33 +4798,44 @@ out: | |||
4655 | return err; | 4798 | return err; |
4656 | } | 4799 | } |
4657 | 4800 | ||
4801 | struct nfs_release_lockowner_data { | ||
4802 | struct nfs4_lock_state *lsp; | ||
4803 | struct nfs_server *server; | ||
4804 | struct nfs_release_lockowner_args args; | ||
4805 | }; | ||
4806 | |||
4658 | static void nfs4_release_lockowner_release(void *calldata) | 4807 | static void nfs4_release_lockowner_release(void *calldata) |
4659 | { | 4808 | { |
4809 | struct nfs_release_lockowner_data *data = calldata; | ||
4810 | nfs4_free_lock_state(data->server, data->lsp); | ||
4660 | kfree(calldata); | 4811 | kfree(calldata); |
4661 | } | 4812 | } |
4662 | 4813 | ||
4663 | const struct rpc_call_ops nfs4_release_lockowner_ops = { | 4814 | static const struct rpc_call_ops nfs4_release_lockowner_ops = { |
4664 | .rpc_release = nfs4_release_lockowner_release, | 4815 | .rpc_release = nfs4_release_lockowner_release, |
4665 | }; | 4816 | }; |
4666 | 4817 | ||
4667 | void nfs4_release_lockowner(const struct nfs4_lock_state *lsp) | 4818 | int nfs4_release_lockowner(struct nfs4_lock_state *lsp) |
4668 | { | 4819 | { |
4669 | struct nfs_server *server = lsp->ls_state->owner->so_server; | 4820 | struct nfs_server *server = lsp->ls_state->owner->so_server; |
4670 | struct nfs_release_lockowner_args *args; | 4821 | struct nfs_release_lockowner_data *data; |
4671 | struct rpc_message msg = { | 4822 | struct rpc_message msg = { |
4672 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER], | 4823 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER], |
4673 | }; | 4824 | }; |
4674 | 4825 | ||
4675 | if (server->nfs_client->cl_mvops->minor_version != 0) | 4826 | if (server->nfs_client->cl_mvops->minor_version != 0) |
4676 | return; | 4827 | return -EINVAL; |
4677 | args = kmalloc(sizeof(*args), GFP_NOFS); | 4828 | data = kmalloc(sizeof(*data), GFP_NOFS); |
4678 | if (!args) | 4829 | if (!data) |
4679 | return; | 4830 | return -ENOMEM; |
4680 | args->lock_owner.clientid = server->nfs_client->cl_clientid; | 4831 | data->lsp = lsp; |
4681 | args->lock_owner.id = lsp->ls_id.id; | 4832 | data->server = server; |
4682 | args->lock_owner.s_dev = server->s_dev; | 4833 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; |
4683 | msg.rpc_argp = args; | 4834 | data->args.lock_owner.id = lsp->ls_seqid.owner_id; |
4684 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, args); | 4835 | data->args.lock_owner.s_dev = server->s_dev; |
4836 | msg.rpc_argp = &data->args; | ||
4837 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); | ||
4838 | return 0; | ||
4685 | } | 4839 | } |
4686 | 4840 | ||
4687 | #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" | 4841 | #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" |
@@ -4727,11 +4881,11 @@ static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) | |||
4727 | if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) || | 4881 | if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) || |
4728 | (fattr->valid & NFS_ATTR_FATTR_FILEID)) && | 4882 | (fattr->valid & NFS_ATTR_FATTR_FILEID)) && |
4729 | (fattr->valid & NFS_ATTR_FATTR_FSID) && | 4883 | (fattr->valid & NFS_ATTR_FATTR_FSID) && |
4730 | (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL))) | 4884 | (fattr->valid & NFS_ATTR_FATTR_V4_LOCATIONS))) |
4731 | return; | 4885 | return; |
4732 | 4886 | ||
4733 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | | 4887 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | |
4734 | NFS_ATTR_FATTR_NLINK; | 4888 | NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_V4_REFERRAL; |
4735 | fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; | 4889 | fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; |
4736 | fattr->nlink = 2; | 4890 | fattr->nlink = 2; |
4737 | } | 4891 | } |
@@ -4798,7 +4952,8 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct | |||
4798 | return status; | 4952 | return status; |
4799 | } | 4953 | } |
4800 | 4954 | ||
4801 | int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) | 4955 | static int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, |
4956 | struct nfs4_secinfo_flavors *flavors) | ||
4802 | { | 4957 | { |
4803 | struct nfs4_exception exception = { }; | 4958 | struct nfs4_exception exception = { }; |
4804 | int err; | 4959 | int err; |
@@ -4852,6 +5007,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4852 | { | 5007 | { |
4853 | nfs4_verifier verifier; | 5008 | nfs4_verifier verifier; |
4854 | struct nfs41_exchange_id_args args = { | 5009 | struct nfs41_exchange_id_args args = { |
5010 | .verifier = &verifier, | ||
4855 | .client = clp, | 5011 | .client = clp, |
4856 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, | 5012 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, |
4857 | }; | 5013 | }; |
@@ -4865,15 +5021,11 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4865 | .rpc_resp = &res, | 5021 | .rpc_resp = &res, |
4866 | .rpc_cred = cred, | 5022 | .rpc_cred = cred, |
4867 | }; | 5023 | }; |
4868 | __be32 *p; | ||
4869 | 5024 | ||
4870 | dprintk("--> %s\n", __func__); | 5025 | dprintk("--> %s\n", __func__); |
4871 | BUG_ON(clp == NULL); | 5026 | BUG_ON(clp == NULL); |
4872 | 5027 | ||
4873 | p = (u32 *)verifier.data; | 5028 | nfs4_construct_boot_verifier(clp, &verifier); |
4874 | *p++ = htonl((u32)clp->cl_boot_time.tv_sec); | ||
4875 | *p = htonl((u32)clp->cl_boot_time.tv_nsec); | ||
4876 | args.verifier = &verifier; | ||
4877 | 5029 | ||
4878 | args.id_len = scnprintf(args.id, sizeof(args.id), | 5030 | args.id_len = scnprintf(args.id, sizeof(args.id), |
4879 | "%s/%s.%s/%u", | 5031 | "%s/%s.%s/%u", |
@@ -4883,14 +5035,29 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4883 | clp->cl_rpcclient->cl_auth->au_flavor); | 5035 | clp->cl_rpcclient->cl_auth->au_flavor); |
4884 | 5036 | ||
4885 | res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL); | 5037 | res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL); |
4886 | if (unlikely(!res.server_scope)) | 5038 | if (unlikely(!res.server_scope)) { |
4887 | return -ENOMEM; | 5039 | status = -ENOMEM; |
5040 | goto out; | ||
5041 | } | ||
5042 | |||
5043 | res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_KERNEL); | ||
5044 | if (unlikely(!res.impl_id)) { | ||
5045 | status = -ENOMEM; | ||
5046 | goto out_server_scope; | ||
5047 | } | ||
4888 | 5048 | ||
4889 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 5049 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4890 | if (!status) | 5050 | if (!status) |
4891 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | 5051 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); |
4892 | 5052 | ||
4893 | if (!status) { | 5053 | if (!status) { |
5054 | /* use the most recent implementation id */ | ||
5055 | kfree(clp->impl_id); | ||
5056 | clp->impl_id = res.impl_id; | ||
5057 | } else | ||
5058 | kfree(res.impl_id); | ||
5059 | |||
5060 | if (!status) { | ||
4894 | if (clp->server_scope && | 5061 | if (clp->server_scope && |
4895 | !nfs41_same_server_scope(clp->server_scope, | 5062 | !nfs41_same_server_scope(clp->server_scope, |
4896 | res.server_scope)) { | 5063 | res.server_scope)) { |
@@ -4901,12 +5068,21 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4901 | clp->server_scope = NULL; | 5068 | clp->server_scope = NULL; |
4902 | } | 5069 | } |
4903 | 5070 | ||
4904 | if (!clp->server_scope) | 5071 | if (!clp->server_scope) { |
4905 | clp->server_scope = res.server_scope; | 5072 | clp->server_scope = res.server_scope; |
4906 | else | 5073 | goto out; |
4907 | kfree(res.server_scope); | 5074 | } |
4908 | } | 5075 | } |
4909 | 5076 | ||
5077 | out_server_scope: | ||
5078 | kfree(res.server_scope); | ||
5079 | out: | ||
5080 | if (clp->impl_id) | ||
5081 | dprintk("%s: Server Implementation ID: " | ||
5082 | "domain: %s, name: %s, date: %llu,%u\n", | ||
5083 | __func__, clp->impl_id->domain, clp->impl_id->name, | ||
5084 | clp->impl_id->date.seconds, | ||
5085 | clp->impl_id->date.nseconds); | ||
4910 | dprintk("<-- %s status= %d\n", __func__, status); | 5086 | dprintk("<-- %s status= %d\n", __func__, status); |
4911 | return status; | 5087 | return status; |
4912 | } | 5088 | } |
@@ -4930,7 +5106,7 @@ static void nfs4_get_lease_time_prepare(struct rpc_task *task, | |||
4930 | since we're invoked within one */ | 5106 | since we're invoked within one */ |
4931 | ret = nfs41_setup_sequence(data->clp->cl_session, | 5107 | ret = nfs41_setup_sequence(data->clp->cl_session, |
4932 | &data->args->la_seq_args, | 5108 | &data->args->la_seq_args, |
4933 | &data->res->lr_seq_res, 0, task); | 5109 | &data->res->lr_seq_res, task); |
4934 | 5110 | ||
4935 | BUG_ON(ret == -EAGAIN); | 5111 | BUG_ON(ret == -EAGAIN); |
4936 | rpc_call_start(task); | 5112 | rpc_call_start(task); |
@@ -4963,7 +5139,7 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
4963 | dprintk("<-- %s\n", __func__); | 5139 | dprintk("<-- %s\n", __func__); |
4964 | } | 5140 | } |
4965 | 5141 | ||
4966 | struct rpc_call_ops nfs4_get_lease_time_ops = { | 5142 | static const struct rpc_call_ops nfs4_get_lease_time_ops = { |
4967 | .rpc_call_prepare = nfs4_get_lease_time_prepare, | 5143 | .rpc_call_prepare = nfs4_get_lease_time_prepare, |
4968 | .rpc_call_done = nfs4_get_lease_time_done, | 5144 | .rpc_call_done = nfs4_get_lease_time_done, |
4969 | }; | 5145 | }; |
@@ -4994,6 +5170,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
4994 | }; | 5170 | }; |
4995 | int status; | 5171 | int status; |
4996 | 5172 | ||
5173 | nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); | ||
4997 | dprintk("--> %s\n", __func__); | 5174 | dprintk("--> %s\n", __func__); |
4998 | task = rpc_run_task(&task_setup); | 5175 | task = rpc_run_task(&task_setup); |
4999 | 5176 | ||
@@ -5008,37 +5185,53 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
5008 | return status; | 5185 | return status; |
5009 | } | 5186 | } |
5010 | 5187 | ||
5188 | static struct nfs4_slot *nfs4_alloc_slots(u32 max_slots, gfp_t gfp_flags) | ||
5189 | { | ||
5190 | return kcalloc(max_slots, sizeof(struct nfs4_slot), gfp_flags); | ||
5191 | } | ||
5192 | |||
5193 | static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl, | ||
5194 | struct nfs4_slot *new, | ||
5195 | u32 max_slots, | ||
5196 | u32 ivalue) | ||
5197 | { | ||
5198 | struct nfs4_slot *old = NULL; | ||
5199 | u32 i; | ||
5200 | |||
5201 | spin_lock(&tbl->slot_tbl_lock); | ||
5202 | if (new) { | ||
5203 | old = tbl->slots; | ||
5204 | tbl->slots = new; | ||
5205 | tbl->max_slots = max_slots; | ||
5206 | } | ||
5207 | tbl->highest_used_slotid = -1; /* no slot is currently used */ | ||
5208 | for (i = 0; i < tbl->max_slots; i++) | ||
5209 | tbl->slots[i].seq_nr = ivalue; | ||
5210 | spin_unlock(&tbl->slot_tbl_lock); | ||
5211 | kfree(old); | ||
5212 | } | ||
5213 | |||
5011 | /* | 5214 | /* |
5012 | * Reset a slot table | 5215 | * (re)Initialise a slot table |
5013 | */ | 5216 | */ |
5014 | static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs, | 5217 | static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs, |
5015 | int ivalue) | 5218 | u32 ivalue) |
5016 | { | 5219 | { |
5017 | struct nfs4_slot *new = NULL; | 5220 | struct nfs4_slot *new = NULL; |
5018 | int i; | 5221 | int ret = -ENOMEM; |
5019 | int ret = 0; | ||
5020 | 5222 | ||
5021 | dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, | 5223 | dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, |
5022 | max_reqs, tbl->max_slots); | 5224 | max_reqs, tbl->max_slots); |
5023 | 5225 | ||
5024 | /* Does the newly negotiated max_reqs match the existing slot table? */ | 5226 | /* Does the newly negotiated max_reqs match the existing slot table? */ |
5025 | if (max_reqs != tbl->max_slots) { | 5227 | if (max_reqs != tbl->max_slots) { |
5026 | ret = -ENOMEM; | 5228 | new = nfs4_alloc_slots(max_reqs, GFP_NOFS); |
5027 | new = kmalloc(max_reqs * sizeof(struct nfs4_slot), | ||
5028 | GFP_NOFS); | ||
5029 | if (!new) | 5229 | if (!new) |
5030 | goto out; | 5230 | goto out; |
5031 | ret = 0; | ||
5032 | kfree(tbl->slots); | ||
5033 | } | ||
5034 | spin_lock(&tbl->slot_tbl_lock); | ||
5035 | if (new) { | ||
5036 | tbl->slots = new; | ||
5037 | tbl->max_slots = max_reqs; | ||
5038 | } | 5231 | } |
5039 | for (i = 0; i < tbl->max_slots; ++i) | 5232 | ret = 0; |
5040 | tbl->slots[i].seq_nr = ivalue; | 5233 | |
5041 | spin_unlock(&tbl->slot_tbl_lock); | 5234 | nfs4_add_and_init_slots(tbl, new, max_reqs, ivalue); |
5042 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | 5235 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, |
5043 | tbl, tbl->slots, tbl->max_slots); | 5236 | tbl, tbl->slots, tbl->max_slots); |
5044 | out: | 5237 | out: |
@@ -5061,36 +5254,6 @@ static void nfs4_destroy_slot_tables(struct nfs4_session *session) | |||
5061 | } | 5254 | } |
5062 | 5255 | ||
5063 | /* | 5256 | /* |
5064 | * Initialize slot table | ||
5065 | */ | ||
5066 | static int nfs4_init_slot_table(struct nfs4_slot_table *tbl, | ||
5067 | int max_slots, int ivalue) | ||
5068 | { | ||
5069 | struct nfs4_slot *slot; | ||
5070 | int ret = -ENOMEM; | ||
5071 | |||
5072 | BUG_ON(max_slots > NFS4_MAX_SLOT_TABLE); | ||
5073 | |||
5074 | dprintk("--> %s: max_reqs=%u\n", __func__, max_slots); | ||
5075 | |||
5076 | slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_NOFS); | ||
5077 | if (!slot) | ||
5078 | goto out; | ||
5079 | ret = 0; | ||
5080 | |||
5081 | spin_lock(&tbl->slot_tbl_lock); | ||
5082 | tbl->max_slots = max_slots; | ||
5083 | tbl->slots = slot; | ||
5084 | tbl->highest_used_slotid = -1; /* no slot is currently used */ | ||
5085 | spin_unlock(&tbl->slot_tbl_lock); | ||
5086 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | ||
5087 | tbl, tbl->slots, tbl->max_slots); | ||
5088 | out: | ||
5089 | dprintk("<-- %s: return %d\n", __func__, ret); | ||
5090 | return ret; | ||
5091 | } | ||
5092 | |||
5093 | /* | ||
5094 | * Initialize or reset the forechannel and backchannel tables | 5257 | * Initialize or reset the forechannel and backchannel tables |
5095 | */ | 5258 | */ |
5096 | static int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | 5259 | static int nfs4_setup_session_slot_tables(struct nfs4_session *ses) |
@@ -5101,25 +5264,16 @@ static int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | |||
5101 | dprintk("--> %s\n", __func__); | 5264 | dprintk("--> %s\n", __func__); |
5102 | /* Fore channel */ | 5265 | /* Fore channel */ |
5103 | tbl = &ses->fc_slot_table; | 5266 | tbl = &ses->fc_slot_table; |
5104 | if (tbl->slots == NULL) { | 5267 | status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); |
5105 | status = nfs4_init_slot_table(tbl, ses->fc_attrs.max_reqs, 1); | 5268 | if (status) /* -ENOMEM */ |
5106 | if (status) /* -ENOMEM */ | 5269 | return status; |
5107 | return status; | ||
5108 | } else { | ||
5109 | status = nfs4_reset_slot_table(tbl, ses->fc_attrs.max_reqs, 1); | ||
5110 | if (status) | ||
5111 | return status; | ||
5112 | } | ||
5113 | /* Back channel */ | 5270 | /* Back channel */ |
5114 | tbl = &ses->bc_slot_table; | 5271 | tbl = &ses->bc_slot_table; |
5115 | if (tbl->slots == NULL) { | 5272 | status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0); |
5116 | status = nfs4_init_slot_table(tbl, ses->bc_attrs.max_reqs, 0); | 5273 | if (status && tbl->slots == NULL) |
5117 | if (status) | 5274 | /* Fore and back channel share a connection so get |
5118 | /* Fore and back channel share a connection so get | 5275 | * both slot tables or neither */ |
5119 | * both slot tables or neither */ | 5276 | nfs4_destroy_slot_tables(ses); |
5120 | nfs4_destroy_slot_tables(ses); | ||
5121 | } else | ||
5122 | status = nfs4_reset_slot_table(tbl, ses->bc_attrs.max_reqs, 0); | ||
5123 | return status; | 5277 | return status; |
5124 | } | 5278 | } |
5125 | 5279 | ||
@@ -5133,13 +5287,13 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
5133 | return NULL; | 5287 | return NULL; |
5134 | 5288 | ||
5135 | tbl = &session->fc_slot_table; | 5289 | tbl = &session->fc_slot_table; |
5136 | tbl->highest_used_slotid = -1; | 5290 | tbl->highest_used_slotid = NFS4_NO_SLOT; |
5137 | spin_lock_init(&tbl->slot_tbl_lock); | 5291 | spin_lock_init(&tbl->slot_tbl_lock); |
5138 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); | 5292 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); |
5139 | init_completion(&tbl->complete); | 5293 | init_completion(&tbl->complete); |
5140 | 5294 | ||
5141 | tbl = &session->bc_slot_table; | 5295 | tbl = &session->bc_slot_table; |
5142 | tbl->highest_used_slotid = -1; | 5296 | tbl->highest_used_slotid = NFS4_NO_SLOT; |
5143 | spin_lock_init(&tbl->slot_tbl_lock); | 5297 | spin_lock_init(&tbl->slot_tbl_lock); |
5144 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); | 5298 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); |
5145 | init_completion(&tbl->complete); | 5299 | init_completion(&tbl->complete); |
@@ -5152,11 +5306,16 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
5152 | 5306 | ||
5153 | void nfs4_destroy_session(struct nfs4_session *session) | 5307 | void nfs4_destroy_session(struct nfs4_session *session) |
5154 | { | 5308 | { |
5309 | struct rpc_xprt *xprt; | ||
5310 | |||
5155 | nfs4_proc_destroy_session(session); | 5311 | nfs4_proc_destroy_session(session); |
5312 | |||
5313 | rcu_read_lock(); | ||
5314 | xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); | ||
5315 | rcu_read_unlock(); | ||
5156 | dprintk("%s Destroy backchannel for xprt %p\n", | 5316 | dprintk("%s Destroy backchannel for xprt %p\n", |
5157 | __func__, session->clp->cl_rpcclient->cl_xprt); | 5317 | __func__, xprt); |
5158 | xprt_destroy_backchannel(session->clp->cl_rpcclient->cl_xprt, | 5318 | xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); |
5159 | NFS41_BC_MIN_CALLBACKS); | ||
5160 | nfs4_destroy_slot_tables(session); | 5319 | nfs4_destroy_slot_tables(session); |
5161 | kfree(session); | 5320 | kfree(session); |
5162 | } | 5321 | } |
@@ -5184,7 +5343,7 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | |||
5184 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | 5343 | args->fc_attrs.max_rqst_sz = mxrqst_sz; |
5185 | args->fc_attrs.max_resp_sz = mxresp_sz; | 5344 | args->fc_attrs.max_resp_sz = mxresp_sz; |
5186 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | 5345 | args->fc_attrs.max_ops = NFS4_MAX_OPS; |
5187 | args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs; | 5346 | args->fc_attrs.max_reqs = max_session_slots; |
5188 | 5347 | ||
5189 | dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u " | 5348 | dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u " |
5190 | "max_ops=%u max_reqs=%u\n", | 5349 | "max_ops=%u max_reqs=%u\n", |
@@ -5224,6 +5383,8 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args | |||
5224 | return -EINVAL; | 5383 | return -EINVAL; |
5225 | if (rcvd->max_reqs == 0) | 5384 | if (rcvd->max_reqs == 0) |
5226 | return -EINVAL; | 5385 | return -EINVAL; |
5386 | if (rcvd->max_reqs > NFS4_MAX_SLOT_TABLE) | ||
5387 | rcvd->max_reqs = NFS4_MAX_SLOT_TABLE; | ||
5227 | return 0; | 5388 | return 0; |
5228 | } | 5389 | } |
5229 | 5390 | ||
@@ -5239,9 +5400,9 @@ static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args | |||
5239 | if (rcvd->max_resp_sz_cached > sent->max_resp_sz_cached) | 5400 | if (rcvd->max_resp_sz_cached > sent->max_resp_sz_cached) |
5240 | return -EINVAL; | 5401 | return -EINVAL; |
5241 | /* These would render the backchannel useless: */ | 5402 | /* These would render the backchannel useless: */ |
5242 | if (rcvd->max_ops == 0) | 5403 | if (rcvd->max_ops != sent->max_ops) |
5243 | return -EINVAL; | 5404 | return -EINVAL; |
5244 | if (rcvd->max_reqs == 0) | 5405 | if (rcvd->max_reqs != sent->max_reqs) |
5245 | return -EINVAL; | 5406 | return -EINVAL; |
5246 | return 0; | 5407 | return 0; |
5247 | } | 5408 | } |
@@ -5344,7 +5505,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session) | |||
5344 | 5505 | ||
5345 | if (status) | 5506 | if (status) |
5346 | printk(KERN_WARNING | 5507 | printk(KERN_WARNING |
5347 | "Got error %d from the server on DESTROY_SESSION. " | 5508 | "NFS: Got error %d from the server on DESTROY_SESSION. " |
5348 | "Session has been destroyed regardless...\n", status); | 5509 | "Session has been destroyed regardless...\n", status); |
5349 | 5510 | ||
5350 | dprintk("<-- nfs4_proc_destroy_session\n"); | 5511 | dprintk("<-- nfs4_proc_destroy_session\n"); |
@@ -5467,7 +5628,7 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data) | |||
5467 | args = task->tk_msg.rpc_argp; | 5628 | args = task->tk_msg.rpc_argp; |
5468 | res = task->tk_msg.rpc_resp; | 5629 | res = task->tk_msg.rpc_resp; |
5469 | 5630 | ||
5470 | if (nfs41_setup_sequence(clp->cl_session, args, res, 0, task)) | 5631 | if (nfs41_setup_sequence(clp->cl_session, args, res, task)) |
5471 | return; | 5632 | return; |
5472 | rpc_call_start(task); | 5633 | rpc_call_start(task); |
5473 | } | 5634 | } |
@@ -5499,6 +5660,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ | |||
5499 | nfs_put_client(clp); | 5660 | nfs_put_client(clp); |
5500 | return ERR_PTR(-ENOMEM); | 5661 | return ERR_PTR(-ENOMEM); |
5501 | } | 5662 | } |
5663 | nfs41_init_sequence(&calldata->args, &calldata->res, 0); | ||
5502 | msg.rpc_argp = &calldata->args; | 5664 | msg.rpc_argp = &calldata->args; |
5503 | msg.rpc_resp = &calldata->res; | 5665 | msg.rpc_resp = &calldata->res; |
5504 | calldata->clp = clp; | 5666 | calldata->clp = clp; |
@@ -5560,7 +5722,7 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data) | |||
5560 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | 5722 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); |
5561 | if (nfs41_setup_sequence(calldata->clp->cl_session, | 5723 | if (nfs41_setup_sequence(calldata->clp->cl_session, |
5562 | &calldata->arg.seq_args, | 5724 | &calldata->arg.seq_args, |
5563 | &calldata->res.seq_res, 0, task)) | 5725 | &calldata->res.seq_res, task)) |
5564 | return; | 5726 | return; |
5565 | 5727 | ||
5566 | rpc_call_start(task); | 5728 | rpc_call_start(task); |
@@ -5639,6 +5801,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
5639 | calldata->clp = clp; | 5801 | calldata->clp = clp; |
5640 | calldata->arg.one_fs = 0; | 5802 | calldata->arg.one_fs = 0; |
5641 | 5803 | ||
5804 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); | ||
5642 | msg.rpc_argp = &calldata->arg; | 5805 | msg.rpc_argp = &calldata->arg; |
5643 | msg.rpc_resp = &calldata->res; | 5806 | msg.rpc_resp = &calldata->res; |
5644 | task_setup_data.callback_data = calldata; | 5807 | task_setup_data.callback_data = calldata; |
@@ -5670,7 +5833,7 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | |||
5670 | * to be no way to prevent it completely. | 5833 | * to be no way to prevent it completely. |
5671 | */ | 5834 | */ |
5672 | if (nfs4_setup_sequence(server, &lgp->args.seq_args, | 5835 | if (nfs4_setup_sequence(server, &lgp->args.seq_args, |
5673 | &lgp->res.seq_res, 0, task)) | 5836 | &lgp->res.seq_res, task)) |
5674 | return; | 5837 | return; |
5675 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, | 5838 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, |
5676 | NFS_I(lgp->args.inode)->layout, | 5839 | NFS_I(lgp->args.inode)->layout, |
@@ -5745,6 +5908,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
5745 | 5908 | ||
5746 | lgp->res.layoutp = &lgp->args.layout; | 5909 | lgp->res.layoutp = &lgp->args.layout; |
5747 | lgp->res.seq_res.sr_slot = NULL; | 5910 | lgp->res.seq_res.sr_slot = NULL; |
5911 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | ||
5748 | task = rpc_run_task(&task_setup_data); | 5912 | task = rpc_run_task(&task_setup_data); |
5749 | if (IS_ERR(task)) | 5913 | if (IS_ERR(task)) |
5750 | return PTR_ERR(task); | 5914 | return PTR_ERR(task); |
@@ -5765,7 +5929,7 @@ nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata) | |||
5765 | 5929 | ||
5766 | dprintk("--> %s\n", __func__); | 5930 | dprintk("--> %s\n", __func__); |
5767 | if (nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args, | 5931 | if (nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args, |
5768 | &lrp->res.seq_res, 0, task)) | 5932 | &lrp->res.seq_res, task)) |
5769 | return; | 5933 | return; |
5770 | rpc_call_start(task); | 5934 | rpc_call_start(task); |
5771 | } | 5935 | } |
@@ -5831,6 +5995,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
5831 | int status; | 5995 | int status; |
5832 | 5996 | ||
5833 | dprintk("--> %s\n", __func__); | 5997 | dprintk("--> %s\n", __func__); |
5998 | nfs41_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1); | ||
5834 | task = rpc_run_task(&task_setup_data); | 5999 | task = rpc_run_task(&task_setup_data); |
5835 | if (IS_ERR(task)) | 6000 | if (IS_ERR(task)) |
5836 | return PTR_ERR(task); | 6001 | return PTR_ERR(task); |
@@ -5931,7 +6096,7 @@ static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata) | |||
5931 | struct nfs_server *server = NFS_SERVER(data->args.inode); | 6096 | struct nfs_server *server = NFS_SERVER(data->args.inode); |
5932 | 6097 | ||
5933 | if (nfs4_setup_sequence(server, &data->args.seq_args, | 6098 | if (nfs4_setup_sequence(server, &data->args.seq_args, |
5934 | &data->res.seq_res, 1, task)) | 6099 | &data->res.seq_res, task)) |
5935 | return; | 6100 | return; |
5936 | rpc_call_start(task); | 6101 | rpc_call_start(task); |
5937 | } | 6102 | } |
@@ -6018,6 +6183,7 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | |||
6018 | data->args.lastbytewritten, | 6183 | data->args.lastbytewritten, |
6019 | data->args.inode->i_ino); | 6184 | data->args.inode->i_ino); |
6020 | 6185 | ||
6186 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | ||
6021 | task = rpc_run_task(&task_setup_data); | 6187 | task = rpc_run_task(&task_setup_data); |
6022 | if (IS_ERR(task)) | 6188 | if (IS_ERR(task)) |
6023 | return PTR_ERR(task); | 6189 | return PTR_ERR(task); |
@@ -6111,11 +6277,12 @@ out_freepage: | |||
6111 | out: | 6277 | out: |
6112 | return err; | 6278 | return err; |
6113 | } | 6279 | } |
6114 | static int _nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *state) | 6280 | |
6281 | static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | ||
6115 | { | 6282 | { |
6116 | int status; | 6283 | int status; |
6117 | struct nfs41_test_stateid_args args = { | 6284 | struct nfs41_test_stateid_args args = { |
6118 | .stateid = &state->stateid, | 6285 | .stateid = stateid, |
6119 | }; | 6286 | }; |
6120 | struct nfs41_test_stateid_res res; | 6287 | struct nfs41_test_stateid_res res; |
6121 | struct rpc_message msg = { | 6288 | struct rpc_message msg = { |
@@ -6123,28 +6290,31 @@ static int _nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *sta | |||
6123 | .rpc_argp = &args, | 6290 | .rpc_argp = &args, |
6124 | .rpc_resp = &res, | 6291 | .rpc_resp = &res, |
6125 | }; | 6292 | }; |
6126 | args.seq_args.sa_session = res.seq_res.sr_session = NULL; | 6293 | |
6127 | status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 0, 1); | 6294 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); |
6295 | status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); | ||
6296 | |||
6297 | if (status == NFS_OK) | ||
6298 | return res.status; | ||
6128 | return status; | 6299 | return status; |
6129 | } | 6300 | } |
6130 | 6301 | ||
6131 | static int nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *state) | 6302 | static int nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) |
6132 | { | 6303 | { |
6133 | struct nfs4_exception exception = { }; | 6304 | struct nfs4_exception exception = { }; |
6134 | int err; | 6305 | int err; |
6135 | do { | 6306 | do { |
6136 | err = nfs4_handle_exception(server, | 6307 | err = nfs4_handle_exception(server, |
6137 | _nfs41_test_stateid(server, state), | 6308 | _nfs41_test_stateid(server, stateid), |
6138 | &exception); | 6309 | &exception); |
6139 | } while (exception.retry); | 6310 | } while (exception.retry); |
6140 | return err; | 6311 | return err; |
6141 | } | 6312 | } |
6142 | 6313 | ||
6143 | static int _nfs4_free_stateid(struct nfs_server *server, struct nfs4_state *state) | 6314 | static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) |
6144 | { | 6315 | { |
6145 | int status; | ||
6146 | struct nfs41_free_stateid_args args = { | 6316 | struct nfs41_free_stateid_args args = { |
6147 | .stateid = &state->stateid, | 6317 | .stateid = stateid, |
6148 | }; | 6318 | }; |
6149 | struct nfs41_free_stateid_res res; | 6319 | struct nfs41_free_stateid_res res; |
6150 | struct rpc_message msg = { | 6320 | struct rpc_message msg = { |
@@ -6153,25 +6323,46 @@ static int _nfs4_free_stateid(struct nfs_server *server, struct nfs4_state *stat | |||
6153 | .rpc_resp = &res, | 6323 | .rpc_resp = &res, |
6154 | }; | 6324 | }; |
6155 | 6325 | ||
6156 | args.seq_args.sa_session = res.seq_res.sr_session = NULL; | 6326 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); |
6157 | status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 0, 1); | 6327 | return nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); |
6158 | return status; | ||
6159 | } | 6328 | } |
6160 | 6329 | ||
6161 | static int nfs41_free_stateid(struct nfs_server *server, struct nfs4_state *state) | 6330 | static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) |
6162 | { | 6331 | { |
6163 | struct nfs4_exception exception = { }; | 6332 | struct nfs4_exception exception = { }; |
6164 | int err; | 6333 | int err; |
6165 | do { | 6334 | do { |
6166 | err = nfs4_handle_exception(server, | 6335 | err = nfs4_handle_exception(server, |
6167 | _nfs4_free_stateid(server, state), | 6336 | _nfs4_free_stateid(server, stateid), |
6168 | &exception); | 6337 | &exception); |
6169 | } while (exception.retry); | 6338 | } while (exception.retry); |
6170 | return err; | 6339 | return err; |
6171 | } | 6340 | } |
6341 | |||
6342 | static bool nfs41_match_stateid(const nfs4_stateid *s1, | ||
6343 | const nfs4_stateid *s2) | ||
6344 | { | ||
6345 | if (memcmp(s1->other, s2->other, sizeof(s1->other)) != 0) | ||
6346 | return false; | ||
6347 | |||
6348 | if (s1->seqid == s2->seqid) | ||
6349 | return true; | ||
6350 | if (s1->seqid == 0 || s2->seqid == 0) | ||
6351 | return true; | ||
6352 | |||
6353 | return false; | ||
6354 | } | ||
6355 | |||
6172 | #endif /* CONFIG_NFS_V4_1 */ | 6356 | #endif /* CONFIG_NFS_V4_1 */ |
6173 | 6357 | ||
6174 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | 6358 | static bool nfs4_match_stateid(const nfs4_stateid *s1, |
6359 | const nfs4_stateid *s2) | ||
6360 | { | ||
6361 | return nfs4_stateid_match(s1, s2); | ||
6362 | } | ||
6363 | |||
6364 | |||
6365 | static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | ||
6175 | .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, | 6366 | .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, |
6176 | .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, | 6367 | .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, |
6177 | .recover_open = nfs4_open_reclaim, | 6368 | .recover_open = nfs4_open_reclaim, |
@@ -6181,7 +6372,7 @@ struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | |||
6181 | }; | 6372 | }; |
6182 | 6373 | ||
6183 | #if defined(CONFIG_NFS_V4_1) | 6374 | #if defined(CONFIG_NFS_V4_1) |
6184 | struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { | 6375 | static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { |
6185 | .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, | 6376 | .owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT, |
6186 | .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, | 6377 | .state_flag_bit = NFS_STATE_RECLAIM_REBOOT, |
6187 | .recover_open = nfs4_open_reclaim, | 6378 | .recover_open = nfs4_open_reclaim, |
@@ -6192,7 +6383,7 @@ struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { | |||
6192 | }; | 6383 | }; |
6193 | #endif /* CONFIG_NFS_V4_1 */ | 6384 | #endif /* CONFIG_NFS_V4_1 */ |
6194 | 6385 | ||
6195 | struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { | 6386 | static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { |
6196 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, | 6387 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, |
6197 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, | 6388 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, |
6198 | .recover_open = nfs4_open_expired, | 6389 | .recover_open = nfs4_open_expired, |
@@ -6202,7 +6393,7 @@ struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { | |||
6202 | }; | 6393 | }; |
6203 | 6394 | ||
6204 | #if defined(CONFIG_NFS_V4_1) | 6395 | #if defined(CONFIG_NFS_V4_1) |
6205 | struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = { | 6396 | static const struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = { |
6206 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, | 6397 | .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, |
6207 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, | 6398 | .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, |
6208 | .recover_open = nfs41_open_expired, | 6399 | .recover_open = nfs41_open_expired, |
@@ -6212,14 +6403,14 @@ struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = { | |||
6212 | }; | 6403 | }; |
6213 | #endif /* CONFIG_NFS_V4_1 */ | 6404 | #endif /* CONFIG_NFS_V4_1 */ |
6214 | 6405 | ||
6215 | struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = { | 6406 | static const struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = { |
6216 | .sched_state_renewal = nfs4_proc_async_renew, | 6407 | .sched_state_renewal = nfs4_proc_async_renew, |
6217 | .get_state_renewal_cred_locked = nfs4_get_renew_cred_locked, | 6408 | .get_state_renewal_cred_locked = nfs4_get_renew_cred_locked, |
6218 | .renew_lease = nfs4_proc_renew, | 6409 | .renew_lease = nfs4_proc_renew, |
6219 | }; | 6410 | }; |
6220 | 6411 | ||
6221 | #if defined(CONFIG_NFS_V4_1) | 6412 | #if defined(CONFIG_NFS_V4_1) |
6222 | struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = { | 6413 | static const struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = { |
6223 | .sched_state_renewal = nfs41_proc_async_sequence, | 6414 | .sched_state_renewal = nfs41_proc_async_sequence, |
6224 | .get_state_renewal_cred_locked = nfs4_get_machine_cred_locked, | 6415 | .get_state_renewal_cred_locked = nfs4_get_machine_cred_locked, |
6225 | .renew_lease = nfs4_proc_sequence, | 6416 | .renew_lease = nfs4_proc_sequence, |
@@ -6229,7 +6420,7 @@ struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = { | |||
6229 | static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | 6420 | static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { |
6230 | .minor_version = 0, | 6421 | .minor_version = 0, |
6231 | .call_sync = _nfs4_call_sync, | 6422 | .call_sync = _nfs4_call_sync, |
6232 | .validate_stateid = nfs4_validate_delegation_stateid, | 6423 | .match_stateid = nfs4_match_stateid, |
6233 | .find_root_sec = nfs4_find_root_sec, | 6424 | .find_root_sec = nfs4_find_root_sec, |
6234 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, | 6425 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, |
6235 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, | 6426 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, |
@@ -6240,7 +6431,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
6240 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | 6431 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { |
6241 | .minor_version = 1, | 6432 | .minor_version = 1, |
6242 | .call_sync = _nfs4_call_sync_session, | 6433 | .call_sync = _nfs4_call_sync_session, |
6243 | .validate_stateid = nfs41_validate_delegation_stateid, | 6434 | .match_stateid = nfs41_match_stateid, |
6244 | .find_root_sec = nfs41_find_root_sec, | 6435 | .find_root_sec = nfs41_find_root_sec, |
6245 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 6436 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
6246 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | 6437 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, |
@@ -6280,9 +6471,11 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
6280 | .create = nfs4_proc_create, | 6471 | .create = nfs4_proc_create, |
6281 | .remove = nfs4_proc_remove, | 6472 | .remove = nfs4_proc_remove, |
6282 | .unlink_setup = nfs4_proc_unlink_setup, | 6473 | .unlink_setup = nfs4_proc_unlink_setup, |
6474 | .unlink_rpc_prepare = nfs4_proc_unlink_rpc_prepare, | ||
6283 | .unlink_done = nfs4_proc_unlink_done, | 6475 | .unlink_done = nfs4_proc_unlink_done, |
6284 | .rename = nfs4_proc_rename, | 6476 | .rename = nfs4_proc_rename, |
6285 | .rename_setup = nfs4_proc_rename_setup, | 6477 | .rename_setup = nfs4_proc_rename_setup, |
6478 | .rename_rpc_prepare = nfs4_proc_rename_rpc_prepare, | ||
6286 | .rename_done = nfs4_proc_rename_done, | 6479 | .rename_done = nfs4_proc_rename_done, |
6287 | .link = nfs4_proc_link, | 6480 | .link = nfs4_proc_link, |
6288 | .symlink = nfs4_proc_symlink, | 6481 | .symlink = nfs4_proc_symlink, |
@@ -6296,8 +6489,10 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
6296 | .set_capabilities = nfs4_server_capabilities, | 6489 | .set_capabilities = nfs4_server_capabilities, |
6297 | .decode_dirent = nfs4_decode_dirent, | 6490 | .decode_dirent = nfs4_decode_dirent, |
6298 | .read_setup = nfs4_proc_read_setup, | 6491 | .read_setup = nfs4_proc_read_setup, |
6492 | .read_rpc_prepare = nfs4_proc_read_rpc_prepare, | ||
6299 | .read_done = nfs4_read_done, | 6493 | .read_done = nfs4_read_done, |
6300 | .write_setup = nfs4_proc_write_setup, | 6494 | .write_setup = nfs4_proc_write_setup, |
6495 | .write_rpc_prepare = nfs4_proc_write_rpc_prepare, | ||
6301 | .write_done = nfs4_write_done, | 6496 | .write_done = nfs4_write_done, |
6302 | .commit_setup = nfs4_proc_commit_setup, | 6497 | .commit_setup = nfs4_proc_commit_setup, |
6303 | .commit_done = nfs4_commit_done, | 6498 | .commit_done = nfs4_commit_done, |
@@ -6321,6 +6516,10 @@ const struct xattr_handler *nfs4_xattr_handlers[] = { | |||
6321 | NULL | 6516 | NULL |
6322 | }; | 6517 | }; |
6323 | 6518 | ||
6519 | module_param(max_session_slots, ushort, 0644); | ||
6520 | MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " | ||
6521 | "requests the client will negotiate"); | ||
6522 | |||
6324 | /* | 6523 | /* |
6325 | * Local variables: | 6524 | * Local variables: |
6326 | * c-basic-offset: 8 | 6525 | * c-basic-offset: 8 |