Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Kinglong Mee and committed by
J. Bruce Fields
276f03e3 4399396e

+13 -2
+12 -2
fs/nfsd/nfs4callback.c
··· 455 455 if (unlikely(status || cb->cb_status)) 456 456 return status; 457 457 458 + cb->cb_update_seq_nr = true; 458 459 return decode_cb_sequence4resok(xdr, cb); 459 460 } 460 461 ··· 876 875 u32 minorversion = clp->cl_minorversion; 877 876 878 877 cb->cb_minorversion = minorversion; 878 + cb->cb_update_seq_nr = false; 879 879 cb->cb_status = 0; 880 880 if (minorversion) { 881 881 if (!nfsd41_cb_get_slot(clp, task)) ··· 894 892 clp->cl_minorversion); 895 893 896 894 if (clp->cl_minorversion) { 897 - /* No need for lock, access serialized in nfsd4_cb_prepare */ 898 - if (!task->tk_status) 895 + /* 896 + * No need for lock, access serialized in nfsd4_cb_prepare 897 + * 898 + * RFC5661 20.9.3 899 + * If CB_SEQUENCE returns an error, then the state of the slot 900 + * (sequence ID, cached reply) MUST NOT change. 901 + */ 902 + if (cb->cb_update_seq_nr) 899 903 ++clp->cl_cb_session->se_cb_seq_nr; 904 + 900 905 clear_bit(0, &clp->cl_cb_slot_busy); 901 906 rpc_wake_up_next(&clp->cl_cb_waitq); 902 907 dprintk("%s: freed slot, new seqid=%d\n", __func__, ··· 1100 1091 cb->cb_ops = ops; 1101 1092 INIT_WORK(&cb->cb_work, nfsd4_run_cb_work); 1102 1093 cb->cb_status = 0; 1094 + cb->cb_update_seq_nr = false; 1103 1095 cb->cb_need_restart = false; 1104 1096 } 1105 1097
+1
fs/nfsd/state.h
··· 68 68 struct nfsd4_callback_ops *cb_ops; 69 69 struct work_struct cb_work; 70 70 int cb_status; 71 + bool cb_update_seq_nr; 71 72 bool cb_need_restart; 72 73 }; 73 74