|
@@ -189,6 +189,15 @@ static void put_client_renew_locked(struct nfs4_client *clp)
|
|
renew_client_locked(clp);
|
|
renew_client_locked(clp);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void put_client_renew(struct nfs4_client *clp)
|
|
|
|
+{
|
|
|
|
+ struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
|
|
|
|
+
|
|
|
|
+ spin_lock(&nn->client_lock);
|
|
|
|
+ put_client_renew_locked(clp);
|
|
|
|
+ spin_unlock(&nn->client_lock);
|
|
|
|
+}
|
|
|
|
+
|
|
static __be32 nfsd4_get_session_locked(struct nfsd4_session *ses)
|
|
static __be32 nfsd4_get_session_locked(struct nfsd4_session *ses)
|
|
{
|
|
{
|
|
__be32 status;
|
|
__be32 status;
|
|
@@ -2391,6 +2400,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
|
|
goto out_put_session;
|
|
goto out_put_session;
|
|
cstate->slot = slot;
|
|
cstate->slot = slot;
|
|
cstate->session = session;
|
|
cstate->session = session;
|
|
|
|
+ cstate->clp = clp;
|
|
/* Return the cached reply status and set cstate->status
|
|
/* Return the cached reply status and set cstate->status
|
|
* for nfsd4_proc_compound processing */
|
|
* for nfsd4_proc_compound processing */
|
|
status = nfsd4_replay_cache_entry(resp, seq);
|
|
status = nfsd4_replay_cache_entry(resp, seq);
|
|
@@ -2425,6 +2435,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
|
|
|
|
|
|
cstate->slot = slot;
|
|
cstate->slot = slot;
|
|
cstate->session = session;
|
|
cstate->session = session;
|
|
|
|
+ cstate->clp = clp;
|
|
|
|
|
|
out:
|
|
out:
|
|
switch (clp->cl_cb_state) {
|
|
switch (clp->cl_cb_state) {
|
|
@@ -2461,7 +2472,8 @@ nfsd4_sequence_done(struct nfsd4_compoundres *resp)
|
|
}
|
|
}
|
|
/* Drop session reference that was taken in nfsd4_sequence() */
|
|
/* Drop session reference that was taken in nfsd4_sequence() */
|
|
nfsd4_put_session(cs->session);
|
|
nfsd4_put_session(cs->session);
|
|
- }
|
|
|
|
|
|
+ } else if (cs->clp)
|
|
|
|
+ put_client_renew(cs->clp);
|
|
}
|
|
}
|
|
|
|
|
|
__be32
|
|
__be32
|
|
@@ -2986,6 +2998,38 @@ static __be32 nfsd4_check_seqid(struct nfsd4_compound_state *cstate, struct nfs4
|
|
return nfserr_bad_seqid;
|
|
return nfserr_bad_seqid;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static __be32 lookup_clientid(clientid_t *clid,
|
|
|
|
+ struct nfsd4_compound_state *cstate,
|
|
|
|
+ struct nfsd_net *nn)
|
|
|
|
+{
|
|
|
|
+ struct nfs4_client *found;
|
|
|
|
+
|
|
|
|
+ if (cstate->clp) {
|
|
|
|
+ found = cstate->clp;
|
|
|
|
+ if (!same_clid(&found->cl_clientid, clid))
|
|
|
|
+ return nfserr_stale_clientid;
|
|
|
|
+ return nfs_ok;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (STALE_CLIENTID(clid, nn))
|
|
|
|
+ return nfserr_stale_clientid;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * For v4.1+ we get the client in the SEQUENCE op. If we don't have one
|
|
|
|
+ * cached already then we know this is for is for v4.0 and "sessions"
|
|
|
|
+ * will be false.
|
|
|
|
+ */
|
|
|
|
+ WARN_ON_ONCE(cstate->session);
|
|
|
|
+ found = find_confirmed_client(clid, false, nn);
|
|
|
|
+ if (!found)
|
|
|
|
+ return nfserr_expired;
|
|
|
|
+
|
|
|
|
+ /* Cache the nfs4_client in cstate! */
|
|
|
|
+ cstate->clp = found;
|
|
|
|
+ atomic_inc(&found->cl_refcount);
|
|
|
|
+ return nfs_ok;
|
|
|
|
+}
|
|
|
|
+
|
|
__be32
|
|
__be32
|
|
nfsd4_process_open1(struct nfsd4_compound_state *cstate,
|
|
nfsd4_process_open1(struct nfsd4_compound_state *cstate,
|
|
struct nfsd4_open *open, struct nfsd_net *nn)
|
|
struct nfsd4_open *open, struct nfsd_net *nn)
|
|
@@ -3498,18 +3542,6 @@ void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status)
|
|
free_generic_stateid(open->op_stp);
|
|
free_generic_stateid(open->op_stp);
|
|
}
|
|
}
|
|
|
|
|
|
-static __be32 lookup_clientid(clientid_t *clid, bool session, struct nfsd_net *nn, struct nfs4_client **clp)
|
|
|
|
-{
|
|
|
|
- struct nfs4_client *found;
|
|
|
|
-
|
|
|
|
- if (STALE_CLIENTID(clid, nn))
|
|
|
|
- return nfserr_stale_clientid;
|
|
|
|
- found = find_confirmed_client(clid, session, nn);
|
|
|
|
- if (clp)
|
|
|
|
- *clp = found;
|
|
|
|
- return found ? nfs_ok : nfserr_expired;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
__be32
|
|
__be32
|
|
nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
clientid_t *clid)
|
|
clientid_t *clid)
|
|
@@ -3521,9 +3553,10 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
nfs4_lock_state();
|
|
nfs4_lock_state();
|
|
dprintk("process_renew(%08x/%08x): starting\n",
|
|
dprintk("process_renew(%08x/%08x): starting\n",
|
|
clid->cl_boot, clid->cl_id);
|
|
clid->cl_boot, clid->cl_id);
|
|
- status = lookup_clientid(clid, cstate->minorversion, nn, &clp);
|
|
|
|
|
|
+ status = lookup_clientid(clid, cstate, nn);
|
|
if (status)
|
|
if (status)
|
|
goto out;
|
|
goto out;
|
|
|
|
+ clp = cstate->clp;
|
|
status = nfserr_cb_path_down;
|
|
status = nfserr_cb_path_down;
|
|
if (!list_empty(&clp->cl_delegations)
|
|
if (!list_empty(&clp->cl_delegations)
|
|
&& clp->cl_cb_state != NFSD4_CB_UP)
|
|
&& clp->cl_cb_state != NFSD4_CB_UP)
|
|
@@ -3786,22 +3819,19 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
|
|
stateid_t *stateid, unsigned char typemask,
|
|
stateid_t *stateid, unsigned char typemask,
|
|
struct nfs4_stid **s, struct nfsd_net *nn)
|
|
struct nfs4_stid **s, struct nfsd_net *nn)
|
|
{
|
|
{
|
|
- struct nfs4_client *cl;
|
|
|
|
__be32 status;
|
|
__be32 status;
|
|
- bool sessions = cstate->minorversion != 0;
|
|
|
|
|
|
|
|
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
|
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
|
return nfserr_bad_stateid;
|
|
return nfserr_bad_stateid;
|
|
- status = lookup_clientid(&stateid->si_opaque.so_clid, sessions,
|
|
|
|
- nn, &cl);
|
|
|
|
|
|
+ status = lookup_clientid(&stateid->si_opaque.so_clid, cstate, nn);
|
|
if (status == nfserr_stale_clientid) {
|
|
if (status == nfserr_stale_clientid) {
|
|
- if (sessions)
|
|
|
|
|
|
+ if (cstate->session)
|
|
return nfserr_bad_stateid;
|
|
return nfserr_bad_stateid;
|
|
return nfserr_stale_stateid;
|
|
return nfserr_stale_stateid;
|
|
}
|
|
}
|
|
if (status)
|
|
if (status)
|
|
return status;
|
|
return status;
|
|
- *s = find_stateid_by_type(cl, stateid, typemask);
|
|
|
|
|
|
+ *s = find_stateid_by_type(cstate->clp, stateid, typemask);
|
|
if (!*s)
|
|
if (!*s)
|
|
return nfserr_bad_stateid;
|
|
return nfserr_bad_stateid;
|
|
return nfs_ok;
|
|
return nfs_ok;
|
|
@@ -4651,7 +4681,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
nfs4_lock_state();
|
|
nfs4_lock_state();
|
|
|
|
|
|
if (!nfsd4_has_session(cstate)) {
|
|
if (!nfsd4_has_session(cstate)) {
|
|
- status = lookup_clientid(&lockt->lt_clientid, false, nn, NULL);
|
|
|
|
|
|
+ status = lookup_clientid(&lockt->lt_clientid, cstate, nn);
|
|
if (status)
|
|
if (status)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -4820,7 +4850,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
|
|
|
|
|
|
nfs4_lock_state();
|
|
nfs4_lock_state();
|
|
|
|
|
|
- status = lookup_clientid(clid, cstate->minorversion, nn, NULL);
|
|
|
|
|
|
+ status = lookup_clientid(clid, cstate, nn);
|
|
if (status)
|
|
if (status)
|
|
goto out;
|
|
goto out;
|
|
|
|
|