|
@@ -575,6 +575,7 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
|
|
|
stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
|
|
|
/* Will be incremented before return to client: */
|
|
|
atomic_set(&stid->sc_count, 1);
|
|
|
+ spin_lock_init(&stid->sc_lock);
|
|
|
|
|
|
/*
|
|
|
* It shouldn't be a problem to reuse an opaque stateid value.
|
|
@@ -745,6 +746,18 @@ nfs4_put_stid(struct nfs4_stid *s)
|
|
|
put_nfs4_file(fp);
|
|
|
}
|
|
|
|
|
|
+void
|
|
|
+nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid)
|
|
|
+{
|
|
|
+ stateid_t *src = &stid->sc_stateid;
|
|
|
+
|
|
|
+ spin_lock(&stid->sc_lock);
|
|
|
+ if (unlikely(++src->si_generation == 0))
|
|
|
+ src->si_generation = 1;
|
|
|
+ memcpy(dst, src, sizeof(*dst));
|
|
|
+ spin_unlock(&stid->sc_lock);
|
|
|
+}
|
|
|
+
|
|
|
static void nfs4_put_deleg_lease(struct nfs4_file *fp)
|
|
|
{
|
|
|
struct file *filp = NULL;
|
|
@@ -4221,8 +4234,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
|
|
if (stp->st_clnt_odstate == open->op_odstate)
|
|
|
open->op_odstate = NULL;
|
|
|
}
|
|
|
- update_stateid(&stp->st_stid.sc_stateid);
|
|
|
- memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
|
|
|
+ nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
|
|
|
up_read(&stp->st_rwsem);
|
|
|
|
|
|
if (nfsd4_has_session(&resp->cstate)) {
|
|
@@ -4925,8 +4937,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
goto put_stateid;
|
|
|
}
|
|
|
oo->oo_flags |= NFS4_OO_CONFIRMED;
|
|
|
- update_stateid(&stp->st_stid.sc_stateid);
|
|
|
- memcpy(&oc->oc_resp_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
|
|
|
+ nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid);
|
|
|
up_write(&stp->st_rwsem);
|
|
|
dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
|
|
|
__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
|
|
@@ -4999,11 +5010,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
|
|
|
goto put_stateid;
|
|
|
}
|
|
|
nfs4_stateid_downgrade(stp, od->od_share_access);
|
|
|
-
|
|
|
reset_union_bmap_deny(od->od_share_deny, stp);
|
|
|
-
|
|
|
- update_stateid(&stp->st_stid.sc_stateid);
|
|
|
- memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
|
|
|
+ nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid);
|
|
|
status = nfs_ok;
|
|
|
put_stateid:
|
|
|
up_write(&stp->st_rwsem);
|
|
@@ -5058,8 +5066,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
nfsd4_bump_seqid(cstate, status);
|
|
|
if (status)
|
|
|
goto out;
|
|
|
- update_stateid(&stp->st_stid.sc_stateid);
|
|
|
- memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
|
|
|
+ nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid);
|
|
|
up_write(&stp->st_rwsem);
|
|
|
|
|
|
nfsd4_close_open_stateid(stp);
|
|
@@ -5542,9 +5549,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
|
|
|
switch (-err) {
|
|
|
case 0: /* success! */
|
|
|
- update_stateid(&lock_stp->st_stid.sc_stateid);
|
|
|
- memcpy(&lock->lk_resp_stateid, &lock_stp->st_stid.sc_stateid,
|
|
|
- sizeof(stateid_t));
|
|
|
+ nfs4_inc_and_copy_stateid(&lock->lk_resp_stateid, &lock_stp->st_stid);
|
|
|
status = 0;
|
|
|
break;
|
|
|
case (EAGAIN): /* conflock holds conflicting lock */
|
|
@@ -5736,8 +5741,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
|
|
|
goto out_nfserr;
|
|
|
}
|
|
|
- update_stateid(&stp->st_stid.sc_stateid);
|
|
|
- memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
|
|
|
+ nfs4_inc_and_copy_stateid(&locku->lu_stateid, &stp->st_stid);
|
|
|
fput:
|
|
|
fput(filp);
|
|
|
put_stateid:
|