diff options
| author | Rick Macklem <rmacklem@FreeBSD.org> | 2021-10-13 00:21:01 +0000 |
|---|---|---|
| committer | Rick Macklem <rmacklem@FreeBSD.org> | 2021-10-20 01:40:27 +0000 |
| commit | 00595201ad4de48a1537d43c77445873df6028db (patch) | |
| tree | 10fc11cf3fc461fc6f0a71c1ba56c95b1366d9c5 | |
| parent | 701eb03cc0dca907de872a41407b8487c38429fc (diff) | |
nfscl: Fix another deadlock related to the NFSv4 clientID lock
Without this patch, it is possible to hang the NFSv4 client,
when a rename/remove is being done on a file where the client
holds a delegation, if pNFS is being used. For a delegation
to be returned, dirty data blocks must be flushed to the NFSv4
server. When pNFS is in use, a shared lock on the clientID
must be acquired while doing a write to the DS(s).
However, if rename/remove is doing the delegation return
an exclusive lock will be acquired on the clientID, preventing
the write to the DS(s) from acquiring a shared lock on the clientID.
This patch stops rename/remove from doing a delegation return
if pNFS is enabled. Since doing delegation return in the same
compound as rename/remove is only an optimization, not doing
so should not cause problems.
This problem was detected during a recent NFSv4 interoperability
testing event held by the IETF working group.
(cherry picked from commit b82168e657d378ff86ea18c4f03b98aac9ee9bb3)
| -rw-r--r-- | sys/fs/nfsclient/nfs_clstate.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index 5aebd68dd9e1..276e94002d34 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -4609,6 +4609,8 @@ nfscl_removedeleg(vnode_t vp, NFSPROC_T *p, nfsv4stateid_t *stp) int igotlock = 0, triedrecall = 0, needsrecall, retcnt = 0, islept; nmp = VFSTONFS(vp->v_mount); + if (NFSHASPNFS(nmp)) + return (retcnt); NFSLOCKMNT(nmp); if ((nmp->nm_privflag & NFSMNTP_DELEGISSUED) == 0) { NFSUNLOCKMNT(nmp); @@ -4714,6 +4716,8 @@ nfscl_renamedeleg(vnode_t fvp, nfsv4stateid_t *fstp, int *gotfdp, vnode_t tvp, nmp = VFSTONFS(fvp->v_mount); *gotfdp = 0; *gottdp = 0; + if (NFSHASPNFS(nmp)) + return (retcnt); NFSLOCKCLSTATE(); /* * Loop around waiting for: |
