diff options
author | jwahlig <none@none> | 2006-05-23 09:19:33 -0700 |
---|---|---|
committer | jwahlig <none@none> | 2006-05-23 09:19:33 -0700 |
commit | fd93bfc32e86a61b0e7f02057aac2979479364e3 (patch) | |
tree | ab28fdab49610bd03cc6466dc2d2ba96da8b3013 /usr/src | |
parent | 60c807700988885656502665e0cf8afd4b4346f7 (diff) | |
download | illumos-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.c | 81 |
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. */ |