aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/host.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r--fs/lockd/host.c410
1 files changed, 246 insertions, 164 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index ed0c59fe23ce..b7c99bfb3da6 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -25,9 +25,22 @@
25#define NLM_HOST_EXPIRE (300 * HZ) 25#define NLM_HOST_EXPIRE (300 * HZ)
26#define NLM_HOST_COLLECT (120 * HZ) 26#define NLM_HOST_COLLECT (120 * HZ)
27 27
28static struct hlist_head nlm_hosts[NLM_HOST_NRHASH]; 28static struct hlist_head nlm_server_hosts[NLM_HOST_NRHASH];
29static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH];
30
31#define for_each_host(host, pos, chain, table) \
32 for ((chain) = (table); \
33 (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \
34 hlist_for_each_entry((host), (pos), (chain), h_hash)
35
36#define for_each_host_safe(host, pos, next, chain, table) \
37 for ((chain) = (table); \
38 (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \
39 hlist_for_each_entry_safe((host), (pos), (next), \
40 (chain), h_hash)
41
29static unsigned long next_gc; 42static unsigned long next_gc;
30static int nrhosts; 43static unsigned long nrhosts;
31static DEFINE_MUTEX(nlm_host_mutex); 44static DEFINE_MUTEX(nlm_host_mutex);
32 45
33static void nlm_gc_hosts(void); 46static void nlm_gc_hosts(void);
@@ -40,8 +53,6 @@ struct nlm_lookup_host_info {
40 const u32 version; /* NLM version to search for */ 53 const u32 version; /* NLM version to search for */
41 const char *hostname; /* remote's hostname */ 54 const char *hostname; /* remote's hostname */
42 const size_t hostname_len; /* it's length */ 55 const size_t hostname_len; /* it's length */
43 const struct sockaddr *src_sap; /* our address (optional) */
44 const size_t src_len; /* it's length */
45 const int noresvport; /* use non-priv port */ 56 const int noresvport; /* use non-priv port */
46}; 57};
47 58
@@ -88,127 +99,83 @@ static unsigned int nlm_hash_address(const struct sockaddr *sap)
88} 99}
89 100
90/* 101/*
91 * Common host lookup routine for server & client 102 * Allocate and initialize an nlm_host. Common to both client and server.
92 */ 103 */
93static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) 104static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni,
105 struct nsm_handle *nsm)
94{ 106{
95 struct hlist_head *chain; 107 struct nlm_host *host = NULL;
96 struct hlist_node *pos; 108 unsigned long now = jiffies;
97 struct nlm_host *host;
98 struct nsm_handle *nsm = NULL;
99
100 mutex_lock(&nlm_host_mutex);
101
102 if (time_after_eq(jiffies, next_gc))
103 nlm_gc_hosts();
104
105 /* We may keep several nlm_host objects for a peer, because each
106 * nlm_host is identified by
107 * (address, protocol, version, server/client)
108 * We could probably simplify this a little by putting all those
109 * different NLM rpc_clients into one single nlm_host object.
110 * This would allow us to have one nlm_host per address.
111 */
112 chain = &nlm_hosts[nlm_hash_address(ni->sap)];
113 hlist_for_each_entry(host, pos, chain, h_hash) {
114 if (!rpc_cmp_addr(nlm_addr(host), ni->sap))
115 continue;
116
117 /* See if we have an NSM handle for this client */
118 if (!nsm)
119 nsm = host->h_nsmhandle;
120
121 if (host->h_proto != ni->protocol)
122 continue;
123 if (host->h_version != ni->version)
124 continue;
125 if (host->h_server != ni->server)
126 continue;
127 if (ni->server && ni->src_len != 0 &&
128 !rpc_cmp_addr(nlm_srcaddr(host), ni->src_sap))
129 continue;
130
131 /* Move to head of hash chain. */
132 hlist_del(&host->h_hash);
133 hlist_add_head(&host->h_hash, chain);
134
135 nlm_get_host(host);
136 dprintk("lockd: nlm_lookup_host found host %s (%s)\n",
137 host->h_name, host->h_addrbuf);
138 goto out;
139 }
140 109
141 /* 110 if (nsm != NULL)
142 * The host wasn't in our hash table. If we don't
143 * have an NSM handle for it yet, create one.
144 */
145 if (nsm)
146 atomic_inc(&nsm->sm_count); 111 atomic_inc(&nsm->sm_count);
147 else { 112 else {
148 host = NULL; 113 host = NULL;
149 nsm = nsm_get_handle(ni->sap, ni->salen, 114 nsm = nsm_get_handle(ni->sap, ni->salen,
150 ni->hostname, ni->hostname_len); 115 ni->hostname, ni->hostname_len);
151 if (!nsm) { 116 if (unlikely(nsm == NULL)) {
152 dprintk("lockd: nlm_lookup_host failed; " 117 dprintk("lockd: %s failed; no nsm handle\n",
153 "no nsm handle\n"); 118 __func__);
154 goto out; 119 goto out;
155 } 120 }
156 } 121 }
157 122
158 host = kzalloc(sizeof(*host), GFP_KERNEL); 123 host = kmalloc(sizeof(*host), GFP_KERNEL);
159 if (!host) { 124 if (unlikely(host == NULL)) {
125 dprintk("lockd: %s failed; no memory\n", __func__);
160 nsm_release(nsm); 126 nsm_release(nsm);
161 dprintk("lockd: nlm_lookup_host failed; no memory\n");
162 goto out; 127 goto out;
163 } 128 }
164 host->h_name = nsm->sm_name; 129
165 host->h_addrbuf = nsm->sm_addrbuf;
166 memcpy(nlm_addr(host), ni->sap, ni->salen); 130 memcpy(nlm_addr(host), ni->sap, ni->salen);
167 host->h_addrlen = ni->salen; 131 host->h_addrlen = ni->salen;
168 rpc_set_port(nlm_addr(host), 0); 132 rpc_set_port(nlm_addr(host), 0);
169 memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len); 133 host->h_srcaddrlen = 0;
170 host->h_srcaddrlen = ni->src_len; 134
135 host->h_rpcclnt = NULL;
136 host->h_name = nsm->sm_name;
171 host->h_version = ni->version; 137 host->h_version = ni->version;
172 host->h_proto = ni->protocol; 138 host->h_proto = ni->protocol;
173 host->h_rpcclnt = NULL; 139 host->h_reclaiming = 0;
174 mutex_init(&host->h_mutex); 140 host->h_server = ni->server;
175 host->h_nextrebind = jiffies + NLM_HOST_REBIND; 141 host->h_noresvport = ni->noresvport;
176 host->h_expires = jiffies + NLM_HOST_EXPIRE; 142 host->h_inuse = 0;
177 atomic_set(&host->h_count, 1);
178 init_waitqueue_head(&host->h_gracewait); 143 init_waitqueue_head(&host->h_gracewait);
179 init_rwsem(&host->h_rwsem); 144 init_rwsem(&host->h_rwsem);
180 host->h_state = 0; /* pseudo NSM state */ 145 host->h_state = 0;
181 host->h_nsmstate = 0; /* real NSM state */ 146 host->h_nsmstate = 0;
182 host->h_nsmhandle = nsm; 147 host->h_pidcount = 0;
183 host->h_server = ni->server; 148 atomic_set(&host->h_count, 1);
184 host->h_noresvport = ni->noresvport; 149 mutex_init(&host->h_mutex);
185 hlist_add_head(&host->h_hash, chain); 150 host->h_nextrebind = now + NLM_HOST_REBIND;
151 host->h_expires = now + NLM_HOST_EXPIRE;
186 INIT_LIST_HEAD(&host->h_lockowners); 152 INIT_LIST_HEAD(&host->h_lockowners);
187 spin_lock_init(&host->h_lock); 153 spin_lock_init(&host->h_lock);
188 INIT_LIST_HEAD(&host->h_granted); 154 INIT_LIST_HEAD(&host->h_granted);
189 INIT_LIST_HEAD(&host->h_reclaim); 155 INIT_LIST_HEAD(&host->h_reclaim);
190 156 host->h_nsmhandle = nsm;
191 nrhosts++; 157 host->h_addrbuf = nsm->sm_addrbuf;
192
193 dprintk("lockd: nlm_lookup_host created host %s\n",
194 host->h_name);
195 158
196out: 159out:
197 mutex_unlock(&nlm_host_mutex);
198 return host; 160 return host;
199} 161}
200 162
201/* 163/*
202 * Destroy a host 164 * Destroy an nlm_host and free associated resources
165 *
166 * Caller must hold nlm_host_mutex.
203 */ 167 */
204static void 168static void nlm_destroy_host_locked(struct nlm_host *host)
205nlm_destroy_host(struct nlm_host *host)
206{ 169{
207 struct rpc_clnt *clnt; 170 struct rpc_clnt *clnt;
208 171
172 dprintk("lockd: destroy host %s\n", host->h_name);
173
209 BUG_ON(!list_empty(&host->h_lockowners)); 174 BUG_ON(!list_empty(&host->h_lockowners));
210 BUG_ON(atomic_read(&host->h_count)); 175 BUG_ON(atomic_read(&host->h_count));
211 176
177 hlist_del_init(&host->h_hash);
178
212 nsm_unmonitor(host); 179 nsm_unmonitor(host);
213 nsm_release(host->h_nsmhandle); 180 nsm_release(host->h_nsmhandle);
214 181
@@ -216,6 +183,8 @@ nlm_destroy_host(struct nlm_host *host)
216 if (clnt != NULL) 183 if (clnt != NULL)
217 rpc_shutdown_client(clnt); 184 rpc_shutdown_client(clnt);
218 kfree(host); 185 kfree(host);
186
187 nrhosts--;
219} 188}
220 189
221/** 190/**
@@ -249,12 +218,76 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
249 .hostname_len = strlen(hostname), 218 .hostname_len = strlen(hostname),
250 .noresvport = noresvport, 219 .noresvport = noresvport,
251 }; 220 };
221 struct hlist_head *chain;
222 struct hlist_node *pos;
223 struct nlm_host *host;
224 struct nsm_handle *nsm = NULL;
252 225
253 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, 226 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
254 (hostname ? hostname : "<none>"), version, 227 (hostname ? hostname : "<none>"), version,
255 (protocol == IPPROTO_UDP ? "udp" : "tcp")); 228 (protocol == IPPROTO_UDP ? "udp" : "tcp"));
256 229
257 return nlm_lookup_host(&ni); 230 mutex_lock(&nlm_host_mutex);
231
232 chain = &nlm_client_hosts[nlm_hash_address(sap)];
233 hlist_for_each_entry(host, pos, chain, h_hash) {
234 if (!rpc_cmp_addr(nlm_addr(host), sap))
235 continue;
236
237 /* Same address. Share an NSM handle if we already have one */
238 if (nsm == NULL)
239 nsm = host->h_nsmhandle;
240
241 if (host->h_proto != protocol)
242 continue;
243 if (host->h_version != version)
244 continue;
245
246 nlm_get_host(host);
247 dprintk("lockd: %s found host %s (%s)\n", __func__,
248 host->h_name, host->h_addrbuf);
249 goto out;
250 }
251
252 host = nlm_alloc_host(&ni, nsm);
253 if (unlikely(host == NULL))
254 goto out;
255
256 hlist_add_head(&host->h_hash, chain);
257 nrhosts++;
258
259 dprintk("lockd: %s created host %s (%s)\n", __func__,
260 host->h_name, host->h_addrbuf);
261
262out:
263 mutex_unlock(&nlm_host_mutex);
264 return host;
265}
266
267/**
268 * nlmclnt_release_host - release client nlm_host
269 * @host: nlm_host to release
270 *
271 */
272void nlmclnt_release_host(struct nlm_host *host)
273{
274 if (host == NULL)
275 return;
276
277 dprintk("lockd: release client host %s\n", host->h_name);
278
279 BUG_ON(atomic_read(&host->h_count) < 0);
280 BUG_ON(host->h_server);
281
282 if (atomic_dec_and_test(&host->h_count)) {
283 BUG_ON(!list_empty(&host->h_lockowners));
284 BUG_ON(!list_empty(&host->h_granted));
285 BUG_ON(!list_empty(&host->h_reclaim));
286
287 mutex_lock(&nlm_host_mutex);
288 nlm_destroy_host_locked(host);
289 mutex_unlock(&nlm_host_mutex);
290 }
258} 291}
259 292
260/** 293/**
@@ -279,12 +312,18 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
279 const char *hostname, 312 const char *hostname,
280 const size_t hostname_len) 313 const size_t hostname_len)
281{ 314{
315 struct hlist_head *chain;
316 struct hlist_node *pos;
317 struct nlm_host *host = NULL;
318 struct nsm_handle *nsm = NULL;
282 struct sockaddr_in sin = { 319 struct sockaddr_in sin = {
283 .sin_family = AF_INET, 320 .sin_family = AF_INET,
284 }; 321 };
285 struct sockaddr_in6 sin6 = { 322 struct sockaddr_in6 sin6 = {
286 .sin6_family = AF_INET6, 323 .sin6_family = AF_INET6,
287 }; 324 };
325 struct sockaddr *src_sap;
326 size_t src_len = rqstp->rq_addrlen;
288 struct nlm_lookup_host_info ni = { 327 struct nlm_lookup_host_info ni = {
289 .server = 1, 328 .server = 1,
290 .sap = svc_addr(rqstp), 329 .sap = svc_addr(rqstp),
@@ -293,27 +332,91 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
293 .version = rqstp->rq_vers, 332 .version = rqstp->rq_vers,
294 .hostname = hostname, 333 .hostname = hostname,
295 .hostname_len = hostname_len, 334 .hostname_len = hostname_len,
296 .src_len = rqstp->rq_addrlen,
297 }; 335 };
298 336
299 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, 337 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
300 (int)hostname_len, hostname, rqstp->rq_vers, 338 (int)hostname_len, hostname, rqstp->rq_vers,
301 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); 339 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp"));
302 340
341 mutex_lock(&nlm_host_mutex);
342
303 switch (ni.sap->sa_family) { 343 switch (ni.sap->sa_family) {
304 case AF_INET: 344 case AF_INET:
305 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr; 345 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr;
306 ni.src_sap = (struct sockaddr *)&sin; 346 src_sap = (struct sockaddr *)&sin;
307 break; 347 break;
308 case AF_INET6: 348 case AF_INET6:
309 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6); 349 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6);
310 ni.src_sap = (struct sockaddr *)&sin6; 350 src_sap = (struct sockaddr *)&sin6;
311 break; 351 break;
312 default: 352 default:
313 return NULL; 353 dprintk("lockd: %s failed; unrecognized address family\n",
354 __func__);
355 goto out;
314 } 356 }
315 357
316 return nlm_lookup_host(&ni); 358 if (time_after_eq(jiffies, next_gc))
359 nlm_gc_hosts();
360
361 chain = &nlm_server_hosts[nlm_hash_address(ni.sap)];
362 hlist_for_each_entry(host, pos, chain, h_hash) {
363 if (!rpc_cmp_addr(nlm_addr(host), ni.sap))
364 continue;
365
366 /* Same address. Share an NSM handle if we already have one */
367 if (nsm == NULL)
368 nsm = host->h_nsmhandle;
369
370 if (host->h_proto != ni.protocol)
371 continue;
372 if (host->h_version != ni.version)
373 continue;
374 if (!rpc_cmp_addr(nlm_srcaddr(host), src_sap))
375 continue;
376
377 /* Move to head of hash chain. */
378 hlist_del(&host->h_hash);
379 hlist_add_head(&host->h_hash, chain);
380
381 nlm_get_host(host);
382 dprintk("lockd: %s found host %s (%s)\n",
383 __func__, host->h_name, host->h_addrbuf);
384 goto out;
385 }
386
387 host = nlm_alloc_host(&ni, nsm);
388 if (unlikely(host == NULL))
389 goto out;
390
391 memcpy(nlm_srcaddr(host), src_sap, src_len);
392 host->h_srcaddrlen = src_len;
393 hlist_add_head(&host->h_hash, chain);
394 nrhosts++;
395
396 dprintk("lockd: %s created host %s (%s)\n",
397 __func__, host->h_name, host->h_addrbuf);
398
399out:
400 mutex_unlock(&nlm_host_mutex);
401 return host;
402}
403
404/**
405 * nlmsvc_release_host - release server nlm_host
406 * @host: nlm_host to release
407 *
408 * Host is destroyed later in nlm_gc_host().
409 */
410void nlmsvc_release_host(struct nlm_host *host)
411{
412 if (host == NULL)
413 return;
414
415 dprintk("lockd: release server host %s\n", host->h_name);
416
417 BUG_ON(atomic_read(&host->h_count) < 0);
418 BUG_ON(!host->h_server);
419 atomic_dec(&host->h_count);
317} 420}
318 421
319/* 422/*
@@ -413,20 +516,29 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)
413 return host; 516 return host;
414} 517}
415 518
416/* 519static struct nlm_host *next_host_state(struct hlist_head *cache,
417 * Release NLM host after use 520 struct nsm_handle *nsm,
418 */ 521 const struct nlm_reboot *info)
419void nlm_release_host(struct nlm_host *host)
420{ 522{
421 if (host != NULL) { 523 struct nlm_host *host;
422 dprintk("lockd: release host %s\n", host->h_name); 524 struct hlist_head *chain;
423 BUG_ON(atomic_read(&host->h_count) < 0); 525 struct hlist_node *pos;
424 if (atomic_dec_and_test(&host->h_count)) { 526
425 BUG_ON(!list_empty(&host->h_lockowners)); 527 mutex_lock(&nlm_host_mutex);
426 BUG_ON(!list_empty(&host->h_granted)); 528 for_each_host(host, pos, chain, cache) {
427 BUG_ON(!list_empty(&host->h_reclaim)); 529 if (host->h_nsmhandle == nsm
530 && host->h_nsmstate != info->state) {
531 host->h_nsmstate = info->state;
532 host->h_state++;
533
534 nlm_get_host(host);
535 mutex_unlock(&nlm_host_mutex);
536 return host;
428 } 537 }
429 } 538 }
539
540 mutex_unlock(&nlm_host_mutex);
541 return NULL;
430} 542}
431 543
432/** 544/**
@@ -438,8 +550,6 @@ void nlm_release_host(struct nlm_host *host)
438 */ 550 */
439void nlm_host_rebooted(const struct nlm_reboot *info) 551void nlm_host_rebooted(const struct nlm_reboot *info)
440{ 552{
441 struct hlist_head *chain;
442 struct hlist_node *pos;
443 struct nsm_handle *nsm; 553 struct nsm_handle *nsm;
444 struct nlm_host *host; 554 struct nlm_host *host;
445 555
@@ -452,32 +562,15 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
452 * lock for this. 562 * lock for this.
453 * To avoid processing a host several times, we match the nsmstate. 563 * To avoid processing a host several times, we match the nsmstate.
454 */ 564 */
455again: mutex_lock(&nlm_host_mutex); 565 while ((host = next_host_state(nlm_server_hosts, nsm, info)) != NULL) {
456 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 566 nlmsvc_free_host_resources(host);
457 hlist_for_each_entry(host, pos, chain, h_hash) { 567 nlmsvc_release_host(host);
458 if (host->h_nsmhandle == nsm
459 && host->h_nsmstate != info->state) {
460 host->h_nsmstate = info->state;
461 host->h_state++;
462
463 nlm_get_host(host);
464 mutex_unlock(&nlm_host_mutex);
465
466 if (host->h_server) {
467 /* We're server for this guy, just ditch
468 * all the locks he held. */
469 nlmsvc_free_host_resources(host);
470 } else {
471 /* He's the server, initiate lock recovery. */
472 nlmclnt_recovery(host);
473 }
474
475 nlm_release_host(host);
476 goto again;
477 }
478 }
479 } 568 }
480 mutex_unlock(&nlm_host_mutex); 569 while ((host = next_host_state(nlm_client_hosts, nsm, info)) != NULL) {
570 nlmclnt_recovery(host);
571 nlmclnt_release_host(host);
572 }
573
481 nsm_release(nsm); 574 nsm_release(nsm);
482} 575}
483 576
@@ -497,13 +590,11 @@ nlm_shutdown_hosts(void)
497 590
498 /* First, make all hosts eligible for gc */ 591 /* First, make all hosts eligible for gc */
499 dprintk("lockd: nuking all hosts...\n"); 592 dprintk("lockd: nuking all hosts...\n");
500 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 593 for_each_host(host, pos, chain, nlm_server_hosts) {
501 hlist_for_each_entry(host, pos, chain, h_hash) { 594 host->h_expires = jiffies - 1;
502 host->h_expires = jiffies - 1; 595 if (host->h_rpcclnt) {
503 if (host->h_rpcclnt) { 596 rpc_shutdown_client(host->h_rpcclnt);
504 rpc_shutdown_client(host->h_rpcclnt); 597 host->h_rpcclnt = NULL;
505 host->h_rpcclnt = NULL;
506 }
507 } 598 }
508 } 599 }
509 600
@@ -512,15 +603,13 @@ nlm_shutdown_hosts(void)
512 mutex_unlock(&nlm_host_mutex); 603 mutex_unlock(&nlm_host_mutex);
513 604
514 /* complain if any hosts are left */ 605 /* complain if any hosts are left */
515 if (nrhosts) { 606 if (nrhosts != 0) {
516 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); 607 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
517 dprintk("lockd: %d hosts left:\n", nrhosts); 608 dprintk("lockd: %lu hosts left:\n", nrhosts);
518 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 609 for_each_host(host, pos, chain, nlm_server_hosts) {
519 hlist_for_each_entry(host, pos, chain, h_hash) { 610 dprintk(" %s (cnt %d use %d exp %ld)\n",
520 dprintk(" %s (cnt %d use %d exp %ld)\n", 611 host->h_name, atomic_read(&host->h_count),
521 host->h_name, atomic_read(&host->h_count), 612 host->h_inuse, host->h_expires);
522 host->h_inuse, host->h_expires);
523 }
524 } 613 }
525 } 614 }
526} 615}
@@ -538,29 +627,22 @@ nlm_gc_hosts(void)
538 struct nlm_host *host; 627 struct nlm_host *host;
539 628
540 dprintk("lockd: host garbage collection\n"); 629 dprintk("lockd: host garbage collection\n");
541 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 630 for_each_host(host, pos, chain, nlm_server_hosts)
542 hlist_for_each_entry(host, pos, chain, h_hash) 631 host->h_inuse = 0;
543 host->h_inuse = 0;
544 }
545 632
546 /* Mark all hosts that hold locks, blocks or shares */ 633 /* Mark all hosts that hold locks, blocks or shares */
547 nlmsvc_mark_resources(); 634 nlmsvc_mark_resources();
548 635
549 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 636 for_each_host_safe(host, pos, next, chain, nlm_server_hosts) {
550 hlist_for_each_entry_safe(host, pos, next, chain, h_hash) { 637 if (atomic_read(&host->h_count) || host->h_inuse
551 if (atomic_read(&host->h_count) || host->h_inuse 638 || time_before(jiffies, host->h_expires)) {
552 || time_before(jiffies, host->h_expires)) { 639 dprintk("nlm_gc_hosts skipping %s "
553 dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n", 640 "(cnt %d use %d exp %ld)\n",
554 host->h_name, atomic_read(&host->h_count), 641 host->h_name, atomic_read(&host->h_count),
555 host->h_inuse, host->h_expires); 642 host->h_inuse, host->h_expires);
556 continue; 643 continue;
557 }
558 dprintk("lockd: delete host %s\n", host->h_name);
559 hlist_del_init(&host->h_hash);
560
561 nlm_destroy_host(host);
562 nrhosts--;
563 } 644 }
645 nlm_destroy_host_locked(host);
564 } 646 }
565 647
566 next_gc = jiffies + NLM_HOST_COLLECT; 648 next_gc = jiffies + NLM_HOST_COLLECT;