aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2010-11-24 17:30:54 -0500
committerJ. Bruce Fields <bfields@redhat.com>2010-12-17 15:48:01 -0500
commite203d506bd221bfa5b3acbb7336ae7b7646636a4 (patch)
tree237901e3b618d50f7ab65ff86dde3aaf1497c09f /fs/nfsd/nfs4state.c
parent6e5f15c93dc745d46c2bb9e4597b44463203844b (diff)
nfsd4: fix mixed 4.0/4.1 handling, 4.1 reboot
Instead of failing to find client entries which don't match the minorversion, we should be finding them, then either erroring out or expiring them as appropriate. This also fixes a problem which would cause the 4.1 server to fail to recognize clients after a second reboot. Reported-by: Casey Bodley <cbodley@citi.umich.edu> Reviewed-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c37
1 files changed, 17 insertions, 20 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 0c61cc1eadca..73adcfb2dc17 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1134,39 +1134,30 @@ find_unconfirmed_client(clientid_t *clid)
1134 return NULL; 1134 return NULL;
1135} 1135}
1136 1136
1137/*
1138 * FIXME: we need to unify the clientid namespaces for nfsv4.x
1139 * and correctly deal with client upgrade/downgrade in EXCHANGE_ID
1140 * and SET_CLIENTID{,_CONFIRM}
1141 */
1142static bool clp_used_exchangeid(struct nfs4_client *clp) 1137static bool clp_used_exchangeid(struct nfs4_client *clp)
1143{ 1138{
1144 return clp->cl_exchange_flags != 0; 1139 return clp->cl_exchange_flags != 0;
1145} 1140}
1146 1141
1147static struct nfs4_client * 1142static struct nfs4_client *
1148find_confirmed_client_by_str(const char *dname, unsigned int hashval, 1143find_confirmed_client_by_str(const char *dname, unsigned int hashval)
1149 bool use_exchange_id)
1150{ 1144{
1151 struct nfs4_client *clp; 1145 struct nfs4_client *clp;
1152 1146
1153 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) { 1147 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
1154 if (same_name(clp->cl_recdir, dname) && 1148 if (same_name(clp->cl_recdir, dname))
1155 clp_used_exchangeid(clp) == use_exchange_id)
1156 return clp; 1149 return clp;
1157 } 1150 }
1158 return NULL; 1151 return NULL;
1159} 1152}
1160 1153
1161static struct nfs4_client * 1154static struct nfs4_client *
1162find_unconfirmed_client_by_str(const char *dname, unsigned int hashval, 1155find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
1163 bool use_exchange_id)
1164{ 1156{
1165 struct nfs4_client *clp; 1157 struct nfs4_client *clp;
1166 1158
1167 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) { 1159 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
1168 if (same_name(clp->cl_recdir, dname) && 1160 if (same_name(clp->cl_recdir, dname))
1169 clp_used_exchangeid(clp) == use_exchange_id)
1170 return clp; 1161 return clp;
1171 } 1162 }
1172 return NULL; 1163 return NULL;
@@ -1357,8 +1348,12 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1357 nfs4_lock_state(); 1348 nfs4_lock_state();
1358 status = nfs_ok; 1349 status = nfs_ok;
1359 1350
1360 conf = find_confirmed_client_by_str(dname, strhashval, true); 1351 conf = find_confirmed_client_by_str(dname, strhashval);
1361 if (conf) { 1352 if (conf) {
1353 if (!clp_used_exchangeid(conf)) {
1354 status = nfserr_clid_inuse; /* XXX: ? */
1355 goto out;
1356 }
1362 if (!same_verf(&verf, &conf->cl_verifier)) { 1357 if (!same_verf(&verf, &conf->cl_verifier)) {
1363 /* 18.35.4 case 8 */ 1358 /* 18.35.4 case 8 */
1364 if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { 1359 if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) {
@@ -1399,7 +1394,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1399 goto out; 1394 goto out;
1400 } 1395 }
1401 1396
1402 unconf = find_unconfirmed_client_by_str(dname, strhashval, true); 1397 unconf = find_unconfirmed_client_by_str(dname, strhashval);
1403 if (unconf) { 1398 if (unconf) {
1404 /* 1399 /*
1405 * Possible retry or client restart. Per 18.35.4 case 4, 1400 * Possible retry or client restart. Per 18.35.4 case 4,
@@ -1799,10 +1794,12 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1799 strhashval = clientstr_hashval(dname); 1794 strhashval = clientstr_hashval(dname);
1800 1795
1801 nfs4_lock_state(); 1796 nfs4_lock_state();
1802 conf = find_confirmed_client_by_str(dname, strhashval, false); 1797 conf = find_confirmed_client_by_str(dname, strhashval);
1803 if (conf) { 1798 if (conf) {
1804 /* RFC 3530 14.2.33 CASE 0: */ 1799 /* RFC 3530 14.2.33 CASE 0: */
1805 status = nfserr_clid_inuse; 1800 status = nfserr_clid_inuse;
1801 if (clp_used_exchangeid(conf))
1802 goto out;
1806 if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) { 1803 if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
1807 char addr_str[INET6_ADDRSTRLEN]; 1804 char addr_str[INET6_ADDRSTRLEN];
1808 rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str, 1805 rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str,
@@ -1817,7 +1814,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1817 * has a description of SETCLIENTID request processing consisting 1814 * has a description of SETCLIENTID request processing consisting
1818 * of 5 bullet points, labeled as CASE0 - CASE4 below. 1815 * of 5 bullet points, labeled as CASE0 - CASE4 below.
1819 */ 1816 */
1820 unconf = find_unconfirmed_client_by_str(dname, strhashval, false); 1817 unconf = find_unconfirmed_client_by_str(dname, strhashval);
1821 status = nfserr_resource; 1818 status = nfserr_resource;
1822 if (!conf) { 1819 if (!conf) {
1823 /* 1820 /*
@@ -1962,7 +1959,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
1962 unsigned int hash = 1959 unsigned int hash =
1963 clientstr_hashval(unconf->cl_recdir); 1960 clientstr_hashval(unconf->cl_recdir);
1964 conf = find_confirmed_client_by_str(unconf->cl_recdir, 1961 conf = find_confirmed_client_by_str(unconf->cl_recdir,
1965 hash, false); 1962 hash);
1966 if (conf) { 1963 if (conf) {
1967 nfsd4_remove_clid_dir(conf); 1964 nfsd4_remove_clid_dir(conf);
1968 expire_client(conf); 1965 expire_client(conf);
@@ -4106,7 +4103,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
4106 unsigned int strhashval = clientstr_hashval(name); 4103 unsigned int strhashval = clientstr_hashval(name);
4107 struct nfs4_client *clp; 4104 struct nfs4_client *clp;
4108 4105
4109 clp = find_confirmed_client_by_str(name, strhashval, use_exchange_id); 4106 clp = find_confirmed_client_by_str(name, strhashval);
4110 return clp ? 1 : 0; 4107 return clp ? 1 : 0;
4111} 4108}
4112 4109