aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/lockspace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dlm/lockspace.c')
-rw-r--r--fs/dlm/lockspace.c107
1 files changed, 70 insertions, 37 deletions
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 499e16759e96..56eae4e4a954 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -2,7 +2,7 @@
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
5** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. 5** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
6** 6**
7** This copyrighted material is made available to anyone wishing to use, 7** This copyrighted material is made available to anyone wishing to use,
8** modify, copy, or redistribute it subject to the terms and conditions 8** modify, copy, or redistribute it subject to the terms and conditions
@@ -23,6 +23,7 @@
23#include "lock.h" 23#include "lock.h"
24#include "recover.h" 24#include "recover.h"
25#include "requestqueue.h" 25#include "requestqueue.h"
26#include "user.h"
26 27
27static int ls_count; 28static int ls_count;
28static struct mutex ls_lock; 29static struct mutex ls_lock;
@@ -246,23 +247,6 @@ static void dlm_scand_stop(void)
246 kthread_stop(scand_task); 247 kthread_stop(scand_task);
247} 248}
248 249
249static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen)
250{
251 struct dlm_ls *ls;
252
253 spin_lock(&lslist_lock);
254
255 list_for_each_entry(ls, &lslist, ls_list) {
256 if (ls->ls_namelen == namelen &&
257 memcmp(ls->ls_name, name, namelen) == 0)
258 goto out;
259 }
260 ls = NULL;
261 out:
262 spin_unlock(&lslist_lock);
263 return ls;
264}
265
266struct dlm_ls *dlm_find_lockspace_global(uint32_t id) 250struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
267{ 251{
268 struct dlm_ls *ls; 252 struct dlm_ls *ls;
@@ -327,6 +311,7 @@ static void remove_lockspace(struct dlm_ls *ls)
327 for (;;) { 311 for (;;) {
328 spin_lock(&lslist_lock); 312 spin_lock(&lslist_lock);
329 if (ls->ls_count == 0) { 313 if (ls->ls_count == 0) {
314 WARN_ON(ls->ls_create_count != 0);
330 list_del(&ls->ls_list); 315 list_del(&ls->ls_list);
331 spin_unlock(&lslist_lock); 316 spin_unlock(&lslist_lock);
332 return; 317 return;
@@ -381,7 +366,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
381 uint32_t flags, int lvblen) 366 uint32_t flags, int lvblen)
382{ 367{
383 struct dlm_ls *ls; 368 struct dlm_ls *ls;
384 int i, size, error = -ENOMEM; 369 int i, size, error;
385 int do_unreg = 0; 370 int do_unreg = 0;
386 371
387 if (namelen > DLM_LOCKSPACE_LEN) 372 if (namelen > DLM_LOCKSPACE_LEN)
@@ -393,12 +378,32 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
393 if (!try_module_get(THIS_MODULE)) 378 if (!try_module_get(THIS_MODULE))
394 return -EINVAL; 379 return -EINVAL;
395 380
396 ls = dlm_find_lockspace_name(name, namelen); 381 error = 0;
397 if (ls) { 382
398 *lockspace = ls; 383 spin_lock(&lslist_lock);
384 list_for_each_entry(ls, &lslist, ls_list) {
385 WARN_ON(ls->ls_create_count <= 0);
386 if (ls->ls_namelen != namelen)
387 continue;
388 if (memcmp(ls->ls_name, name, namelen))
389 continue;
390 if (flags & DLM_LSFL_NEWEXCL) {
391 error = -EEXIST;
392 break;
393 }
394 ls->ls_create_count++;
399 module_put(THIS_MODULE); 395 module_put(THIS_MODULE);
400 return -EEXIST; 396 error = 1; /* not an error, return 0 */
397 break;
401 } 398 }
399 spin_unlock(&lslist_lock);
400
401 if (error < 0)
402 goto out;
403 if (error)
404 goto ret_zero;
405
406 error = -ENOMEM;
402 407
403 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL); 408 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
404 if (!ls) 409 if (!ls)
@@ -418,8 +423,9 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
418 ls->ls_allocation = GFP_KERNEL; 423 ls->ls_allocation = GFP_KERNEL;
419 424
420 /* ls_exflags are forced to match among nodes, and we don't 425 /* ls_exflags are forced to match among nodes, and we don't
421 need to require all nodes to have TIMEWARN or FS set */ 426 need to require all nodes to have some flags set */
422 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS)); 427 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
428 DLM_LSFL_NEWEXCL));
423 429
424 size = dlm_config.ci_rsbtbl_size; 430 size = dlm_config.ci_rsbtbl_size;
425 ls->ls_rsbtbl_size = size; 431 ls->ls_rsbtbl_size = size;
@@ -510,6 +516,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
510 down_write(&ls->ls_in_recovery); 516 down_write(&ls->ls_in_recovery);
511 517
512 spin_lock(&lslist_lock); 518 spin_lock(&lslist_lock);
519 ls->ls_create_count = 1;
513 list_add(&ls->ls_list, &lslist); 520 list_add(&ls->ls_list, &lslist);
514 spin_unlock(&lslist_lock); 521 spin_unlock(&lslist_lock);
515 522
@@ -548,7 +555,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
548 dlm_create_debug_file(ls); 555 dlm_create_debug_file(ls);
549 556
550 log_debug(ls, "join complete"); 557 log_debug(ls, "join complete");
551 558 ret_zero:
552 *lockspace = ls; 559 *lockspace = ls;
553 return 0; 560 return 0;
554 561
@@ -635,11 +642,32 @@ static int release_lockspace(struct dlm_ls *ls, int force)
635 struct dlm_lkb *lkb; 642 struct dlm_lkb *lkb;
636 struct dlm_rsb *rsb; 643 struct dlm_rsb *rsb;
637 struct list_head *head; 644 struct list_head *head;
638 int i; 645 int i, busy, rv;
639 int busy = lockspace_busy(ls); 646
647 busy = lockspace_busy(ls);
648
649 spin_lock(&lslist_lock);
650 if (ls->ls_create_count == 1) {
651 if (busy > force)
652 rv = -EBUSY;
653 else {
654 /* remove_lockspace takes ls off lslist */
655 ls->ls_create_count = 0;
656 rv = 0;
657 }
658 } else if (ls->ls_create_count > 1) {
659 rv = --ls->ls_create_count;
660 } else {
661 rv = -EINVAL;
662 }
663 spin_unlock(&lslist_lock);
664
665 if (rv) {
666 log_debug(ls, "release_lockspace no remove %d", rv);
667 return rv;
668 }
640 669
641 if (busy > force) 670 dlm_device_deregister(ls);
642 return -EBUSY;
643 671
644 if (force < 3) 672 if (force < 3)
645 do_uevent(ls, 0); 673 do_uevent(ls, 0);
@@ -720,15 +748,10 @@ static int release_lockspace(struct dlm_ls *ls, int force)
720 dlm_clear_members(ls); 748 dlm_clear_members(ls);
721 dlm_clear_members_gone(ls); 749 dlm_clear_members_gone(ls);
722 kfree(ls->ls_node_array); 750 kfree(ls->ls_node_array);
751 log_debug(ls, "release_lockspace final free");
723 kobject_put(&ls->ls_kobj); 752 kobject_put(&ls->ls_kobj);
724 /* The ls structure will be freed when the kobject is done with */ 753 /* The ls structure will be freed when the kobject is done with */
725 754
726 mutex_lock(&ls_lock);
727 ls_count--;
728 if (!ls_count)
729 threads_stop();
730 mutex_unlock(&ls_lock);
731
732 module_put(THIS_MODULE); 755 module_put(THIS_MODULE);
733 return 0; 756 return 0;
734} 757}
@@ -750,11 +773,21 @@ static int release_lockspace(struct dlm_ls *ls, int force)
750int dlm_release_lockspace(void *lockspace, int force) 773int dlm_release_lockspace(void *lockspace, int force)
751{ 774{
752 struct dlm_ls *ls; 775 struct dlm_ls *ls;
776 int error;
753 777
754 ls = dlm_find_lockspace_local(lockspace); 778 ls = dlm_find_lockspace_local(lockspace);
755 if (!ls) 779 if (!ls)
756 return -EINVAL; 780 return -EINVAL;
757 dlm_put_lockspace(ls); 781 dlm_put_lockspace(ls);
758 return release_lockspace(ls, force); 782
783 mutex_lock(&ls_lock);
784 error = release_lockspace(ls, force);
785 if (!error)
786 ls_count--;
787 else if (!ls_count)
788 threads_stop();
789 mutex_unlock(&ls_lock);
790
791 return error;
759} 792}
760 793