aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/host.c71
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
30static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH]; 30static struct hlist_head nlm_hosts[NLM_HOST_NRHASH];
31static unsigned long next_gc; 31static unsigned long next_gc;
32static int nrhosts; 32static int nrhosts;
33static DEFINE_MUTEX(nlm_host_mutex); 33static 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:
164struct nlm_host * 167struct nlm_host *
165nlm_find_client(void) 168nlm_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 */
317again: mutex_lock(&nlm_host_mutex); 324again: 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);
350void 357void
351nlm_shutdown_hosts(void) 358nlm_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)
389static void 397static void
390nlm_gc_hosts(void) 398nlm_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)