diff options
Diffstat (limited to 'fs/lockd')
-rw-r--r-- | fs/lockd/host.c | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 3cd96e2e1256..4449ef0b7837 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ) | 27 | #define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ) |
28 | #define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ) | 28 | #define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ) |
29 | 29 | ||
30 | static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH]; | 30 | static struct hlist_head nlm_hosts[NLM_HOST_NRHASH]; |
31 | static unsigned long next_gc; | 31 | static unsigned long next_gc; |
32 | static int nrhosts; | 32 | static int nrhosts; |
33 | static DEFINE_MUTEX(nlm_host_mutex); | 33 | static DEFINE_MUTEX(nlm_host_mutex); |
@@ -69,7 +69,9 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin, | |||
69 | const char *hostname, | 69 | const char *hostname, |
70 | int hostname_len) | 70 | int hostname_len) |
71 | { | 71 | { |
72 | struct nlm_host *host, **hp; | 72 | struct hlist_head *chain; |
73 | struct hlist_node *pos; | ||
74 | struct nlm_host *host; | ||
73 | struct nsm_handle *nsm = NULL; | 75 | struct nsm_handle *nsm = NULL; |
74 | int hash; | 76 | int hash; |
75 | 77 | ||
@@ -95,7 +97,8 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin, | |||
95 | * different NLM rpc_clients into one single nlm_host object. | 97 | * different NLM rpc_clients into one single nlm_host object. |
96 | * This would allow us to have one nlm_host per address. | 98 | * This would allow us to have one nlm_host per address. |
97 | */ | 99 | */ |
98 | for (hp = &nlm_hosts[hash]; (host = *hp) != 0; hp = &host->h_next) { | 100 | chain = &nlm_hosts[hash]; |
101 | hlist_for_each_entry(host, pos, chain, h_hash) { | ||
99 | if (!nlm_cmp_addr(&host->h_addr, sin)) | 102 | if (!nlm_cmp_addr(&host->h_addr, sin)) |
100 | continue; | 103 | continue; |
101 | 104 | ||
@@ -110,15 +113,16 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin, | |||
110 | if (host->h_server != server) | 113 | if (host->h_server != server) |
111 | continue; | 114 | continue; |
112 | 115 | ||
113 | if (hp != nlm_hosts + hash) { | 116 | /* Move to head of hash chain. */ |
114 | *hp = host->h_next; | 117 | hlist_del(&host->h_hash); |
115 | host->h_next = nlm_hosts[hash]; | 118 | hlist_add_head(&host->h_hash, chain); |
116 | nlm_hosts[hash] = host; | 119 | |
117 | } | ||
118 | nlm_get_host(host); | 120 | nlm_get_host(host); |
119 | goto out; | 121 | goto out; |
120 | } | 122 | } |
121 | 123 | ||
124 | host = NULL; | ||
125 | |||
122 | /* Sadly, the host isn't in our hash table yet. See if | 126 | /* Sadly, the host isn't in our hash table yet. See if |
123 | * we have an NSM handle for it. If not, create one. | 127 | * we have an NSM handle for it. If not, create one. |
124 | */ | 128 | */ |
@@ -146,8 +150,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin, | |||
146 | host->h_nsmstate = 0; /* real NSM state */ | 150 | host->h_nsmstate = 0; /* real NSM state */ |
147 | host->h_nsmhandle = nsm; | 151 | host->h_nsmhandle = nsm; |
148 | host->h_server = server; | 152 | host->h_server = server; |
149 | host->h_next = nlm_hosts[hash]; | 153 | hlist_add_head(&host->h_hash, chain); |
150 | nlm_hosts[hash] = host; | ||
151 | INIT_LIST_HEAD(&host->h_lockowners); | 154 | INIT_LIST_HEAD(&host->h_lockowners); |
152 | spin_lock_init(&host->h_lock); | 155 | spin_lock_init(&host->h_lock); |
153 | INIT_LIST_HEAD(&host->h_granted); | 156 | INIT_LIST_HEAD(&host->h_granted); |
@@ -164,14 +167,17 @@ out: | |||
164 | struct nlm_host * | 167 | struct nlm_host * |
165 | nlm_find_client(void) | 168 | nlm_find_client(void) |
166 | { | 169 | { |
170 | struct hlist_head *chain; | ||
171 | struct hlist_node *pos; | ||
172 | |||
167 | /* find a nlm_host for a client for which h_killed == 0. | 173 | /* find a nlm_host for a client for which h_killed == 0. |
168 | * and return it | 174 | * and return it |
169 | */ | 175 | */ |
170 | int hash; | ||
171 | mutex_lock(&nlm_host_mutex); | 176 | mutex_lock(&nlm_host_mutex); |
172 | for (hash = 0 ; hash < NLM_HOST_NRHASH; hash++) { | 177 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { |
173 | struct nlm_host *host, **hp; | 178 | struct nlm_host *host; |
174 | for (hp = &nlm_hosts[hash]; (host = *hp) != 0; hp = &host->h_next) { | 179 | |
180 | hlist_for_each_entry(host, pos, chain, h_hash) { | ||
175 | if (host->h_server && | 181 | if (host->h_server && |
176 | host->h_killed == 0) { | 182 | host->h_killed == 0) { |
177 | nlm_get_host(host); | 183 | nlm_get_host(host); |
@@ -294,9 +300,10 @@ void nlm_host_rebooted(const struct sockaddr_in *sin, | |||
294 | const char *hostname, int hostname_len, | 300 | const char *hostname, int hostname_len, |
295 | u32 new_state) | 301 | u32 new_state) |
296 | { | 302 | { |
303 | struct hlist_head *chain; | ||
304 | struct hlist_node *pos; | ||
297 | struct nsm_handle *nsm; | 305 | struct nsm_handle *nsm; |
298 | struct nlm_host *host, **hp; | 306 | struct nlm_host *host; |
299 | int hash; | ||
300 | 307 | ||
301 | dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n", | 308 | dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n", |
302 | hostname, NIPQUAD(sin->sin_addr)); | 309 | hostname, NIPQUAD(sin->sin_addr)); |
@@ -315,8 +322,8 @@ void nlm_host_rebooted(const struct sockaddr_in *sin, | |||
315 | * To avoid processing a host several times, we match the nsmstate. | 322 | * To avoid processing a host several times, we match the nsmstate. |
316 | */ | 323 | */ |
317 | again: mutex_lock(&nlm_host_mutex); | 324 | again: mutex_lock(&nlm_host_mutex); |
318 | for (hash = 0; hash < NLM_HOST_NRHASH; hash++) { | 325 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { |
319 | for (hp = &nlm_hosts[hash]; (host = *hp); hp = &host->h_next) { | 326 | hlist_for_each_entry(host, pos, chain, h_hash) { |
320 | if (host->h_nsmhandle == nsm | 327 | if (host->h_nsmhandle == nsm |
321 | && host->h_nsmstate != new_state) { | 328 | && host->h_nsmstate != new_state) { |
322 | host->h_nsmstate = new_state; | 329 | host->h_nsmstate = new_state; |
@@ -350,16 +357,17 @@ again: mutex_lock(&nlm_host_mutex); | |||
350 | void | 357 | void |
351 | nlm_shutdown_hosts(void) | 358 | nlm_shutdown_hosts(void) |
352 | { | 359 | { |
360 | struct hlist_head *chain; | ||
361 | struct hlist_node *pos; | ||
353 | struct nlm_host *host; | 362 | struct nlm_host *host; |
354 | int i; | ||
355 | 363 | ||
356 | dprintk("lockd: shutting down host module\n"); | 364 | dprintk("lockd: shutting down host module\n"); |
357 | mutex_lock(&nlm_host_mutex); | 365 | mutex_lock(&nlm_host_mutex); |
358 | 366 | ||
359 | /* First, make all hosts eligible for gc */ | 367 | /* First, make all hosts eligible for gc */ |
360 | dprintk("lockd: nuking all hosts...\n"); | 368 | dprintk("lockd: nuking all hosts...\n"); |
361 | for (i = 0; i < NLM_HOST_NRHASH; i++) { | 369 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { |
362 | for (host = nlm_hosts[i]; host; host = host->h_next) | 370 | hlist_for_each_entry(host, pos, chain, h_hash) |
363 | host->h_expires = jiffies - 1; | 371 | host->h_expires = jiffies - 1; |
364 | } | 372 | } |
365 | 373 | ||
@@ -371,8 +379,8 @@ nlm_shutdown_hosts(void) | |||
371 | if (nrhosts) { | 379 | if (nrhosts) { |
372 | printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); | 380 | printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); |
373 | dprintk("lockd: %d hosts left:\n", nrhosts); | 381 | dprintk("lockd: %d hosts left:\n", nrhosts); |
374 | for (i = 0; i < NLM_HOST_NRHASH; i++) { | 382 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { |
375 | for (host = nlm_hosts[i]; host; host = host->h_next) { | 383 | hlist_for_each_entry(host, pos, chain, h_hash) { |
376 | dprintk(" %s (cnt %d use %d exp %ld)\n", | 384 | dprintk(" %s (cnt %d use %d exp %ld)\n", |
377 | host->h_name, atomic_read(&host->h_count), | 385 | host->h_name, atomic_read(&host->h_count), |
378 | host->h_inuse, host->h_expires); | 386 | host->h_inuse, host->h_expires); |
@@ -389,32 +397,31 @@ nlm_shutdown_hosts(void) | |||
389 | static void | 397 | static void |
390 | nlm_gc_hosts(void) | 398 | nlm_gc_hosts(void) |
391 | { | 399 | { |
392 | struct nlm_host **q, *host; | 400 | struct hlist_head *chain; |
401 | struct hlist_node *pos, *next; | ||
402 | struct nlm_host *host; | ||
393 | struct rpc_clnt *clnt; | 403 | struct rpc_clnt *clnt; |
394 | int i; | ||
395 | 404 | ||
396 | dprintk("lockd: host garbage collection\n"); | 405 | dprintk("lockd: host garbage collection\n"); |
397 | for (i = 0; i < NLM_HOST_NRHASH; i++) { | 406 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { |
398 | for (host = nlm_hosts[i]; host; host = host->h_next) | 407 | hlist_for_each_entry(host, pos, chain, h_hash) |
399 | host->h_inuse = 0; | 408 | host->h_inuse = 0; |
400 | } | 409 | } |
401 | 410 | ||
402 | /* Mark all hosts that hold locks, blocks or shares */ | 411 | /* Mark all hosts that hold locks, blocks or shares */ |
403 | nlmsvc_mark_resources(); | 412 | nlmsvc_mark_resources(); |
404 | 413 | ||
405 | for (i = 0; i < NLM_HOST_NRHASH; i++) { | 414 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { |
406 | q = &nlm_hosts[i]; | 415 | hlist_for_each_entry_safe(host, pos, next, chain, h_hash) { |
407 | while ((host = *q) != NULL) { | ||
408 | if (atomic_read(&host->h_count) || host->h_inuse | 416 | if (atomic_read(&host->h_count) || host->h_inuse |
409 | || time_before(jiffies, host->h_expires)) { | 417 | || time_before(jiffies, host->h_expires)) { |
410 | dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n", | 418 | dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n", |
411 | host->h_name, atomic_read(&host->h_count), | 419 | host->h_name, atomic_read(&host->h_count), |
412 | host->h_inuse, host->h_expires); | 420 | host->h_inuse, host->h_expires); |
413 | q = &host->h_next; | ||
414 | continue; | 421 | continue; |
415 | } | 422 | } |
416 | dprintk("lockd: delete host %s\n", host->h_name); | 423 | dprintk("lockd: delete host %s\n", host->h_name); |
417 | *q = host->h_next; | 424 | hlist_del_init(&host->h_hash); |
418 | 425 | ||
419 | /* | 426 | /* |
420 | * Unmonitor unless host was invalidated (i.e. lockd restarted) | 427 | * Unmonitor unless host was invalidated (i.e. lockd restarted) |