Commit a1bcecd2 authored by Andy Adamson's avatar Andy Adamson Committed by J. Bruce Fields

nfsd41: match clientid establishment method

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: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarAndy Adamson <andros@netapp.com>
[nfsd41: use boolean values for use_exchange_id argument]
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
[nfsd41: simplify match_clientid_establishment logic]
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 0733d213
...@@ -344,7 +344,8 @@ purge_old(struct dentry *parent, struct dentry *child) ...@@ -344,7 +344,8 @@ purge_old(struct dentry *parent, struct dentry *child)
{ {
int status; 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; return 0;
status = nfsd4_clear_clid_dir(parent, child); status = nfsd4_clear_clid_dir(parent, child);
......
...@@ -715,25 +715,45 @@ find_unconfirmed_client(clientid_t *clid) ...@@ -715,25 +715,45 @@ find_unconfirmed_client(clientid_t *clid)
return NULL; 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 * 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; struct nfs4_client *clp;
list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) { 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 clp;
} }
return NULL; return NULL;
} }
static struct nfs4_client * 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; struct nfs4_client *clp;
list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) { 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 clp;
} }
return NULL; return NULL;
...@@ -890,7 +910,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, ...@@ -890,7 +910,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
nfs4_lock_state(); nfs4_lock_state();
status = nfs_ok; status = nfs_ok;
conf = find_confirmed_client_by_str(dname, strhashval); conf = find_confirmed_client_by_str(dname, strhashval, true);
if (conf) { if (conf) {
if (!same_verf(&verf, &conf->cl_verifier)) { if (!same_verf(&verf, &conf->cl_verifier)) {
/* 18.35.4 case 8 */ /* 18.35.4 case 8 */
...@@ -938,7 +958,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, ...@@ -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) { if (unconf) {
/* /*
* Possible retry or client restart. Per 18.35.4 case 4, * Possible retry or client restart. Per 18.35.4 case 4,
...@@ -1035,7 +1055,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -1035,7 +1055,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
strhashval = clientstr_hashval(dname); strhashval = clientstr_hashval(dname);
nfs4_lock_state(); nfs4_lock_state();
conf = find_confirmed_client_by_str(dname, strhashval); conf = find_confirmed_client_by_str(dname, strhashval, false);
if (conf) { if (conf) {
/* RFC 3530 14.2.33 CASE 0: */ /* RFC 3530 14.2.33 CASE 0: */
status = nfserr_clid_inuse; status = nfserr_clid_inuse;
...@@ -1050,7 +1070,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -1050,7 +1070,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
* has a description of SETCLIENTID request processing consisting * has a description of SETCLIENTID request processing consisting
* of 5 bullet points, labeled as CASE0 - CASE4 below. * 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; status = nfserr_resource;
if (!conf) { if (!conf) {
/* /*
...@@ -1205,7 +1225,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, ...@@ -1205,7 +1225,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
unsigned int hash = unsigned int hash =
clientstr_hashval(unconf->cl_recdir); clientstr_hashval(unconf->cl_recdir);
conf = find_confirmed_client_by_str(unconf->cl_recdir, conf = find_confirmed_client_by_str(unconf->cl_recdir,
hash); hash, false);
if (conf) { if (conf) {
nfsd4_remove_clid_dir(conf); nfsd4_remove_clid_dir(conf);
expire_client(conf); expire_client(conf);
...@@ -3326,12 +3346,12 @@ alloc_reclaim(void) ...@@ -3326,12 +3346,12 @@ alloc_reclaim(void)
} }
int 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); unsigned int strhashval = clientstr_hashval(name);
struct nfs4_client *clp; 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; return clp ? 1 : 0;
} }
......
...@@ -330,7 +330,7 @@ extern void nfsd4_init_recdir(char *recdir_name); ...@@ -330,7 +330,7 @@ extern void nfsd4_init_recdir(char *recdir_name);
extern int nfsd4_recdir_load(void); extern int nfsd4_recdir_load(void);
extern void nfsd4_shutdown_recdir(void); extern void nfsd4_shutdown_recdir(void);
extern int nfs4_client_to_reclaim(const char *name); 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 void nfsd4_recdir_purge_old(void);
extern int nfsd4_create_clid_dir(struct nfs4_client *clp); extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
extern void nfsd4_remove_clid_dir(struct nfs4_client *clp); extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment