aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/host.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/lockd/host.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r--fs/lockd/host.c418
1 files changed, 249 insertions, 169 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index bb464d12104c..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,126 +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 &&
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;
134
135 host->h_rpcclnt = NULL;
136 host->h_name = nsm->sm_name;
170 host->h_version = ni->version; 137 host->h_version = ni->version;
171 host->h_proto = ni->protocol; 138 host->h_proto = ni->protocol;
172 host->h_rpcclnt = NULL; 139 host->h_reclaiming = 0;
173 mutex_init(&host->h_mutex); 140 host->h_server = ni->server;
174 host->h_nextrebind = jiffies + NLM_HOST_REBIND; 141 host->h_noresvport = ni->noresvport;
175 host->h_expires = jiffies + NLM_HOST_EXPIRE; 142 host->h_inuse = 0;
176 atomic_set(&host->h_count, 1);
177 init_waitqueue_head(&host->h_gracewait); 143 init_waitqueue_head(&host->h_gracewait);
178 init_rwsem(&host->h_rwsem); 144 init_rwsem(&host->h_rwsem);
179 host->h_state = 0; /* pseudo NSM state */ 145 host->h_state = 0;
180 host->h_nsmstate = 0; /* real NSM state */ 146 host->h_nsmstate = 0;
181 host->h_nsmhandle = nsm; 147 host->h_pidcount = 0;
182 host->h_server = ni->server; 148 atomic_set(&host->h_count, 1);
183 host->h_noresvport = ni->noresvport; 149 mutex_init(&host->h_mutex);
184 hlist_add_head(&host->h_hash, chain); 150 host->h_nextrebind = now + NLM_HOST_REBIND;
151 host->h_expires = now + NLM_HOST_EXPIRE;
185 INIT_LIST_HEAD(&host->h_lockowners); 152 INIT_LIST_HEAD(&host->h_lockowners);
186 spin_lock_init(&host->h_lock); 153 spin_lock_init(&host->h_lock);
187 INIT_LIST_HEAD(&host->h_granted); 154 INIT_LIST_HEAD(&host->h_granted);
188 INIT_LIST_HEAD(&host->h_reclaim); 155 INIT_LIST_HEAD(&host->h_reclaim);
189 156 host->h_nsmhandle = nsm;
190 nrhosts++; 157 host->h_addrbuf = nsm->sm_addrbuf;
191
192 dprintk("lockd: nlm_lookup_host created host %s\n",
193 host->h_name);
194 158
195out: 159out:
196 mutex_unlock(&nlm_host_mutex);
197 return host; 160 return host;
198} 161}
199 162
200/* 163/*
201 * Destroy a host 164 * Destroy an nlm_host and free associated resources
165 *
166 * Caller must hold nlm_host_mutex.
202 */ 167 */
203static void 168static void nlm_destroy_host_locked(struct nlm_host *host)
204nlm_destroy_host(struct nlm_host *host)
205{ 169{
206 struct rpc_clnt *clnt; 170 struct rpc_clnt *clnt;
207 171
172 dprintk("lockd: destroy host %s\n", host->h_name);
173
208 BUG_ON(!list_empty(&host->h_lockowners)); 174 BUG_ON(!list_empty(&host->h_lockowners));
209 BUG_ON(atomic_read(&host->h_count)); 175 BUG_ON(atomic_read(&host->h_count));
210 176
177 hlist_del_init(&host->h_hash);
178
211 nsm_unmonitor(host); 179 nsm_unmonitor(host);
212 nsm_release(host->h_nsmhandle); 180 nsm_release(host->h_nsmhandle);
213 181
@@ -215,6 +183,8 @@ nlm_destroy_host(struct nlm_host *host)
215 if (clnt != NULL) 183 if (clnt != NULL)
216 rpc_shutdown_client(clnt); 184 rpc_shutdown_client(clnt);
217 kfree(host); 185 kfree(host);
186
187 nrhosts--;
218} 188}
219 189
220/** 190/**
@@ -238,9 +208,6 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
238 const char *hostname, 208 const char *hostname,
239 int noresvport) 209 int noresvport)
240{ 210{
241 const struct sockaddr source = {
242 .sa_family = AF_UNSPEC,
243 };
244 struct nlm_lookup_host_info ni = { 211 struct nlm_lookup_host_info ni = {
245 .server = 0, 212 .server = 0,
246 .sap = sap, 213 .sap = sap,
@@ -249,16 +216,78 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
249 .version = version, 216 .version = version,
250 .hostname = hostname, 217 .hostname = hostname,
251 .hostname_len = strlen(hostname), 218 .hostname_len = strlen(hostname),
252 .src_sap = &source,
253 .src_len = sizeof(source),
254 .noresvport = noresvport, 219 .noresvport = noresvport,
255 }; 220 };
221 struct hlist_head *chain;
222 struct hlist_node *pos;
223 struct nlm_host *host;
224 struct nsm_handle *nsm = NULL;
256 225
257 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, 226 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
258 (hostname ? hostname : "<none>"), version, 227 (hostname ? hostname : "<none>"), version,
259 (protocol == IPPROTO_UDP ? "udp" : "tcp")); 228 (protocol == IPPROTO_UDP ? "udp" : "tcp"));
260 229
261 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 }
262} 291}
263 292
264/** 293/**
@@ -283,12 +312,18 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
283 const char *hostname, 312 const char *hostname,
284 const size_t hostname_len) 313 const size_t hostname_len)
285{ 314{
315 struct hlist_head *chain;
316 struct hlist_node *pos;
317 struct nlm_host *host = NULL;
318 struct nsm_handle *nsm = NULL;
286 struct sockaddr_in sin = { 319 struct sockaddr_in sin = {
287 .sin_family = AF_INET, 320 .sin_family = AF_INET,
288 }; 321 };
289 struct sockaddr_in6 sin6 = { 322 struct sockaddr_in6 sin6 = {
290 .sin6_family = AF_INET6, 323 .sin6_family = AF_INET6,
291 }; 324 };
325 struct sockaddr *src_sap;
326 size_t src_len = rqstp->rq_addrlen;
292 struct nlm_lookup_host_info ni = { 327 struct nlm_lookup_host_info ni = {
293 .server = 1, 328 .server = 1,
294 .sap = svc_addr(rqstp), 329 .sap = svc_addr(rqstp),
@@ -297,27 +332,91 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
297 .version = rqstp->rq_vers, 332 .version = rqstp->rq_vers,
298 .hostname = hostname, 333 .hostname = hostname,
299 .hostname_len = hostname_len, 334 .hostname_len = hostname_len,
300 .src_len = rqstp->rq_addrlen,
301 }; 335 };
302 336
303 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, 337 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
304 (int)hostname_len, hostname, rqstp->rq_vers, 338 (int)hostname_len, hostname, rqstp->rq_vers,
305 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); 339 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp"));
306 340
341 mutex_lock(&nlm_host_mutex);
342
307 switch (ni.sap->sa_family) { 343 switch (ni.sap->sa_family) {
308 case AF_INET: 344 case AF_INET:
309 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr; 345 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr;
310 ni.src_sap = (struct sockaddr *)&sin; 346 src_sap = (struct sockaddr *)&sin;
311 break; 347 break;
312 case AF_INET6: 348 case AF_INET6:
313 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6); 349 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6);
314 ni.src_sap = (struct sockaddr *)&sin6; 350 src_sap = (struct sockaddr *)&sin6;
315 break; 351 break;
316 default: 352 default:
317 return NULL; 353 dprintk("lockd: %s failed; unrecognized address family\n",
354 __func__);
355 goto out;
318 } 356 }
319 357
320 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);
321} 420}
322 421
323/* 422/*
@@ -353,10 +452,10 @@ nlm_bind_host(struct nlm_host *host)
353 .to_retries = 5U, 452 .to_retries = 5U,
354 }; 453 };
355 struct rpc_create_args args = { 454 struct rpc_create_args args = {
455 .net = &init_net,
356 .protocol = host->h_proto, 456 .protocol = host->h_proto,
357 .address = nlm_addr(host), 457 .address = nlm_addr(host),
358 .addrsize = host->h_addrlen, 458 .addrsize = host->h_addrlen,
359 .saddress = nlm_srcaddr(host),
360 .timeout = &timeparms, 459 .timeout = &timeparms,
361 .servername = host->h_name, 460 .servername = host->h_name,
362 .program = &nlm_program, 461 .program = &nlm_program,
@@ -375,6 +474,8 @@ nlm_bind_host(struct nlm_host *host)
375 args.flags |= RPC_CLNT_CREATE_HARDRTRY; 474 args.flags |= RPC_CLNT_CREATE_HARDRTRY;
376 if (host->h_noresvport) 475 if (host->h_noresvport)
377 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; 476 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
477 if (host->h_srcaddrlen)
478 args.saddress = nlm_srcaddr(host);
378 479
379 clnt = rpc_create(&args); 480 clnt = rpc_create(&args);
380 if (!IS_ERR(clnt)) 481 if (!IS_ERR(clnt))
@@ -415,20 +516,29 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)
415 return host; 516 return host;
416} 517}
417 518
418/* 519static struct nlm_host *next_host_state(struct hlist_head *cache,
419 * Release NLM host after use 520 struct nsm_handle *nsm,
420 */ 521 const struct nlm_reboot *info)
421void nlm_release_host(struct nlm_host *host)
422{ 522{
423 if (host != NULL) { 523 struct nlm_host *host;
424 dprintk("lockd: release host %s\n", host->h_name); 524 struct hlist_head *chain;
425 BUG_ON(atomic_read(&host->h_count) < 0); 525 struct hlist_node *pos;
426 if (atomic_dec_and_test(&host->h_count)) { 526
427 BUG_ON(!list_empty(&host->h_lockowners)); 527 mutex_lock(&nlm_host_mutex);
428 BUG_ON(!list_empty(&host->h_granted)); 528 for_each_host(host, pos, chain, cache) {
429 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;
430 } 537 }
431 } 538 }
539
540 mutex_unlock(&nlm_host_mutex);
541 return NULL;
432} 542}
433 543
434/** 544/**
@@ -440,8 +550,6 @@ void nlm_release_host(struct nlm_host *host)
440 */ 550 */
441void nlm_host_rebooted(const struct nlm_reboot *info) 551void nlm_host_rebooted(const struct nlm_reboot *info)
442{ 552{
443 struct hlist_head *chain;
444 struct hlist_node *pos;
445 struct nsm_handle *nsm; 553 struct nsm_handle *nsm;
446 struct nlm_host *host; 554 struct nlm_host *host;
447 555
@@ -454,32 +562,15 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
454 * lock for this. 562 * lock for this.
455 * To avoid processing a host several times, we match the nsmstate. 563 * To avoid processing a host several times, we match the nsmstate.
456 */ 564 */
457again: mutex_lock(&nlm_host_mutex); 565 while ((host = next_host_state(nlm_server_hosts, nsm, info)) != NULL) {
458 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 566 nlmsvc_free_host_resources(host);
459 hlist_for_each_entry(host, pos, chain, h_hash) { 567 nlmsvc_release_host(host);
460 if (host->h_nsmhandle == nsm
461 && host->h_nsmstate != info->state) {
462 host->h_nsmstate = info->state;
463 host->h_state++;
464
465 nlm_get_host(host);
466 mutex_unlock(&nlm_host_mutex);
467
468 if (host->h_server) {
469 /* We're server for this guy, just ditch
470 * all the locks he held. */
471 nlmsvc_free_host_resources(host);
472 } else {
473 /* He's the server, initiate lock recovery. */
474 nlmclnt_recovery(host);
475 }
476
477 nlm_release_host(host);
478 goto again;
479 }
480 }
481 } 568 }
482 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
483 nsm_release(nsm); 574 nsm_release(nsm);
484} 575}
485 576
@@ -499,13 +590,11 @@ nlm_shutdown_hosts(void)
499 590
500 /* First, make all hosts eligible for gc */ 591 /* First, make all hosts eligible for gc */
501 dprintk("lockd: nuking all hosts...\n"); 592 dprintk("lockd: nuking all hosts...\n");
502 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 593 for_each_host(host, pos, chain, nlm_server_hosts) {
503 hlist_for_each_entry(host, pos, chain, h_hash) { 594 host->h_expires = jiffies - 1;
504 host->h_expires = jiffies - 1; 595 if (host->h_rpcclnt) {
505 if (host->h_rpcclnt) { 596 rpc_shutdown_client(host->h_rpcclnt);
506 rpc_shutdown_client(host->h_rpcclnt); 597 host->h_rpcclnt = NULL;
507 host->h_rpcclnt = NULL;
508 }
509 } 598 }
510 } 599 }
511 600
@@ -514,15 +603,13 @@ nlm_shutdown_hosts(void)
514 mutex_unlock(&nlm_host_mutex); 603 mutex_unlock(&nlm_host_mutex);
515 604
516 /* complain if any hosts are left */ 605 /* complain if any hosts are left */
517 if (nrhosts) { 606 if (nrhosts != 0) {
518 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); 607 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
519 dprintk("lockd: %d hosts left:\n", nrhosts); 608 dprintk("lockd: %lu hosts left:\n", nrhosts);
520 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 609 for_each_host(host, pos, chain, nlm_server_hosts) {
521 hlist_for_each_entry(host, pos, chain, h_hash) { 610 dprintk(" %s (cnt %d use %d exp %ld)\n",
522 dprintk(" %s (cnt %d use %d exp %ld)\n", 611 host->h_name, atomic_read(&host->h_count),
523 host->h_name, atomic_read(&host->h_count), 612 host->h_inuse, host->h_expires);
524 host->h_inuse, host->h_expires);
525 }
526 } 613 }
527 } 614 }
528} 615}
@@ -540,29 +627,22 @@ nlm_gc_hosts(void)
540 struct nlm_host *host; 627 struct nlm_host *host;
541 628
542 dprintk("lockd: host garbage collection\n"); 629 dprintk("lockd: host garbage collection\n");
543 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 630 for_each_host(host, pos, chain, nlm_server_hosts)
544 hlist_for_each_entry(host, pos, chain, h_hash) 631 host->h_inuse = 0;
545 host->h_inuse = 0;
546 }
547 632
548 /* Mark all hosts that hold locks, blocks or shares */ 633 /* Mark all hosts that hold locks, blocks or shares */
549 nlmsvc_mark_resources(); 634 nlmsvc_mark_resources();
550 635
551 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 636 for_each_host_safe(host, pos, next, chain, nlm_server_hosts) {
552 hlist_for_each_entry_safe(host, pos, next, chain, h_hash) { 637 if (atomic_read(&host->h_count) || host->h_inuse
553 if (atomic_read(&host->h_count) || host->h_inuse 638 || time_before(jiffies, host->h_expires)) {
554 || time_before(jiffies, host->h_expires)) { 639 dprintk("nlm_gc_hosts skipping %s "
555 dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n", 640 "(cnt %d use %d exp %ld)\n",
556 host->h_name, atomic_read(&host->h_count), 641 host->h_name, atomic_read(&host->h_count),
557 host->h_inuse, host->h_expires); 642 host->h_inuse, host->h_expires);
558 continue; 643 continue;
559 }
560 dprintk("lockd: delete host %s\n", host->h_name);
561 hlist_del_init(&host->h_hash);
562
563 nlm_destroy_host(host);
564 nrhosts--;
565 } 644 }
645 nlm_destroy_host_locked(host);
566 } 646 }
567 647
568 next_gc = jiffies + NLM_HOST_COLLECT; 648 next_gc = jiffies + NLM_HOST_COLLECT;