Skip to content

Commit 7df302f

Browse files
chuckleverJ. Bruce Fields
authored andcommitted
NFSD: TEST_STATEID should not return NFS4ERR_STALE_STATEID
According to RFC 5661, the TEST_STATEID operation is not allowed to return NFS4ERR_STALE_STATEID. In addition, RFC 5661 says: 15.1.16.5. NFS4ERR_STALE_STATEID (Error Code 10023) A stateid generated by an earlier server instance was used. This error is moot in NFSv4.1 because all operations that take a stateid MUST be preceded by the SEQUENCE operation, and the earlier server instance is detected by the session infrastructure that supports SEQUENCE. I triggered NFS4ERR_STALE_STATEID while testing the Linux client's NOGRACE recovery. Bruce suggested an additional test that could be useful to client developers. Lastly, RFC 5661, section 18.48.3 has this: o Special stateids are always considered invalid (they result in the error code NFS4ERR_BAD_STATEID). An explicit check is made for those state IDs to avoid printk noise. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
1 parent 2411967 commit 7df302f

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed

fs/nfsd/nfs4state.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <linux/namei.h>
3939
#include <linux/swap.h>
4040
#include <linux/pagemap.h>
41+
#include <linux/ratelimit.h>
4142
#include <linux/sunrpc/svcauth_gss.h>
4243
#include <linux/sunrpc/clnt.h>
4344
#include "xdr4.h"
@@ -3338,18 +3339,26 @@ static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_s
33383339
return nfserr_old_stateid;
33393340
}
33403341

3341-
__be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
3342+
static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
33423343
{
33433344
struct nfs4_stid *s;
33443345
struct nfs4_ol_stateid *ols;
33453346
__be32 status;
33463347

3347-
if (STALE_STATEID(stateid))
3348-
return nfserr_stale_stateid;
3349-
3348+
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3349+
return nfserr_bad_stateid;
3350+
/* Client debugging aid. */
3351+
if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) {
3352+
char addr_str[INET6_ADDRSTRLEN];
3353+
rpc_ntop((struct sockaddr *)&cl->cl_addr, addr_str,
3354+
sizeof(addr_str));
3355+
pr_warn_ratelimited("NFSD: client %s testing state ID "
3356+
"with incorrect client ID\n", addr_str);
3357+
return nfserr_bad_stateid;
3358+
}
33503359
s = find_stateid(cl, stateid);
33513360
if (!s)
3352-
return nfserr_stale_stateid;
3361+
return nfserr_bad_stateid;
33533362
status = check_stateid_generation(stateid, &s->sc_stateid, 1);
33543363
if (status)
33553364
return status;
@@ -3468,7 +3477,8 @@ nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
34683477

34693478
nfs4_lock_state();
34703479
list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list)
3471-
stateid->ts_id_status = nfs4_validate_stateid(cl, &stateid->ts_id_stateid);
3480+
stateid->ts_id_status =
3481+
nfsd4_validate_stateid(cl, &stateid->ts_id_stateid);
34723482
nfs4_unlock_state();
34733483

34743484
return nfs_ok;

fs/nfsd/state.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,6 @@ extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
475475
extern int nfs4_client_to_reclaim(const char *name);
476476
extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
477477
extern void release_session_client(struct nfsd4_session *);
478-
extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *);
479478
extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
480479

481480
/* nfs4recover operations */

0 commit comments

Comments
 (0)