aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2012-09-26 11:36:16 -0400
committerJ. Bruce Fields <bfields@redhat.com>2012-10-01 17:40:04 -0400
commit0d22f68f02c10d5d10ec5712917e5828b001a822 (patch)
tree7b0d005f8bffe4623c1df2d65a14d321598c70c9 /fs
parent6a3b15634279aa6740f9b829d25db32024b2ca7c (diff)
nfsd4: don't allow reclaims of expired clients
When a confirmed client expires, we normally also need to expire any stable storage record which would allow that client to reclaim state on the next boot. We forgot to do this in some cases. (For example, in destroy_clientid, and in the cases in exchange_id and create_session that destroy and existing confirmed client.) But in most other cases, there's really no harm to calling nfsd4_client_record_remove(), because it is a no-op in the case the client doesn't have an existing The single exception is destroying a client on shutdown, when we want to keep the stable storage records so we can recognize which clients will be allowed to reclaim when we come back up. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/nfs4state.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 773b903c07c1..412b888faecb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1118,7 +1118,7 @@ unhash_client_locked(struct nfs4_client *clp)
1118} 1118}
1119 1119
1120static void 1120static void
1121expire_client(struct nfs4_client *clp) 1121destroy_client(struct nfs4_client *clp)
1122{ 1122{
1123 struct nfs4_openowner *oo; 1123 struct nfs4_openowner *oo;
1124 struct nfs4_delegation *dp; 1124 struct nfs4_delegation *dp;
@@ -1152,6 +1152,12 @@ expire_client(struct nfs4_client *clp)
1152 spin_unlock(&client_lock); 1152 spin_unlock(&client_lock);
1153} 1153}
1154 1154
1155static void expire_client(struct nfs4_client *clp)
1156{
1157 nfsd4_client_record_remove(clp);
1158 destroy_client(clp);
1159}
1160
1155static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) 1161static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
1156{ 1162{
1157 memcpy(target->cl_verifier.data, source->data, 1163 memcpy(target->cl_verifier.data, source->data,
@@ -2273,10 +2279,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2273 unsigned int hash = clientstr_hashval(unconf->cl_recdir); 2279 unsigned int hash = clientstr_hashval(unconf->cl_recdir);
2274 2280
2275 conf = find_confirmed_client_by_str(unconf->cl_recdir, hash); 2281 conf = find_confirmed_client_by_str(unconf->cl_recdir, hash);
2276 if (conf) { 2282 if (conf)
2277 nfsd4_client_record_remove(conf);
2278 expire_client(conf); 2283 expire_client(conf);
2279 }
2280 move_to_confirmed(unconf); 2284 move_to_confirmed(unconf);
2281 nfsd4_probe_callback(unconf); 2285 nfsd4_probe_callback(unconf);
2282 } 2286 }
@@ -3191,7 +3195,6 @@ nfs4_laundromat(void)
3191 clp = list_entry(pos, struct nfs4_client, cl_lru); 3195 clp = list_entry(pos, struct nfs4_client, cl_lru);
3192 dprintk("NFSD: purging unused client (clientid %08x)\n", 3196 dprintk("NFSD: purging unused client (clientid %08x)\n",
3193 clp->cl_clientid.cl_id); 3197 clp->cl_clientid.cl_id);
3194 nfsd4_client_record_remove(clp);
3195 expire_client(clp); 3198 expire_client(clp);
3196 } 3199 }
3197 spin_lock(&recall_lock); 3200 spin_lock(&recall_lock);
@@ -4562,7 +4565,6 @@ void nfsd_forget_clients(u64 num)
4562 4565
4563 nfs4_lock_state(); 4566 nfs4_lock_state();
4564 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { 4567 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
4565 nfsd4_client_record_remove(clp);
4566 expire_client(clp); 4568 expire_client(clp);
4567 if (++count == num) 4569 if (++count == num)
4568 break; 4570 break;
@@ -4787,11 +4789,11 @@ __nfs4_state_shutdown(void)
4787 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 4789 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
4788 while (!list_empty(&conf_id_hashtbl[i])) { 4790 while (!list_empty(&conf_id_hashtbl[i])) {
4789 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); 4791 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
4790 expire_client(clp); 4792 destroy_client(clp);
4791 } 4793 }
4792 while (!list_empty(&unconf_str_hashtbl[i])) { 4794 while (!list_empty(&unconf_str_hashtbl[i])) {
4793 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash); 4795 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
4794 expire_client(clp); 4796 destroy_client(clp);
4795 } 4797 }
4796 } 4798 }
4797 INIT_LIST_HEAD(&reaplist); 4799 INIT_LIST_HEAD(&reaplist);