diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 117 |
1 files changed, 56 insertions, 61 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 557a5d636183..77c6e2d3f3fc 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -730,13 +730,25 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | |||
730 | res->sr_slot = NULL; | 730 | res->sr_slot = NULL; |
731 | } | 731 | } |
732 | 732 | ||
733 | static void nfs4_slot_sequence_record_sent(struct nfs4_slot *slot, | ||
734 | u32 seqnr) | ||
735 | { | ||
736 | if ((s32)(seqnr - slot->seq_nr_highest_sent) > 0) | ||
737 | slot->seq_nr_highest_sent = seqnr; | ||
738 | } | ||
739 | static void nfs4_slot_sequence_acked(struct nfs4_slot *slot, | ||
740 | u32 seqnr) | ||
741 | { | ||
742 | slot->seq_nr_highest_sent = seqnr; | ||
743 | slot->seq_nr_last_acked = seqnr; | ||
744 | } | ||
745 | |||
733 | static int nfs41_sequence_process(struct rpc_task *task, | 746 | static int nfs41_sequence_process(struct rpc_task *task, |
734 | struct nfs4_sequence_res *res) | 747 | struct nfs4_sequence_res *res) |
735 | { | 748 | { |
736 | struct nfs4_session *session; | 749 | struct nfs4_session *session; |
737 | struct nfs4_slot *slot = res->sr_slot; | 750 | struct nfs4_slot *slot = res->sr_slot; |
738 | struct nfs_client *clp; | 751 | struct nfs_client *clp; |
739 | bool interrupted = false; | ||
740 | int ret = 1; | 752 | int ret = 1; |
741 | 753 | ||
742 | if (slot == NULL) | 754 | if (slot == NULL) |
@@ -747,16 +759,12 @@ static int nfs41_sequence_process(struct rpc_task *task, | |||
747 | 759 | ||
748 | session = slot->table->session; | 760 | session = slot->table->session; |
749 | 761 | ||
750 | if (slot->interrupted) { | ||
751 | if (res->sr_status != -NFS4ERR_DELAY) | ||
752 | slot->interrupted = 0; | ||
753 | interrupted = true; | ||
754 | } | ||
755 | |||
756 | trace_nfs4_sequence_done(session, res); | 762 | trace_nfs4_sequence_done(session, res); |
757 | /* Check the SEQUENCE operation status */ | 763 | /* Check the SEQUENCE operation status */ |
758 | switch (res->sr_status) { | 764 | switch (res->sr_status) { |
759 | case 0: | 765 | case 0: |
766 | /* Mark this sequence number as having been acked */ | ||
767 | nfs4_slot_sequence_acked(slot, slot->seq_nr); | ||
760 | /* Update the slot's sequence and clientid lease timer */ | 768 | /* Update the slot's sequence and clientid lease timer */ |
761 | slot->seq_done = 1; | 769 | slot->seq_done = 1; |
762 | clp = session->clp; | 770 | clp = session->clp; |
@@ -771,9 +779,9 @@ static int nfs41_sequence_process(struct rpc_task *task, | |||
771 | * sr_status remains 1 if an RPC level error occurred. | 779 | * sr_status remains 1 if an RPC level error occurred. |
772 | * The server may or may not have processed the sequence | 780 | * The server may or may not have processed the sequence |
773 | * operation.. | 781 | * operation.. |
774 | * Mark the slot as having hosted an interrupted RPC call. | ||
775 | */ | 782 | */ |
776 | slot->interrupted = 1; | 783 | nfs4_slot_sequence_record_sent(slot, slot->seq_nr); |
784 | slot->seq_done = 1; | ||
777 | goto out; | 785 | goto out; |
778 | case -NFS4ERR_DELAY: | 786 | case -NFS4ERR_DELAY: |
779 | /* The server detected a resend of the RPC call and | 787 | /* The server detected a resend of the RPC call and |
@@ -784,6 +792,7 @@ static int nfs41_sequence_process(struct rpc_task *task, | |||
784 | __func__, | 792 | __func__, |
785 | slot->slot_nr, | 793 | slot->slot_nr, |
786 | slot->seq_nr); | 794 | slot->seq_nr); |
795 | nfs4_slot_sequence_acked(slot, slot->seq_nr); | ||
787 | goto out_retry; | 796 | goto out_retry; |
788 | case -NFS4ERR_RETRY_UNCACHED_REP: | 797 | case -NFS4ERR_RETRY_UNCACHED_REP: |
789 | case -NFS4ERR_SEQ_FALSE_RETRY: | 798 | case -NFS4ERR_SEQ_FALSE_RETRY: |
@@ -791,6 +800,7 @@ static int nfs41_sequence_process(struct rpc_task *task, | |||
791 | * The server thinks we tried to replay a request. | 800 | * The server thinks we tried to replay a request. |
792 | * Retry the call after bumping the sequence ID. | 801 | * Retry the call after bumping the sequence ID. |
793 | */ | 802 | */ |
803 | nfs4_slot_sequence_acked(slot, slot->seq_nr); | ||
794 | goto retry_new_seq; | 804 | goto retry_new_seq; |
795 | case -NFS4ERR_BADSLOT: | 805 | case -NFS4ERR_BADSLOT: |
796 | /* | 806 | /* |
@@ -801,21 +811,28 @@ static int nfs41_sequence_process(struct rpc_task *task, | |||
801 | goto session_recover; | 811 | goto session_recover; |
802 | goto retry_nowait; | 812 | goto retry_nowait; |
803 | case -NFS4ERR_SEQ_MISORDERED: | 813 | case -NFS4ERR_SEQ_MISORDERED: |
814 | nfs4_slot_sequence_record_sent(slot, slot->seq_nr); | ||
804 | /* | 815 | /* |
805 | * Was the last operation on this sequence interrupted? | 816 | * Were one or more calls using this slot interrupted? |
806 | * If so, retry after bumping the sequence number. | 817 | * If the server never received the request, then our |
807 | */ | 818 | * transmitted slot sequence number may be too high. |
808 | if (interrupted) | ||
809 | goto retry_new_seq; | ||
810 | /* | ||
811 | * Could this slot have been previously retired? | ||
812 | * If so, then the server may be expecting seq_nr = 1! | ||
813 | */ | 819 | */ |
814 | if (slot->seq_nr != 1) { | 820 | if ((s32)(slot->seq_nr - slot->seq_nr_last_acked) > 1) { |
815 | slot->seq_nr = 1; | 821 | slot->seq_nr--; |
816 | goto retry_nowait; | 822 | goto retry_nowait; |
817 | } | 823 | } |
818 | goto session_recover; | 824 | /* |
825 | * RFC5661: | ||
826 | * A retry might be sent while the original request is | ||
827 | * still in progress on the replier. The replier SHOULD | ||
828 | * deal with the issue by returning NFS4ERR_DELAY as the | ||
829 | * reply to SEQUENCE or CB_SEQUENCE operation, but | ||
830 | * implementations MAY return NFS4ERR_SEQ_MISORDERED. | ||
831 | * | ||
832 | * Restart the search after a delay. | ||
833 | */ | ||
834 | slot->seq_nr = slot->seq_nr_highest_sent; | ||
835 | goto out_retry; | ||
819 | default: | 836 | default: |
820 | /* Just update the slot sequence no. */ | 837 | /* Just update the slot sequence no. */ |
821 | slot->seq_done = 1; | 838 | slot->seq_done = 1; |
@@ -906,17 +923,6 @@ static const struct rpc_call_ops nfs41_call_sync_ops = { | |||
906 | .rpc_call_done = nfs41_call_sync_done, | 923 | .rpc_call_done = nfs41_call_sync_done, |
907 | }; | 924 | }; |
908 | 925 | ||
909 | static void | ||
910 | nfs4_sequence_process_interrupted(struct nfs_client *client, | ||
911 | struct nfs4_slot *slot, const struct cred *cred) | ||
912 | { | ||
913 | struct rpc_task *task; | ||
914 | |||
915 | task = _nfs41_proc_sequence(client, cred, slot, true); | ||
916 | if (!IS_ERR(task)) | ||
917 | rpc_put_task_async(task); | ||
918 | } | ||
919 | |||
920 | #else /* !CONFIG_NFS_V4_1 */ | 926 | #else /* !CONFIG_NFS_V4_1 */ |
921 | 927 | ||
922 | static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res) | 928 | static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res) |
@@ -937,14 +943,6 @@ int nfs4_sequence_done(struct rpc_task *task, | |||
937 | } | 943 | } |
938 | EXPORT_SYMBOL_GPL(nfs4_sequence_done); | 944 | EXPORT_SYMBOL_GPL(nfs4_sequence_done); |
939 | 945 | ||
940 | static void | ||
941 | nfs4_sequence_process_interrupted(struct nfs_client *client, | ||
942 | struct nfs4_slot *slot, const struct cred *cred) | ||
943 | { | ||
944 | WARN_ON_ONCE(1); | ||
945 | slot->interrupted = 0; | ||
946 | } | ||
947 | |||
948 | #endif /* !CONFIG_NFS_V4_1 */ | 946 | #endif /* !CONFIG_NFS_V4_1 */ |
949 | 947 | ||
950 | static | 948 | static |
@@ -982,26 +980,19 @@ int nfs4_setup_sequence(struct nfs_client *client, | |||
982 | task->tk_timeout = 0; | 980 | task->tk_timeout = 0; |
983 | } | 981 | } |
984 | 982 | ||
985 | for (;;) { | 983 | spin_lock(&tbl->slot_tbl_lock); |
986 | spin_lock(&tbl->slot_tbl_lock); | 984 | /* The state manager will wait until the slot table is empty */ |
987 | /* The state manager will wait until the slot table is empty */ | 985 | if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged) |
988 | if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged) | 986 | goto out_sleep; |
989 | goto out_sleep; | ||
990 | |||
991 | slot = nfs4_alloc_slot(tbl); | ||
992 | if (IS_ERR(slot)) { | ||
993 | /* Try again in 1/4 second */ | ||
994 | if (slot == ERR_PTR(-ENOMEM)) | ||
995 | task->tk_timeout = HZ >> 2; | ||
996 | goto out_sleep; | ||
997 | } | ||
998 | spin_unlock(&tbl->slot_tbl_lock); | ||
999 | 987 | ||
1000 | if (likely(!slot->interrupted)) | 988 | slot = nfs4_alloc_slot(tbl); |
1001 | break; | 989 | if (IS_ERR(slot)) { |
1002 | nfs4_sequence_process_interrupted(client, | 990 | /* Try again in 1/4 second */ |
1003 | slot, task->tk_msg.rpc_cred); | 991 | if (slot == ERR_PTR(-ENOMEM)) |
992 | task->tk_timeout = HZ >> 2; | ||
993 | goto out_sleep; | ||
1004 | } | 994 | } |
995 | spin_unlock(&tbl->slot_tbl_lock); | ||
1005 | 996 | ||
1006 | nfs4_sequence_attach_slot(args, res, slot); | 997 | nfs4_sequence_attach_slot(args, res, slot); |
1007 | 998 | ||
@@ -1555,6 +1546,10 @@ static void nfs_clear_open_stateid(struct nfs4_state *state, | |||
1555 | 1546 | ||
1556 | static void nfs_set_open_stateid_locked(struct nfs4_state *state, | 1547 | static void nfs_set_open_stateid_locked(struct nfs4_state *state, |
1557 | const nfs4_stateid *stateid, nfs4_stateid *freeme) | 1548 | const nfs4_stateid *stateid, nfs4_stateid *freeme) |
1549 | __must_hold(&state->owner->so_lock) | ||
1550 | __must_hold(&state->seqlock) | ||
1551 | __must_hold(RCU) | ||
1552 | |||
1558 | { | 1553 | { |
1559 | DEFINE_WAIT(wait); | 1554 | DEFINE_WAIT(wait); |
1560 | int status = 0; | 1555 | int status = 0; |
@@ -5963,7 +5958,7 @@ out: | |||
5963 | /** | 5958 | /** |
5964 | * nfs4_proc_setclientid_confirm - Confirm client ID | 5959 | * nfs4_proc_setclientid_confirm - Confirm client ID |
5965 | * @clp: state data structure | 5960 | * @clp: state data structure |
5966 | * @res: result of a previous SETCLIENTID | 5961 | * @arg: result of a previous SETCLIENTID |
5967 | * @cred: credential to use for this call | 5962 | * @cred: credential to use for this call |
5968 | * | 5963 | * |
5969 | * Returns zero, a negative errno, or a negative NFS4ERR status code. | 5964 | * Returns zero, a negative errno, or a negative NFS4ERR status code. |
@@ -7527,7 +7522,7 @@ int nfs4_proc_fsid_present(struct inode *inode, const struct cred *cred) | |||
7527 | return status; | 7522 | return status; |
7528 | } | 7523 | } |
7529 | 7524 | ||
7530 | /** | 7525 | /* |
7531 | * If 'use_integrity' is true and the state managment nfs_client | 7526 | * If 'use_integrity' is true and the state managment nfs_client |
7532 | * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient | 7527 | * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient |
7533 | * and the machine credential as per RFC3530bis and RFC5661 Security | 7528 | * and the machine credential as per RFC3530bis and RFC5661 Security |
@@ -9219,7 +9214,7 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | |||
9219 | return status; | 9214 | return status; |
9220 | } | 9215 | } |
9221 | 9216 | ||
9222 | /** | 9217 | /* |
9223 | * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if | 9218 | * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if |
9224 | * possible) as per RFC3530bis and RFC5661 Security Considerations sections | 9219 | * possible) as per RFC3530bis and RFC5661 Security Considerations sections |
9225 | */ | 9220 | */ |
@@ -9484,7 +9479,7 @@ static const struct rpc_call_ops nfs41_free_stateid_ops = { | |||
9484 | * @server: server / transport on which to perform the operation | 9479 | * @server: server / transport on which to perform the operation |
9485 | * @stateid: state ID to release | 9480 | * @stateid: state ID to release |
9486 | * @cred: credential | 9481 | * @cred: credential |
9487 | * @is_recovery: set to true if this call needs to be privileged | 9482 | * @privileged: set to true if this call needs to be privileged |
9488 | * | 9483 | * |
9489 | * Note: this function is always asynchronous. | 9484 | * Note: this function is always asynchronous. |
9490 | */ | 9485 | */ |