summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorjwahlig <none@none>2006-05-23 09:19:33 -0700
committerjwahlig <none@none>2006-05-23 09:19:33 -0700
commitfd93bfc32e86a61b0e7f02057aac2979479364e3 (patch)
treeab28fdab49610bd03cc6466dc2d2ba96da8b3013 /usr/src
parent60c807700988885656502665e0cf8afd4b4346f7 (diff)
downloadillumos-joyent-fd93bfc32e86a61b0e7f02057aac2979479364e3.tar.gz
6413702 NFS Server is leaking SHRLOCK state.
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv.c81
1 files changed, 44 insertions, 37 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c
index 0646bace0f..cd741c18c0 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c
@@ -6183,17 +6183,7 @@ rfs4_do_open(struct compound_state *cs, struct svc_req *req,
return;
}
- /*
- * Check for conflicts in deny and access before checking for
- * conflicts in delegation. We don't want to recall a
- * delegation based on an open that will eventually fail based
- * on shares modes.
- */
-
- shr.s_access = (short)access;
- shr.s_deny = (short)deny;
- shr.s_pid = rfs4_dbe_getid(oo->dbe);
-
+ /* try to get the sysid before continuing */
if ((status = rfs4_client_sysid(oo->client, &sysid)) != NFS4_OK) {
resp->status = status;
rfs4_file_rele(file);
@@ -6203,42 +6193,59 @@ rfs4_do_open(struct compound_state *cs, struct svc_req *req,
rfs4_state_rele(state);
return;
}
- shr.s_sysid = sysid;
- shr_loco.sl_pid = shr.s_pid;
- shr_loco.sl_id = shr.s_sysid;
- shr.s_owner = (caddr_t)&shr_loco;
- shr.s_own_len = sizeof (shr_loco);
- fflags = 0;
- if (access & OPEN4_SHARE_ACCESS_READ)
- fflags |= FREAD;
- if (access & OPEN4_SHARE_ACCESS_WRITE)
- fflags |= FWRITE;
+ /*
+ * Calculate the new deny and access mode that this open is adding to
+ * the file for this open owner;
+ */
+ dmodes = (deny & ~state->share_deny);
+ amodes = (access & ~state->share_access);
- if ((err = vop_shrlock(cs->vp, F_SHARE, &shr, fflags)) != 0) {
+ /*
+ * Check to see the client has already sent an open for this
+ * open owner on this file with the same share/deny modes.
+ * If so, we don't need to check for a conflict and we don't
+ * need to add another shrlock. If not, then we need to
+ * check for conflicts in deny and access before checking for
+ * conflicts in delegation. We don't want to recall a
+ * delegation based on an open that will eventually fail based
+ * on shares modes.
+ */
- resp->status = err == EAGAIN ?
- NFS4ERR_SHARE_DENIED : puterrno4(err);
+ if (dmodes || amodes) {
+ shr.s_access = (short)access;
+ shr.s_deny = (short)deny;
+ shr.s_pid = rfs4_dbe_getid(oo->dbe);
+ shr.s_sysid = sysid;
+ shr_loco.sl_pid = shr.s_pid;
+ shr_loco.sl_id = shr.s_sysid;
+ shr.s_owner = (caddr_t)&shr_loco;
+ shr.s_own_len = sizeof (shr_loco);
- rfs4_file_rele(file);
- /* Not a fully formed open; "close" it */
- if (screate == TRUE)
- rfs4_state_close(state, FALSE, FALSE, cs->cr);
- rfs4_state_rele(state);
- return;
+ fflags = 0;
+ if (access & OPEN4_SHARE_ACCESS_READ)
+ fflags |= FREAD;
+ if (access & OPEN4_SHARE_ACCESS_WRITE)
+ fflags |= FWRITE;
+
+ if ((err = vop_shrlock(cs->vp, F_SHARE, &shr, fflags)) != 0) {
+
+ resp->status = err == EAGAIN ?
+ NFS4ERR_SHARE_DENIED : puterrno4(err);
+
+ rfs4_file_rele(file);
+ /* Not a fully formed open; "close" it */
+ if (screate == TRUE)
+ rfs4_state_close(state, FALSE, FALSE, cs->cr);
+ rfs4_state_rele(state);
+ return;
+ }
}
rfs4_dbe_lock(state->dbe);
rfs4_dbe_lock(file->dbe);
/*
- * Calculate the new deny and access mode that this open is adding to
- * the file for this open owner;
- */
- dmodes = (deny & ~state->share_deny);
- amodes = (access & ~state->share_access);
-
- /*
* Check to see if this file is delegated and if so, if a
* recall needs to be done.
*/