aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/host.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index de0ffb6106c4..c7854791898f 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -457,7 +457,7 @@ nlm_gc_hosts(void)
457 * Manage NSM handles 457 * Manage NSM handles
458 */ 458 */
459static LIST_HEAD(nsm_handles); 459static LIST_HEAD(nsm_handles);
460static DEFINE_MUTEX(nsm_mutex); 460static DEFINE_SPINLOCK(nsm_lock);
461 461
462static struct nsm_handle * 462static struct nsm_handle *
463__nsm_find(const struct sockaddr_in *sin, 463__nsm_find(const struct sockaddr_in *sin,
@@ -479,7 +479,8 @@ __nsm_find(const struct sockaddr_in *sin,
479 return NULL; 479 return NULL;
480 } 480 }
481 481
482 mutex_lock(&nsm_mutex); 482retry:
483 spin_lock(&nsm_lock);
483 list_for_each_entry(pos, &nsm_handles, sm_link) { 484 list_for_each_entry(pos, &nsm_handles, sm_link) {
484 485
485 if (hostname && nsm_use_hostnames) { 486 if (hostname && nsm_use_hostnames) {
@@ -489,28 +490,32 @@ __nsm_find(const struct sockaddr_in *sin,
489 } else if (!nlm_cmp_addr(&pos->sm_addr, sin)) 490 } else if (!nlm_cmp_addr(&pos->sm_addr, sin))
490 continue; 491 continue;
491 atomic_inc(&pos->sm_count); 492 atomic_inc(&pos->sm_count);
493 kfree(nsm);
492 nsm = pos; 494 nsm = pos;
493 goto out; 495 goto found;
494 } 496 }
495 497 if (nsm) {
496 if (!create) { 498 list_add(&nsm->sm_link, &nsm_handles);
497 nsm = NULL; 499 goto found;
498 goto out;
499 } 500 }
501 spin_unlock(&nsm_lock);
502
503 if (!create)
504 return NULL;
500 505
501 nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL); 506 nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
502 if (nsm == NULL) 507 if (nsm == NULL)
503 goto out; 508 return NULL;
509
504 nsm->sm_addr = *sin; 510 nsm->sm_addr = *sin;
505 nsm->sm_name = (char *) (nsm + 1); 511 nsm->sm_name = (char *) (nsm + 1);
506 memcpy(nsm->sm_name, hostname, hostname_len); 512 memcpy(nsm->sm_name, hostname, hostname_len);
507 nsm->sm_name[hostname_len] = '\0'; 513 nsm->sm_name[hostname_len] = '\0';
508 atomic_set(&nsm->sm_count, 1); 514 atomic_set(&nsm->sm_count, 1);
515 goto retry;
509 516
510 list_add(&nsm->sm_link, &nsm_handles); 517found:
511 518 spin_unlock(&nsm_lock);
512out:
513 mutex_unlock(&nsm_mutex);
514 return nsm; 519 return nsm;
515} 520}
516 521
@@ -529,10 +534,9 @@ nsm_release(struct nsm_handle *nsm)
529{ 534{
530 if (!nsm) 535 if (!nsm)
531 return; 536 return;
532 mutex_lock(&nsm_mutex); 537 if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
533 if (atomic_dec_and_test(&nsm->sm_count)) {
534 list_del(&nsm->sm_link); 538 list_del(&nsm->sm_link);
539 spin_unlock(&nsm_lock);
535 kfree(nsm); 540 kfree(nsm);
536 } 541 }
537 mutex_unlock(&nsm_mutex);
538} 542}