diff options
author | Robert Mastors <Robert.Mastors@Sun.COM> | 2009-07-14 19:08:57 -0500 |
---|---|---|
committer | Robert Mastors <Robert.Mastors@Sun.COM> | 2009-07-14 19:08:57 -0500 |
commit | 14f41b92b939b0941f725a4e3a65b76005ea33e0 (patch) | |
tree | 2339dbf5bfff8e1247734528e56632e410b57b20 /usr/src | |
parent | 32c66a4da4528e641a7f3b223c32df190340fe1c (diff) | |
download | illumos-gate-14f41b92b939b0941f725a4e3a65b76005ea33e0.tar.gz |
6858854 jurassic panicked in rfs4_release_share_lock_state; fix for 6711844 suspected
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs4_srv.c | 81 | ||||
-rw-r--r-- | usr/src/uts/common/nfs/nfs4.h | 2 |
2 files changed, 53 insertions, 30 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c index 5315f716b6..990a1d9d0a 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_srv.c +++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c @@ -6676,6 +6676,21 @@ rfs4_do_open(struct compound_state *cs, struct svc_req *req, rfs4_recall_deleg(fp, FALSE, sp->rs_owner->ro_client); delay(NFS4_DELEGATION_CONFLICT_DELAY); rfs4_dbe_lock(sp->rs_dbe); + + /* if state closed while lock was dropped */ + if (sp->rs_closed) { + if (dmodes || amodes) + (void) rfs4_unshare(sp); + rfs4_dbe_unlock(sp->rs_dbe); + rfs4_file_rele(fp); + /* Not a fully formed open; "close" it */ + if (screate == TRUE) + rfs4_state_close(sp, FALSE, FALSE, cs->cr); + rfs4_state_rele(sp); + resp->status = NFS4ERR_OLD_STATEID; + return; + } + rfs4_dbe_lock(fp->rf_dbe); /* Let's see if the delegation was returned */ if (rfs4_check_recall(sp, access)) { @@ -6743,6 +6758,7 @@ rfs4_do_open(struct compound_state *cs, struct svc_req *req, fflags |= FWRITE; vn_open_upgrade(cs->vp, fflags); } + sp->rs_opened = TRUE; if (dmodes & OPEN4_SHARE_DENY_READ) fp->rf_deny_read++; @@ -8183,35 +8199,6 @@ rfs4_release_share_lock_state(rfs4_state_t *sp, cred_t *cr, int fflags = 0; /* - * Decrement the count for each access and deny bit that this - * state has contributed to the file. If the file counts go to zero - * clear the appropriate bit in the appropriate mask. - */ - - if (sp->rs_share_access & OPEN4_SHARE_ACCESS_READ) { - fp->rf_access_read--; - fflags |= FREAD; - if (fp->rf_access_read == 0) - fp->rf_share_access &= ~OPEN4_SHARE_ACCESS_READ; - } - if (sp->rs_share_access & OPEN4_SHARE_ACCESS_WRITE) { - fp->rf_access_write--; - fflags |= FWRITE; - if (fp->rf_access_write == 0) - fp->rf_share_access &= ~OPEN4_SHARE_ACCESS_WRITE; - } - if (sp->rs_share_deny & OPEN4_SHARE_DENY_READ) { - fp->rf_deny_read--; - if (fp->rf_deny_read == 0) - fp->rf_share_deny &= ~OPEN4_SHARE_DENY_READ; - } - if (sp->rs_share_deny & OPEN4_SHARE_DENY_WRITE) { - fp->rf_deny_write--; - if (fp->rf_deny_write == 0) - fp->rf_share_deny &= ~OPEN4_SHARE_DENY_WRITE; - } - - /* * If this call is part of the larger closing down of client * state then it is just easier to release all locks * associated with this client instead of going through each @@ -8280,7 +8267,41 @@ rfs4_release_share_lock_state(rfs4_state_t *sp, cred_t *cr, if (sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID) (void) rfs4_unshare(sp); - (void) VOP_CLOSE(fp->rf_vp, fflags, 1, (offset_t)0, cr, NULL); + if (sp->rs_opened) { + /* + * Decrement the count for each access and deny bit that this + * state has contributed to the file. + * If the file counts go to zero + * clear the appropriate bit in the appropriate mask. + */ + if (sp->rs_share_access & OPEN4_SHARE_ACCESS_READ) { + fp->rf_access_read--; + fflags |= FREAD; + if (fp->rf_access_read == 0) + fp->rf_share_access &= ~OPEN4_SHARE_ACCESS_READ; + } + if (sp->rs_share_access & OPEN4_SHARE_ACCESS_WRITE) { + fp->rf_access_write--; + fflags |= FWRITE; + if (fp->rf_access_write == 0) + fp->rf_share_access &= + ~OPEN4_SHARE_ACCESS_WRITE; + } + if (sp->rs_share_deny & OPEN4_SHARE_DENY_READ) { + fp->rf_deny_read--; + if (fp->rf_deny_read == 0) + fp->rf_share_deny &= ~OPEN4_SHARE_DENY_READ; + } + if (sp->rs_share_deny & OPEN4_SHARE_DENY_WRITE) { + fp->rf_deny_write--; + if (fp->rf_deny_write == 0) + fp->rf_share_deny &= ~OPEN4_SHARE_DENY_WRITE; + } + + (void) VOP_CLOSE(fp->rf_vp, fflags, 1, (offset_t)0, cr, NULL); + + sp->rs_opened = FALSE; + } } /* diff --git a/usr/src/uts/common/nfs/nfs4.h b/usr/src/uts/common/nfs/nfs4.h index d113ff6f83..9e489a7c06 100644 --- a/usr/src/uts/common/nfs/nfs4.h +++ b/usr/src/uts/common/nfs/nfs4.h @@ -545,6 +545,7 @@ typedef struct rfs4_openowner { * finfo - reference to the open file for this state * share_access - how did the openowner OPEN the file (access) * share_deny - how did the openowner OPEN the file (deny) + * opened - has VOP_OPEN been done * closed - has this file been closed? * lostatelist - root of list of lo_state associated with this state/file * node - node for state struct list of states @@ -556,6 +557,7 @@ typedef struct rfs4_state { struct rfs4_file *rs_finfo; uint32_t rs_share_access; uint32_t rs_share_deny; + unsigned rs_opened:1; unsigned rs_closed:1; list_t rs_lostatelist; list_node_t rs_node; |