aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKinglong Mee <kinglongmee@gmail.com>2015-06-02 06:59:25 -0400
committerJ. Bruce Fields <bfields@redhat.com>2015-06-04 16:51:30 -0400
commit276f03e3ba242ebf2cf201cc3c7058d2884912b7 (patch)
tree882bd87a72e38396f21739bf8196ebbf3ef521b3
parent4399396eecfc586a1d92e64fe49c3c899f080436 (diff)
nfsd: Update callback sequnce id only CB_SEQUENCE success
When testing pnfs layout, nfsd got error NFS4ERR_SEQ_MISORDERED. It is caused by nfs return NFS4ERR_DELAY before validate_seqid(), don't update the sequnce id, but nfsd updates the sequnce id !!! According to RFC5661 20.9.3, " If CB_SEQUENCE returns an error, then the state of the slot (sequence ID, cached reply) MUST NOT change. " Signed-off-by: Kinglong Mee <kinglongmee@gmail.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/nfs4callback.c14
-rw-r--r--fs/nfsd/state.h1
2 files changed, 13 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 8b1ac8d4f011..a49201835a97 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -455,6 +455,7 @@ static int decode_cb_sequence4res(struct xdr_stream *xdr,
455 if (unlikely(status || cb->cb_status)) 455 if (unlikely(status || cb->cb_status))
456 return status; 456 return status;
457 457
458 cb->cb_update_seq_nr = true;
458 return decode_cb_sequence4resok(xdr, cb); 459 return decode_cb_sequence4resok(xdr, cb);
459} 460}
460 461
@@ -875,6 +876,7 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
875 u32 minorversion = clp->cl_minorversion; 876 u32 minorversion = clp->cl_minorversion;
876 877
877 cb->cb_minorversion = minorversion; 878 cb->cb_minorversion = minorversion;
879 cb->cb_update_seq_nr = false;
878 cb->cb_status = 0; 880 cb->cb_status = 0;
879 if (minorversion) { 881 if (minorversion) {
880 if (!nfsd41_cb_get_slot(clp, task)) 882 if (!nfsd41_cb_get_slot(clp, task))
@@ -892,9 +894,16 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
892 clp->cl_minorversion); 894 clp->cl_minorversion);
893 895
894 if (clp->cl_minorversion) { 896 if (clp->cl_minorversion) {
895 /* No need for lock, access serialized in nfsd4_cb_prepare */ 897 /*
896 if (!task->tk_status) 898 * No need for lock, access serialized in nfsd4_cb_prepare
899 *
900 * RFC5661 20.9.3
901 * If CB_SEQUENCE returns an error, then the state of the slot
902 * (sequence ID, cached reply) MUST NOT change.
903 */
904 if (cb->cb_update_seq_nr)
897 ++clp->cl_cb_session->se_cb_seq_nr; 905 ++clp->cl_cb_session->se_cb_seq_nr;
906
898 clear_bit(0, &clp->cl_cb_slot_busy); 907 clear_bit(0, &clp->cl_cb_slot_busy);
899 rpc_wake_up_next(&clp->cl_cb_waitq); 908 rpc_wake_up_next(&clp->cl_cb_waitq);
900 dprintk("%s: freed slot, new seqid=%d\n", __func__, 909 dprintk("%s: freed slot, new seqid=%d\n", __func__,
@@ -1091,6 +1100,7 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
1091 cb->cb_ops = ops; 1100 cb->cb_ops = ops;
1092 INIT_WORK(&cb->cb_work, nfsd4_run_cb_work); 1101 INIT_WORK(&cb->cb_work, nfsd4_run_cb_work);
1093 cb->cb_status = 0; 1102 cb->cb_status = 0;
1103 cb->cb_update_seq_nr = false;
1094 cb->cb_need_restart = false; 1104 cb->cb_need_restart = false;
1095} 1105}
1096 1106
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index dbc4f85a5008..4ed7c2ae95eb 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -68,6 +68,7 @@ struct nfsd4_callback {
68 struct nfsd4_callback_ops *cb_ops; 68 struct nfsd4_callback_ops *cb_ops;
69 struct work_struct cb_work; 69 struct work_struct cb_work;
70 int cb_status; 70 int cb_status;
71 bool cb_update_seq_nr;
71 bool cb_need_restart; 72 bool cb_need_restart;
72}; 73};
73 74