@@ -2806,6 +2806,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
struct nfs4_openowner *oo = open->op_openowner;
+ atomic_inc(&stp->st_stid.sc_count);
stp->st_stid.sc_type = NFS4_OPEN_STID;
INIT_LIST_HEAD(&stp->st_locks);
list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
@@ -3111,6 +3112,7 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_ol_st
{
struct nfs4_ol_stateid *local;
struct nfs4_openowner *oo = open->op_openowner;
+ struct nfs4_ol_stateid *ret = NULL;
spin_lock(&fp->fi_lock);
list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
@@ -3119,13 +3121,17 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_ol_st
continue;
/* remember if we have seen this open owner */
if (local->st_stateowner == &oo->oo_owner)
- *stpp = local;
+ ret = local;
/* check for conflicting share reservations */
if (!test_share(local, open)) {
spin_unlock(&fp->fi_lock);
return nfserr_share_denied;
}
}
+ if (ret) {
+ atomic_inc(&ret->st_stid.sc_count);
+ *stpp = ret;
+ }
spin_unlock(&fp->fi_lock);
return nfs_ok;
}
@@ -3536,6 +3542,8 @@ out:
open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
if (dp)
nfs4_put_delegation(dp);
+ if (stp)
+ put_generic_stateid(stp);
return status;
}
Ensure that nfsd4_process_open2() keeps a reference to the open stateid until it is done working with it. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> --- fs/nfsd/nfs4state.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)