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

Configure Feed

Select the types of activity you want to include in your feed.

NFSv4: ensure the open stateid seqid doesn't go backwards

We have observed an NFSv4 client receiving a LOCK reply with a status of
NFS4ERR_OLD_STATEID and subsequently retrying the LOCK request with an
earlier seqid value in the stateid. As this was for a new lockowner,
that would imply that nfs_set_open_stateid_locked() had updated the open
stateid seqid with an earlier value.

Looking at nfs_set_open_stateid_locked(), if the incoming seqid is out
of sequence, the task will sleep on the state->waitq for up to 5
seconds. If the task waits for the full 5 seconds, then after finishing
the wait it'll update the open stateid seqid with whatever value the
incoming seqid has. If there are multiple waiters in this scenario,
then the last one to perform said update may not be the one with the
highest seqid.

Add a check to ensure that the seqid can only be incremented, and add a
tracepoint to indicate when old seqids are skipped.

Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Reviewed-by: Benjamin Coddington <bcodding@hammerspace.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

authored by

Scott Mayhew and committed by
Trond Myklebust
2e47c3cc 0f900f11

+12 -2
+11 -2
fs/nfs/nfs4proc.c
··· 1780 1780 if (nfs_stateid_is_sequential(state, stateid)) 1781 1781 break; 1782 1782 1783 - if (status) 1784 - break; 1783 + if (status) { 1784 + if (nfs4_stateid_match_other(stateid, &state->open_stateid) && 1785 + !nfs4_stateid_is_newer(stateid, &state->open_stateid)) { 1786 + trace_nfs4_open_stateid_update_skip(state->inode, 1787 + stateid, status); 1788 + return; 1789 + } else { 1790 + break; 1791 + } 1792 + } 1793 + 1785 1794 /* Rely on seqids for serialisation with NFSv4.0 */ 1786 1795 if (!nfs4_has_session(NFS_SERVER(state->inode)->nfs_client)) 1787 1796 break;
+1
fs/nfs/nfs4trace.h
··· 1353 1353 DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_delegreturn); 1354 1354 DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update); 1355 1355 DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_wait); 1356 + DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_skip); 1356 1357 DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_close_stateid_update_wait); 1357 1358 1358 1359 DECLARE_EVENT_CLASS(nfs4_getattr_event,