diff options
author | J. Bruce Fields <bfields@redhat.com> | 2012-09-26 11:36:16 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-10-01 17:40:04 -0400 |
commit | 0d22f68f02c10d5d10ec5712917e5828b001a822 (patch) | |
tree | 7b0d005f8bffe4623c1df2d65a14d321598c70c9 /fs | |
parent | 6a3b15634279aa6740f9b829d25db32024b2ca7c (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.c | 18 |
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 | ||
1120 | static void | 1120 | static void |
1121 | expire_client(struct nfs4_client *clp) | 1121 | destroy_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 | ||
1155 | static void expire_client(struct nfs4_client *clp) | ||
1156 | { | ||
1157 | nfsd4_client_record_remove(clp); | ||
1158 | destroy_client(clp); | ||
1159 | } | ||
1160 | |||
1155 | static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) | 1161 | static 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); |