summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv.c81
-rw-r--r--usr/src/uts/common/nfs/nfs4.h2
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;