aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c117
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
733static 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}
739static 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
733static int nfs41_sequence_process(struct rpc_task *task, 746static 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
909static void
910nfs4_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
922static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res) 928static 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}
938EXPORT_SYMBOL_GPL(nfs4_sequence_done); 944EXPORT_SYMBOL_GPL(nfs4_sequence_done);
939 945
940static void
941nfs4_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
950static 948static
@@ -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
1556static void nfs_set_open_stateid_locked(struct nfs4_state *state, 1547static 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 */