aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4recover.c3
-rw-r--r--fs/nfsd/nfs4state.c42
-rw-r--r--include/linux/nfsd/state.h2
3 files changed, 34 insertions, 13 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index b11cf8d34280..3444c0052a87 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -344,7 +344,8 @@ purge_old(struct dentry *parent, struct dentry *child)
344{ 344{
345 int status; 345 int status;
346 346
347 if (nfs4_has_reclaimed_state(child->d_name.name)) 347 /* note: we currently use this path only for minorversion 0 */
348 if (nfs4_has_reclaimed_state(child->d_name.name, false))
348 return 0; 349 return 0;
349 350
350 status = nfsd4_clear_clid_dir(parent, child); 351 status = nfsd4_clear_clid_dir(parent, child);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 4f963e902972..dfc6d946cdfe 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -715,25 +715,45 @@ find_unconfirmed_client(clientid_t *clid)
715 return NULL; 715 return NULL;
716} 716}
717 717
718/*
719 * Return 1 iff clp's clientid establishment method matches the use_exchange_id
720 * parameter. Matching is based on the fact the at least one of the
721 * EXCHGID4_FLAG_USE_{NON_PNFS,PNFS_MDS,PNFS_DS} flags must be set for v4.1
722 *
723 * FIXME: we need to unify the clientid namespaces for nfsv4.x
724 * and correctly deal with client upgrade/downgrade in EXCHANGE_ID
725 * and SET_CLIENTID{,_CONFIRM}
726 */
727static inline int
728match_clientid_establishment(struct nfs4_client *clp, bool use_exchange_id)
729{
730 bool has_exchange_flags = (clp->cl_exchange_flags != 0);
731 return use_exchange_id == has_exchange_flags;
732}
733
718static struct nfs4_client * 734static struct nfs4_client *
719find_confirmed_client_by_str(const char *dname, unsigned int hashval) 735find_confirmed_client_by_str(const char *dname, unsigned int hashval,
736 bool use_exchange_id)
720{ 737{
721 struct nfs4_client *clp; 738 struct nfs4_client *clp;
722 739
723 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) { 740 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
724 if (same_name(clp->cl_recdir, dname)) 741 if (same_name(clp->cl_recdir, dname) &&
742 match_clientid_establishment(clp, use_exchange_id))
725 return clp; 743 return clp;
726 } 744 }
727 return NULL; 745 return NULL;
728} 746}
729 747
730static struct nfs4_client * 748static struct nfs4_client *
731find_unconfirmed_client_by_str(const char *dname, unsigned int hashval) 749find_unconfirmed_client_by_str(const char *dname, unsigned int hashval,
750 bool use_exchange_id)
732{ 751{
733 struct nfs4_client *clp; 752 struct nfs4_client *clp;
734 753
735 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) { 754 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
736 if (same_name(clp->cl_recdir, dname)) 755 if (same_name(clp->cl_recdir, dname) &&
756 match_clientid_establishment(clp, use_exchange_id))
737 return clp; 757 return clp;
738 } 758 }
739 return NULL; 759 return NULL;
@@ -890,7 +910,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
890 nfs4_lock_state(); 910 nfs4_lock_state();
891 status = nfs_ok; 911 status = nfs_ok;
892 912
893 conf = find_confirmed_client_by_str(dname, strhashval); 913 conf = find_confirmed_client_by_str(dname, strhashval, true);
894 if (conf) { 914 if (conf) {
895 if (!same_verf(&verf, &conf->cl_verifier)) { 915 if (!same_verf(&verf, &conf->cl_verifier)) {
896 /* 18.35.4 case 8 */ 916 /* 18.35.4 case 8 */
@@ -938,7 +958,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
938 } 958 }
939 } 959 }
940 960
941 unconf = find_unconfirmed_client_by_str(dname, strhashval); 961 unconf = find_unconfirmed_client_by_str(dname, strhashval, true);
942 if (unconf) { 962 if (unconf) {
943 /* 963 /*
944 * Possible retry or client restart. Per 18.35.4 case 4, 964 * 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 strhashval = clientstr_hashval(dname); 1055 strhashval = clientstr_hashval(dname);
1036 1056
1037 nfs4_lock_state(); 1057 nfs4_lock_state();
1038 conf = find_confirmed_client_by_str(dname, strhashval); 1058 conf = find_confirmed_client_by_str(dname, strhashval, false);
1039 if (conf) { 1059 if (conf) {
1040 /* RFC 3530 14.2.33 CASE 0: */ 1060 /* RFC 3530 14.2.33 CASE 0: */
1041 status = nfserr_clid_inuse; 1061 status = nfserr_clid_inuse;
@@ -1050,7 +1070,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1050 * has a description of SETCLIENTID request processing consisting 1070 * has a description of SETCLIENTID request processing consisting
1051 * of 5 bullet points, labeled as CASE0 - CASE4 below. 1071 * of 5 bullet points, labeled as CASE0 - CASE4 below.
1052 */ 1072 */
1053 unconf = find_unconfirmed_client_by_str(dname, strhashval); 1073 unconf = find_unconfirmed_client_by_str(dname, strhashval, false);
1054 status = nfserr_resource; 1074 status = nfserr_resource;
1055 if (!conf) { 1075 if (!conf) {
1056 /* 1076 /*
@@ -1205,7 +1225,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
1205 unsigned int hash = 1225 unsigned int hash =
1206 clientstr_hashval(unconf->cl_recdir); 1226 clientstr_hashval(unconf->cl_recdir);
1207 conf = find_confirmed_client_by_str(unconf->cl_recdir, 1227 conf = find_confirmed_client_by_str(unconf->cl_recdir,
1208 hash); 1228 hash, false);
1209 if (conf) { 1229 if (conf) {
1210 nfsd4_remove_clid_dir(conf); 1230 nfsd4_remove_clid_dir(conf);
1211 expire_client(conf); 1231 expire_client(conf);
@@ -3326,12 +3346,12 @@ alloc_reclaim(void)
3326} 3346}
3327 3347
3328int 3348int
3329nfs4_has_reclaimed_state(const char *name) 3349nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
3330{ 3350{
3331 unsigned int strhashval = clientstr_hashval(name); 3351 unsigned int strhashval = clientstr_hashval(name);
3332 struct nfs4_client *clp; 3352 struct nfs4_client *clp;
3333 3353
3334 clp = find_confirmed_client_by_str(name, strhashval); 3354 clp = find_confirmed_client_by_str(name, strhashval, use_exchange_id);
3335 return clp ? 1 : 0; 3355 return clp ? 1 : 0;
3336} 3356}
3337 3357
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 8d0b10167937..90829db76861 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -330,7 +330,7 @@ extern void nfsd4_init_recdir(char *recdir_name);
330extern int nfsd4_recdir_load(void); 330extern int nfsd4_recdir_load(void);
331extern void nfsd4_shutdown_recdir(void); 331extern void nfsd4_shutdown_recdir(void);
332extern int nfs4_client_to_reclaim(const char *name); 332extern int nfs4_client_to_reclaim(const char *name);
333extern int nfs4_has_reclaimed_state(const char *name); 333extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
334extern void nfsd4_recdir_purge_old(void); 334extern void nfsd4_recdir_purge_old(void);
335extern int nfsd4_create_clid_dir(struct nfs4_client *clp); 335extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
336extern void nfsd4_remove_clid_dir(struct nfs4_client *clp); 336extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);