diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 76 |
1 files changed, 35 insertions, 41 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 95202719a1fd..43903abd6189 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -990,6 +990,12 @@ release_all_access(struct nfs4_ol_stateid *stp) } } +static inline void nfs4_free_stateowner(struct nfs4_stateowner *sop) +{ + kfree(sop->so_owner.data); + sop->so_ops->so_free(sop); +} + static void nfs4_put_stateowner(struct nfs4_stateowner *sop) { struct nfs4_client *clp = sop->so_client; @@ -1000,8 +1006,7 @@ static void nfs4_put_stateowner(struct nfs4_stateowner *sop) return; sop->so_ops->so_unhash(sop); spin_unlock(&clp->cl_lock); - kfree(sop->so_owner.data); - sop->so_ops->so_free(sop); + nfs4_free_stateowner(sop); } static void unhash_ol_stateid(struct nfs4_ol_stateid *stp) @@ -1894,7 +1899,7 @@ static void gen_confirm(struct nfs4_client *clp, struct nfsd_net *nn) * __force to keep sparse happy */ verf[0] = (__force __be32)get_seconds(); - verf[1] = (__force __be32)nn->clientid_counter; + verf[1] = (__force __be32)nn->clverifier_counter++; memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data)); } @@ -2241,6 +2246,9 @@ static bool client_has_state(struct nfs4_client *clp) * Also note we should probably be using this in 4.0 case too. */ return !list_empty(&clp->cl_openowners) +#ifdef CONFIG_NFSD_PNFS + || !list_empty(&clp->cl_lo_states) +#endif || !list_empty(&clp->cl_delegations) || !list_empty(&clp->cl_sessions); } @@ -2547,11 +2555,9 @@ nfsd4_create_session(struct svc_rqst *rqstp, goto out_free_conn; cs_slot = &conf->cl_cs_slot; status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); - if (status == nfserr_replay_cache) { - status = nfsd4_replay_create_session(cr_ses, cs_slot); - goto out_free_conn; - } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) { - status = nfserr_seq_misordered; + if (status) { + if (status == nfserr_replay_cache) + status = nfsd4_replay_create_session(cr_ses, cs_slot); goto out_free_conn; } } else if (unconf) { @@ -3041,10 +3047,11 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, unconf = find_unconfirmed_client_by_name(&clname, nn); if (unconf) unhash_client_locked(unconf); - if (conf && same_verf(&conf->cl_verifier, &clverifier)) + if (conf && same_verf(&conf->cl_verifier, &clverifier)) { /* case 1: probable callback update */ copy_clid(new, conf); - else /* case 4 (new client) or cases 2, 3 (client reboot): */ + gen_confirm(new, nn); + } else /* case 4 (new client) or cases 2, 3 (client reboot): */ gen_clid(new, nn); new->cl_minorversion = 0; gen_callback(new, setclid, rqstp); @@ -3315,7 +3322,8 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open, hash_openowner(oo, clp, strhashval); ret = oo; } else - nfs4_free_openowner(&oo->oo_owner); + nfs4_free_stateowner(&oo->oo_owner); + spin_unlock(&clp->cl_lock); return ret; } @@ -3885,12 +3893,6 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c return status; } -static void -nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session) -{ - open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; -} - /* Should we give out recallable state?: */ static bool nfsd4_cb_channel_good(struct nfs4_client *clp) { @@ -3923,7 +3925,7 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_file *fp, int flag) static int nfs4_setlease(struct nfs4_delegation *dp) { struct nfs4_file *fp = dp->dl_stid.sc_file; - struct file_lock *fl, *ret; + struct file_lock *fl; struct file *filp; int status = 0; @@ -3934,10 +3936,10 @@ static int nfs4_setlease(struct nfs4_delegation *dp) if (!filp) { /* We should always have a readable file here */ WARN_ON_ONCE(1); + locks_free_lock(fl); return -EBADF; } fl->fl_file = filp; - ret = fl; status = vfs_setlease(filp, fl->fl_type, &fl, NULL); if (fl) locks_free_lock(fl); @@ -4209,7 +4211,7 @@ out: if (fp) put_nfs4_file(fp); if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) - nfs4_set_claim_prev(open, nfsd4_has_session(&resp->cstate)); + open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; /* * To finish the open response, we just need to set the rflags. */ @@ -4338,8 +4340,6 @@ nfs4_laundromat(struct nfsd_net *nn) spin_lock(&state_lock); list_for_each_safe(pos, next, &nn->del_recall_lru) { dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); - if (net_generic(dp->dl_stid.sc_client->net, nfsd_net_id) != nn) - continue; if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) { t = dp->dl_time - cutoff; new_timeo = min(new_timeo, t); @@ -5045,9 +5045,6 @@ out: return status; } - -#define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start)) - static inline u64 end_offset(u64 start, u64 len) { @@ -5139,8 +5136,7 @@ nevermind: } static struct nfs4_lockowner * -find_lockowner_str_locked(clientid_t *clid, struct xdr_netobj *owner, - struct nfs4_client *clp) +find_lockowner_str_locked(struct nfs4_client *clp, struct xdr_netobj *owner) { unsigned int strhashval = ownerstr_hashval(owner); struct nfs4_stateowner *so; @@ -5158,13 +5154,12 @@ find_lockowner_str_locked(clientid_t *clid, struct xdr_netobj *owner, } static struct nfs4_lockowner * -find_lockowner_str(clientid_t *clid, struct xdr_netobj *owner, - struct nfs4_client *clp) +find_lockowner_str(struct nfs4_client *clp, struct xdr_netobj *owner) { struct nfs4_lockowner *lo; spin_lock(&clp->cl_lock); - lo = find_lockowner_str_locked(clid, owner, clp); + lo = find_lockowner_str_locked(clp, owner); spin_unlock(&clp->cl_lock); return lo; } @@ -5208,14 +5203,14 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, lo->lo_owner.so_seqid = lock->lk_new_lock_seqid; lo->lo_owner.so_ops = &lockowner_ops; spin_lock(&clp->cl_lock); - ret = find_lockowner_str_locked(&clp->cl_clientid, - &lock->lk_new_owner, clp); + ret = find_lockowner_str_locked(clp, &lock->lk_new_owner); if (ret == NULL) { list_add(&lo->lo_owner.so_strhash, &clp->cl_ownerstr_hashtbl[strhashval]); ret = lo; } else - nfs4_free_lockowner(&lo->lo_owner); + nfs4_free_stateowner(&lo->lo_owner); + spin_unlock(&clp->cl_lock); return ret; } @@ -5298,8 +5293,8 @@ find_or_create_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fi, static int check_lock_length(u64 offset, u64 length) { - return ((length == 0) || ((length != NFS4_MAX_UINT64) && - LOFF_OVERFLOW(offset, length))); + return ((length == 0) || ((length != NFS4_MAX_UINT64) && + (length > ~offset))); } static void get_lock_access(struct nfs4_ol_stateid *lock_stp, u32 access) @@ -5328,9 +5323,9 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct nfs4_lockowner *lo; unsigned int strhashval; - lo = find_lockowner_str(&cl->cl_clientid, &lock->v.new.owner, cl); + lo = find_lockowner_str(cl, &lock->lk_new_owner); if (!lo) { - strhashval = ownerstr_hashval(&lock->v.new.owner); + strhashval = ownerstr_hashval(&lock->lk_new_owner); lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); if (lo == NULL) return nfserr_jukebox; @@ -5391,7 +5386,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (lock->lk_is_new) { if (nfsd4_has_session(cstate)) /* See rfc 5661 18.10.3: given clientid is ignored: */ - memcpy(&lock->v.new.clientid, + memcpy(&lock->lk_new_clientid, &cstate->session->se_client->cl_clientid, sizeof(clientid_t)); @@ -5409,7 +5404,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, open_sop = openowner(open_stp->st_stateowner); status = nfserr_bad_stateid; if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, - &lock->v.new.clientid)) + &lock->lk_new_clientid)) goto out; status = lookup_or_create_lock_state(cstate, open_stp, lock, &lock_stp, &new); @@ -5603,8 +5598,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out; } - lo = find_lockowner_str(&lockt->lt_clientid, &lockt->lt_owner, - cstate->clp); + lo = find_lockowner_str(cstate->clp, &lockt->lt_owner); if (lo) file_lock->fl_owner = (fl_owner_t)lo; file_lock->fl_pid = current->tgid; |