Skip to content

Commit

Permalink
nfsd41: match clientid establishment method
Browse files Browse the repository at this point in the history
We need to distinguish between client names provided by NFSv4.0 clients
SETCLIENTID and those provided by NFSv4.1 via EXCHANGE_ID when looking
up the clientid by string.

Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Andy Adamson <andros@netapp.com>
[nfsd41: use boolean values for use_exchange_id argument]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfsd41: simplify match_clientid_establishment logic]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
  • Loading branch information
Andy Adamson authored and J. Bruce Fields committed Apr 4, 2009
1 parent 0733d21 commit a1bcecd
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 13 deletions.
3 changes: 2 additions & 1 deletion fs/nfsd/nfs4recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ purge_old(struct dentry *parent, struct dentry *child)
{
int status;

if (nfs4_has_reclaimed_state(child->d_name.name))
/* note: we currently use this path only for minorversion 0 */
if (nfs4_has_reclaimed_state(child->d_name.name, false))
return 0;

status = nfsd4_clear_clid_dir(parent, child);
Expand Down
42 changes: 31 additions & 11 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,25 +715,45 @@ find_unconfirmed_client(clientid_t *clid)
return NULL;
}

/*
* Return 1 iff clp's clientid establishment method matches the use_exchange_id
* parameter. Matching is based on the fact the at least one of the
* EXCHGID4_FLAG_USE_{NON_PNFS,PNFS_MDS,PNFS_DS} flags must be set for v4.1
*
* FIXME: we need to unify the clientid namespaces for nfsv4.x
* and correctly deal with client upgrade/downgrade in EXCHANGE_ID
* and SET_CLIENTID{,_CONFIRM}
*/
static inline int
match_clientid_establishment(struct nfs4_client *clp, bool use_exchange_id)
{
bool has_exchange_flags = (clp->cl_exchange_flags != 0);
return use_exchange_id == has_exchange_flags;
}

static struct nfs4_client *
find_confirmed_client_by_str(const char *dname, unsigned int hashval)
find_confirmed_client_by_str(const char *dname, unsigned int hashval,
bool use_exchange_id)
{
struct nfs4_client *clp;

list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
if (same_name(clp->cl_recdir, dname))
if (same_name(clp->cl_recdir, dname) &&
match_clientid_establishment(clp, use_exchange_id))
return clp;
}
return NULL;
}

static struct nfs4_client *
find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
find_unconfirmed_client_by_str(const char *dname, unsigned int hashval,
bool use_exchange_id)
{
struct nfs4_client *clp;

list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
if (same_name(clp->cl_recdir, dname))
if (same_name(clp->cl_recdir, dname) &&
match_clientid_establishment(clp, use_exchange_id))
return clp;
}
return NULL;
Expand Down Expand Up @@ -890,7 +910,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
nfs4_lock_state();
status = nfs_ok;

conf = find_confirmed_client_by_str(dname, strhashval);
conf = find_confirmed_client_by_str(dname, strhashval, true);
if (conf) {
if (!same_verf(&verf, &conf->cl_verifier)) {
/* 18.35.4 case 8 */
Expand Down Expand Up @@ -938,7 +958,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
}
}

unconf = find_unconfirmed_client_by_str(dname, strhashval);
unconf = find_unconfirmed_client_by_str(dname, strhashval, true);
if (unconf) {
/*
* Possible retry or client restart. Per 18.35.4 case 4,
Expand Down Expand Up @@ -1035,7 +1055,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
strhashval = clientstr_hashval(dname);

nfs4_lock_state();
conf = find_confirmed_client_by_str(dname, strhashval);
conf = find_confirmed_client_by_str(dname, strhashval, false);
if (conf) {
/* RFC 3530 14.2.33 CASE 0: */
status = nfserr_clid_inuse;
Expand All @@ -1050,7 +1070,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
* has a description of SETCLIENTID request processing consisting
* of 5 bullet points, labeled as CASE0 - CASE4 below.
*/
unconf = find_unconfirmed_client_by_str(dname, strhashval);
unconf = find_unconfirmed_client_by_str(dname, strhashval, false);
status = nfserr_resource;
if (!conf) {
/*
Expand Down Expand Up @@ -1205,7 +1225,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
unsigned int hash =
clientstr_hashval(unconf->cl_recdir);
conf = find_confirmed_client_by_str(unconf->cl_recdir,
hash);
hash, false);
if (conf) {
nfsd4_remove_clid_dir(conf);
expire_client(conf);
Expand Down Expand Up @@ -3326,12 +3346,12 @@ alloc_reclaim(void)
}

int
nfs4_has_reclaimed_state(const char *name)
nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
{
unsigned int strhashval = clientstr_hashval(name);
struct nfs4_client *clp;

clp = find_confirmed_client_by_str(name, strhashval);
clp = find_confirmed_client_by_str(name, strhashval, use_exchange_id);
return clp ? 1 : 0;
}

Expand Down
2 changes: 1 addition & 1 deletion include/linux/nfsd/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ extern void nfsd4_init_recdir(char *recdir_name);
extern int nfsd4_recdir_load(void);
extern void nfsd4_shutdown_recdir(void);
extern int nfs4_client_to_reclaim(const char *name);
extern int nfs4_has_reclaimed_state(const char *name);
extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
extern void nfsd4_recdir_purge_old(void);
extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
Expand Down

0 comments on commit a1bcecd

Please sign in to comment.