diff options
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r-- | fs/lockd/host.c | 73 |
1 files changed, 36 insertions, 37 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index f1ef49fff118..c7854791898f 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -19,12 +19,11 @@ | |||
19 | 19 | ||
20 | 20 | ||
21 | #define NLMDBG_FACILITY NLMDBG_HOSTCACHE | 21 | #define NLMDBG_FACILITY NLMDBG_HOSTCACHE |
22 | #define NLM_HOST_MAX 64 | ||
23 | #define NLM_HOST_NRHASH 32 | 22 | #define NLM_HOST_NRHASH 32 |
24 | #define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1)) | 23 | #define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1)) |
25 | #define NLM_HOST_REBIND (60 * HZ) | 24 | #define NLM_HOST_REBIND (60 * HZ) |
26 | #define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ) | 25 | #define NLM_HOST_EXPIRE (300 * HZ) |
27 | #define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ) | 26 | #define NLM_HOST_COLLECT (120 * HZ) |
28 | 27 | ||
29 | static struct hlist_head nlm_hosts[NLM_HOST_NRHASH]; | 28 | static struct hlist_head nlm_hosts[NLM_HOST_NRHASH]; |
30 | static unsigned long next_gc; | 29 | static unsigned long next_gc; |
@@ -142,9 +141,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin, | |||
142 | INIT_LIST_HEAD(&host->h_granted); | 141 | INIT_LIST_HEAD(&host->h_granted); |
143 | INIT_LIST_HEAD(&host->h_reclaim); | 142 | INIT_LIST_HEAD(&host->h_reclaim); |
144 | 143 | ||
145 | if (++nrhosts > NLM_HOST_MAX) | 144 | nrhosts++; |
146 | next_gc = 0; | ||
147 | |||
148 | out: | 145 | out: |
149 | mutex_unlock(&nlm_host_mutex); | 146 | mutex_unlock(&nlm_host_mutex); |
150 | return host; | 147 | return host; |
@@ -460,7 +457,7 @@ nlm_gc_hosts(void) | |||
460 | * Manage NSM handles | 457 | * Manage NSM handles |
461 | */ | 458 | */ |
462 | static LIST_HEAD(nsm_handles); | 459 | static LIST_HEAD(nsm_handles); |
463 | static DEFINE_MUTEX(nsm_mutex); | 460 | static DEFINE_SPINLOCK(nsm_lock); |
464 | 461 | ||
465 | static struct nsm_handle * | 462 | static struct nsm_handle * |
466 | __nsm_find(const struct sockaddr_in *sin, | 463 | __nsm_find(const struct sockaddr_in *sin, |
@@ -468,7 +465,7 @@ __nsm_find(const struct sockaddr_in *sin, | |||
468 | int create) | 465 | int create) |
469 | { | 466 | { |
470 | struct nsm_handle *nsm = NULL; | 467 | struct nsm_handle *nsm = NULL; |
471 | struct list_head *pos; | 468 | struct nsm_handle *pos; |
472 | 469 | ||
473 | if (!sin) | 470 | if (!sin) |
474 | return NULL; | 471 | return NULL; |
@@ -482,38 +479,43 @@ __nsm_find(const struct sockaddr_in *sin, | |||
482 | return NULL; | 479 | return NULL; |
483 | } | 480 | } |
484 | 481 | ||
485 | mutex_lock(&nsm_mutex); | 482 | retry: |
486 | list_for_each(pos, &nsm_handles) { | 483 | spin_lock(&nsm_lock); |
487 | nsm = list_entry(pos, struct nsm_handle, sm_link); | 484 | list_for_each_entry(pos, &nsm_handles, sm_link) { |
488 | 485 | ||
489 | if (hostname && nsm_use_hostnames) { | 486 | if (hostname && nsm_use_hostnames) { |
490 | if (strlen(nsm->sm_name) != hostname_len | 487 | if (strlen(pos->sm_name) != hostname_len |
491 | || memcmp(nsm->sm_name, hostname, hostname_len)) | 488 | || memcmp(pos->sm_name, hostname, hostname_len)) |
492 | continue; | 489 | continue; |
493 | } else if (!nlm_cmp_addr(&nsm->sm_addr, sin)) | 490 | } else if (!nlm_cmp_addr(&pos->sm_addr, sin)) |
494 | continue; | 491 | continue; |
495 | atomic_inc(&nsm->sm_count); | 492 | atomic_inc(&pos->sm_count); |
496 | goto out; | 493 | kfree(nsm); |
494 | nsm = pos; | ||
495 | goto found; | ||
497 | } | 496 | } |
498 | 497 | if (nsm) { | |
499 | if (!create) { | 498 | list_add(&nsm->sm_link, &nsm_handles); |
500 | nsm = NULL; | 499 | goto found; |
501 | goto out; | ||
502 | } | 500 | } |
501 | spin_unlock(&nsm_lock); | ||
502 | |||
503 | if (!create) | ||
504 | return NULL; | ||
503 | 505 | ||
504 | nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL); | 506 | nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL); |
505 | if (nsm != NULL) { | 507 | if (nsm == NULL) |
506 | nsm->sm_addr = *sin; | 508 | return NULL; |
507 | nsm->sm_name = (char *) (nsm + 1); | ||
508 | memcpy(nsm->sm_name, hostname, hostname_len); | ||
509 | nsm->sm_name[hostname_len] = '\0'; | ||
510 | atomic_set(&nsm->sm_count, 1); | ||
511 | 509 | ||
512 | list_add(&nsm->sm_link, &nsm_handles); | 510 | nsm->sm_addr = *sin; |
513 | } | 511 | nsm->sm_name = (char *) (nsm + 1); |
512 | memcpy(nsm->sm_name, hostname, hostname_len); | ||
513 | nsm->sm_name[hostname_len] = '\0'; | ||
514 | atomic_set(&nsm->sm_count, 1); | ||
515 | goto retry; | ||
514 | 516 | ||
515 | out: | 517 | found: |
516 | mutex_unlock(&nsm_mutex); | 518 | spin_unlock(&nsm_lock); |
517 | return nsm; | 519 | return nsm; |
518 | } | 520 | } |
519 | 521 | ||
@@ -532,12 +534,9 @@ nsm_release(struct nsm_handle *nsm) | |||
532 | { | 534 | { |
533 | if (!nsm) | 535 | if (!nsm) |
534 | return; | 536 | return; |
535 | if (atomic_dec_and_test(&nsm->sm_count)) { | 537 | if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) { |
536 | mutex_lock(&nsm_mutex); | 538 | list_del(&nsm->sm_link); |
537 | if (atomic_read(&nsm->sm_count) == 0) { | 539 | spin_unlock(&nsm_lock); |
538 | list_del(&nsm->sm_link); | 540 | kfree(nsm); |
539 | kfree(nsm); | ||
540 | } | ||
541 | mutex_unlock(&nsm_mutex); | ||
542 | } | 541 | } |
543 | } | 542 | } |