aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/nfsclient/nfs_clrpcops.c
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2021-10-12 04:58:24 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2021-10-12 04:58:24 +0000
commit120b20bdf49630cf2a7dbc5f93b9e985e1f4f198 (patch)
tree591a29772641cdc3fe30170a0c54c408cb868237 /sys/fs/nfsclient/nfs_clrpcops.c
parent2d827c065a1c6ed12d48fc71ab41443e2de0936f (diff)
downloadsrc-120b20bdf49630cf2a7dbc5f93b9e985e1f4f198.tar.gz
src-120b20bdf49630cf2a7dbc5f93b9e985e1f4f198.zip
nfscl: Fix a deadlock related to the NFSv4 clientID lock
Without this patch, it is possible for a process doing an NFSv4 Open/create of a file to block to allow another process to acquire the exclusive lock on the clientID when holding a shared lock on the clientID. As such, both processes deadlock, with one wanting the exclusive lock, while the other holds the shared lock. This deadlock is unlikely to occur unless delegations are in use on the NFSv4 mount. This patch fixes the problem by not deferring to the process waiting for the exclusive lock when a shared lock (reference cnt) is already held by the process. This problem was detected during a recent NFSv4 interoperability testing event held by the IETF working group. MFC after: 1 week
Diffstat (limited to 'sys/fs/nfsclient/nfs_clrpcops.c')
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 0a3826ed8dc1..66e093505ca3 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -392,7 +392,7 @@ else printf(" fhl=0\n");
do {
dp = NULL;
error = nfscl_open(vp, nfhp->nfh_fh, nfhp->nfh_len, mode, 1,
- cred, p, NULL, &op, &newone, &ret, 1);
+ cred, p, NULL, &op, &newone, &ret, 1, true);
if (error) {
return (error);
}
@@ -1579,7 +1579,7 @@ nfsrpc_lookup(vnode_t dvp, char *name, int len, struct ucred *cred,
goto nfsmout;
}
ret = nfscl_open(dvp, (*nfhpp)->nfh_fh, (*nfhpp)->nfh_len,
- openmode, 0, cred, p, NULL, &op, &newone, &retop, 1);
+ openmode, 0, cred, p, NULL, &op, &newone, &retop, 1, true);
if (ret != 0)
goto nfsmout;
if (newone != 0) {
@@ -2307,7 +2307,7 @@ nfsrpc_create(vnode_t dvp, char *name, int namelen, struct vattr *vap,
dp = NULL;
error = nfscl_open(dvp, NULL, 0, (NFSV4OPEN_ACCESSWRITE |
NFSV4OPEN_ACCESSREAD), 0, cred, p, &owp, NULL, &newone,
- NULL, 1);
+ NULL, 1, true);
if (error)
return (error);
if (nmp->nm_clp != NULL)
@@ -2593,7 +2593,7 @@ nfsrpc_createv4(vnode_t dvp, char *name, int namelen, struct vattr *vap,
*/
error = nfscl_open(dvp, nfhp->nfh_fh, nfhp->nfh_len,
(NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), 0,
- cred, p, NULL, &op, &newone, NULL, 0);
+ cred, p, NULL, &op, &newone, NULL, 0, false);
if (error)
goto nfsmout;
op->nfso_stateid = stateid;
@@ -4214,7 +4214,7 @@ nfsrpc_advlock(vnode_t vp, off_t size, int op, struct flock *fl,
do {
nd->nd_repstat = 0;
if (op == F_GETLK) {
- error = nfscl_getcl(vp->v_mount, cred, p, false, &clp);
+ error = nfscl_getcl(vp->v_mount, cred, p, false, true, &clp);
if (error)
return (error);
error = nfscl_lockt(vp, clp, off, len, fl, p, id, flags);
@@ -4231,7 +4231,7 @@ nfsrpc_advlock(vnode_t vp, off_t size, int op, struct flock *fl,
* We must loop around for all lockowner cases.
*/
callcnt = 0;
- error = nfscl_getcl(vp->v_mount, cred, p, false, &clp);
+ error = nfscl_getcl(vp->v_mount, cred, p, false, true, &clp);
if (error)
return (error);
do {
@@ -8177,7 +8177,7 @@ nfsrpc_createlayout(vnode_t dvp, char *name, int namelen, struct vattr *vap,
*/
error = nfscl_open(dvp, nfhp->nfh_fh, nfhp->nfh_len,
(NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), 0,
- cred, p, NULL, &op, &newone, NULL, 0);
+ cred, p, NULL, &op, &newone, NULL, 0, false);
if (error != 0)
goto nfsmout;
op->nfso_stateid = stateid;