aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-10 14:13:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-10 14:13:55 -0400
commit13dd7f876dffb44088c5435c3df1986e33cff960 (patch)
treec9043429452663661dc888e1cbafa87bd2a62f44
parentb0af205afb111e17ac8db64c3b9c4f2c332de92a (diff)
parent27eccf46491e1f77f9af9bbe0778122ce6882890 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm: dlm: choose better identifiers dlm: remove bkl dlm: fix address compare dlm: fix locking of lockspace list in dlm_scand dlm: detect available userspace daemon dlm: allow multiple lockspace creates
-rw-r--r--fs/dlm/config.c77
-rw-r--r--fs/dlm/dlm_internal.h7
-rw-r--r--fs/dlm/lockspace.c158
-rw-r--r--fs/dlm/lockspace.h1
-rw-r--r--fs/dlm/user.c124
-rw-r--r--fs/dlm/user.h4
-rw-r--r--fs/gfs2/locking/dlm/mount.c3
-rw-r--r--include/linux/dlm.h5
-rw-r--r--include/linux/dlm_device.h2
9 files changed, 281 insertions, 100 deletions
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 89d2fb7b991a..fd9859f92fad 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -14,6 +14,9 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/configfs.h> 16#include <linux/configfs.h>
17#include <linux/in.h>
18#include <linux/in6.h>
19#include <net/ipv6.h>
17#include <net/sock.h> 20#include <net/sock.h>
18 21
19#include "config.h" 22#include "config.h"
@@ -377,24 +380,24 @@ static struct config_item_type node_type = {
377 .ct_owner = THIS_MODULE, 380 .ct_owner = THIS_MODULE,
378}; 381};
379 382
380static struct dlm_cluster *to_cluster(struct config_item *i) 383static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
381{ 384{
382 return i ? container_of(to_config_group(i), struct dlm_cluster, group) : 385 return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
383 NULL; 386 NULL;
384} 387}
385 388
386static struct dlm_space *to_space(struct config_item *i) 389static struct dlm_space *config_item_to_space(struct config_item *i)
387{ 390{
388 return i ? container_of(to_config_group(i), struct dlm_space, group) : 391 return i ? container_of(to_config_group(i), struct dlm_space, group) :
389 NULL; 392 NULL;
390} 393}
391 394
392static struct dlm_comm *to_comm(struct config_item *i) 395static struct dlm_comm *config_item_to_comm(struct config_item *i)
393{ 396{
394 return i ? container_of(i, struct dlm_comm, item) : NULL; 397 return i ? container_of(i, struct dlm_comm, item) : NULL;
395} 398}
396 399
397static struct dlm_node *to_node(struct config_item *i) 400static struct dlm_node *config_item_to_node(struct config_item *i)
398{ 401{
399 return i ? container_of(i, struct dlm_node, item) : NULL; 402 return i ? container_of(i, struct dlm_node, item) : NULL;
400} 403}
@@ -450,7 +453,7 @@ static struct config_group *make_cluster(struct config_group *g,
450 453
451static void drop_cluster(struct config_group *g, struct config_item *i) 454static void drop_cluster(struct config_group *g, struct config_item *i)
452{ 455{
453 struct dlm_cluster *cl = to_cluster(i); 456 struct dlm_cluster *cl = config_item_to_cluster(i);
454 struct config_item *tmp; 457 struct config_item *tmp;
455 int j; 458 int j;
456 459
@@ -468,7 +471,7 @@ static void drop_cluster(struct config_group *g, struct config_item *i)
468 471
469static void release_cluster(struct config_item *i) 472static void release_cluster(struct config_item *i)
470{ 473{
471 struct dlm_cluster *cl = to_cluster(i); 474 struct dlm_cluster *cl = config_item_to_cluster(i);
472 kfree(cl->group.default_groups); 475 kfree(cl->group.default_groups);
473 kfree(cl); 476 kfree(cl);
474} 477}
@@ -507,7 +510,7 @@ static struct config_group *make_space(struct config_group *g, const char *name)
507 510
508static void drop_space(struct config_group *g, struct config_item *i) 511static void drop_space(struct config_group *g, struct config_item *i)
509{ 512{
510 struct dlm_space *sp = to_space(i); 513 struct dlm_space *sp = config_item_to_space(i);
511 struct config_item *tmp; 514 struct config_item *tmp;
512 int j; 515 int j;
513 516
@@ -524,7 +527,7 @@ static void drop_space(struct config_group *g, struct config_item *i)
524 527
525static void release_space(struct config_item *i) 528static void release_space(struct config_item *i)
526{ 529{
527 struct dlm_space *sp = to_space(i); 530 struct dlm_space *sp = config_item_to_space(i);
528 kfree(sp->group.default_groups); 531 kfree(sp->group.default_groups);
529 kfree(sp); 532 kfree(sp);
530} 533}
@@ -546,7 +549,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name)
546 549
547static void drop_comm(struct config_group *g, struct config_item *i) 550static void drop_comm(struct config_group *g, struct config_item *i)
548{ 551{
549 struct dlm_comm *cm = to_comm(i); 552 struct dlm_comm *cm = config_item_to_comm(i);
550 if (local_comm == cm) 553 if (local_comm == cm)
551 local_comm = NULL; 554 local_comm = NULL;
552 dlm_lowcomms_close(cm->nodeid); 555 dlm_lowcomms_close(cm->nodeid);
@@ -557,13 +560,13 @@ static void drop_comm(struct config_group *g, struct config_item *i)
557 560
558static void release_comm(struct config_item *i) 561static void release_comm(struct config_item *i)
559{ 562{
560 struct dlm_comm *cm = to_comm(i); 563 struct dlm_comm *cm = config_item_to_comm(i);
561 kfree(cm); 564 kfree(cm);
562} 565}
563 566
564static struct config_item *make_node(struct config_group *g, const char *name) 567static struct config_item *make_node(struct config_group *g, const char *name)
565{ 568{
566 struct dlm_space *sp = to_space(g->cg_item.ci_parent); 569 struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
567 struct dlm_node *nd; 570 struct dlm_node *nd;
568 571
569 nd = kzalloc(sizeof(struct dlm_node), GFP_KERNEL); 572 nd = kzalloc(sizeof(struct dlm_node), GFP_KERNEL);
@@ -585,8 +588,8 @@ static struct config_item *make_node(struct config_group *g, const char *name)
585 588
586static void drop_node(struct config_group *g, struct config_item *i) 589static void drop_node(struct config_group *g, struct config_item *i)
587{ 590{
588 struct dlm_space *sp = to_space(g->cg_item.ci_parent); 591 struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
589 struct dlm_node *nd = to_node(i); 592 struct dlm_node *nd = config_item_to_node(i);
590 593
591 mutex_lock(&sp->members_lock); 594 mutex_lock(&sp->members_lock);
592 list_del(&nd->list); 595 list_del(&nd->list);
@@ -598,7 +601,7 @@ static void drop_node(struct config_group *g, struct config_item *i)
598 601
599static void release_node(struct config_item *i) 602static void release_node(struct config_item *i)
600{ 603{
601 struct dlm_node *nd = to_node(i); 604 struct dlm_node *nd = config_item_to_node(i);
602 kfree(nd); 605 kfree(nd);
603} 606}
604 607
@@ -632,7 +635,7 @@ void dlm_config_exit(void)
632static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a, 635static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
633 char *buf) 636 char *buf)
634{ 637{
635 struct dlm_cluster *cl = to_cluster(i); 638 struct dlm_cluster *cl = config_item_to_cluster(i);
636 struct cluster_attribute *cla = 639 struct cluster_attribute *cla =
637 container_of(a, struct cluster_attribute, attr); 640 container_of(a, struct cluster_attribute, attr);
638 return cla->show ? cla->show(cl, buf) : 0; 641 return cla->show ? cla->show(cl, buf) : 0;
@@ -642,7 +645,7 @@ static ssize_t store_cluster(struct config_item *i,
642 struct configfs_attribute *a, 645 struct configfs_attribute *a,
643 const char *buf, size_t len) 646 const char *buf, size_t len)
644{ 647{
645 struct dlm_cluster *cl = to_cluster(i); 648 struct dlm_cluster *cl = config_item_to_cluster(i);
646 struct cluster_attribute *cla = 649 struct cluster_attribute *cla =
647 container_of(a, struct cluster_attribute, attr); 650 container_of(a, struct cluster_attribute, attr);
648 return cla->store ? cla->store(cl, buf, len) : -EINVAL; 651 return cla->store ? cla->store(cl, buf, len) : -EINVAL;
@@ -651,7 +654,7 @@ static ssize_t store_cluster(struct config_item *i,
651static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, 654static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
652 char *buf) 655 char *buf)
653{ 656{
654 struct dlm_comm *cm = to_comm(i); 657 struct dlm_comm *cm = config_item_to_comm(i);
655 struct comm_attribute *cma = 658 struct comm_attribute *cma =
656 container_of(a, struct comm_attribute, attr); 659 container_of(a, struct comm_attribute, attr);
657 return cma->show ? cma->show(cm, buf) : 0; 660 return cma->show ? cma->show(cm, buf) : 0;
@@ -660,7 +663,7 @@ static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
660static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, 663static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
661 const char *buf, size_t len) 664 const char *buf, size_t len)
662{ 665{
663 struct dlm_comm *cm = to_comm(i); 666 struct dlm_comm *cm = config_item_to_comm(i);
664 struct comm_attribute *cma = 667 struct comm_attribute *cma =
665 container_of(a, struct comm_attribute, attr); 668 container_of(a, struct comm_attribute, attr);
666 return cma->store ? cma->store(cm, buf, len) : -EINVAL; 669 return cma->store ? cma->store(cm, buf, len) : -EINVAL;
@@ -714,7 +717,7 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
714static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, 717static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
715 char *buf) 718 char *buf)
716{ 719{
717 struct dlm_node *nd = to_node(i); 720 struct dlm_node *nd = config_item_to_node(i);
718 struct node_attribute *nda = 721 struct node_attribute *nda =
719 container_of(a, struct node_attribute, attr); 722 container_of(a, struct node_attribute, attr);
720 return nda->show ? nda->show(nd, buf) : 0; 723 return nda->show ? nda->show(nd, buf) : 0;
@@ -723,7 +726,7 @@ static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
723static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, 726static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
724 const char *buf, size_t len) 727 const char *buf, size_t len)
725{ 728{
726 struct dlm_node *nd = to_node(i); 729 struct dlm_node *nd = config_item_to_node(i);
727 struct node_attribute *nda = 730 struct node_attribute *nda =
728 container_of(a, struct node_attribute, attr); 731 container_of(a, struct node_attribute, attr);
729 return nda->store ? nda->store(nd, buf, len) : -EINVAL; 732 return nda->store ? nda->store(nd, buf, len) : -EINVAL;
@@ -768,7 +771,7 @@ static struct dlm_space *get_space(char *name)
768 i = config_group_find_item(space_list, name); 771 i = config_group_find_item(space_list, name);
769 mutex_unlock(&space_list->cg_subsys->su_mutex); 772 mutex_unlock(&space_list->cg_subsys->su_mutex);
770 773
771 return to_space(i); 774 return config_item_to_space(i);
772} 775}
773 776
774static void put_space(struct dlm_space *sp) 777static void put_space(struct dlm_space *sp)
@@ -776,6 +779,33 @@ static void put_space(struct dlm_space *sp)
776 config_item_put(&sp->group.cg_item); 779 config_item_put(&sp->group.cg_item);
777} 780}
778 781
782static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y)
783{
784 switch (x->ss_family) {
785 case AF_INET: {
786 struct sockaddr_in *sinx = (struct sockaddr_in *)x;
787 struct sockaddr_in *siny = (struct sockaddr_in *)y;
788 if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
789 return 0;
790 if (sinx->sin_port != siny->sin_port)
791 return 0;
792 break;
793 }
794 case AF_INET6: {
795 struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
796 struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
797 if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
798 return 0;
799 if (sinx->sin6_port != siny->sin6_port)
800 return 0;
801 break;
802 }
803 default:
804 return 0;
805 }
806 return 1;
807}
808
779static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) 809static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
780{ 810{
781 struct config_item *i; 811 struct config_item *i;
@@ -788,7 +818,7 @@ static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
788 mutex_lock(&clusters_root.subsys.su_mutex); 818 mutex_lock(&clusters_root.subsys.su_mutex);
789 819
790 list_for_each_entry(i, &comm_list->cg_children, ci_entry) { 820 list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
791 cm = to_comm(i); 821 cm = config_item_to_comm(i);
792 822
793 if (nodeid) { 823 if (nodeid) {
794 if (cm->nodeid != nodeid) 824 if (cm->nodeid != nodeid)
@@ -797,8 +827,7 @@ static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
797 config_item_get(i); 827 config_item_get(i);
798 break; 828 break;
799 } else { 829 } else {
800 if (!cm->addr_count || 830 if (!cm->addr_count || !addr_compare(cm->addr[0], addr))
801 memcmp(cm->addr[0], addr, sizeof(*addr)))
802 continue; 831 continue;
803 found = 1; 832 found = 1;
804 config_item_get(i); 833 config_item_get(i);
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 5a7ac33b629c..868e4c9ef127 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -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
@@ -441,8 +441,11 @@ struct dlm_ls {
441 uint32_t ls_global_id; /* global unique lockspace ID */ 441 uint32_t ls_global_id; /* global unique lockspace ID */
442 uint32_t ls_exflags; 442 uint32_t ls_exflags;
443 int ls_lvblen; 443 int ls_lvblen;
444 int ls_count; /* reference count */ 444 int ls_count; /* refcount of processes in
445 the dlm using this ls */
446 int ls_create_count; /* create/release refcount */
445 unsigned long ls_flags; /* LSFL_ */ 447 unsigned long ls_flags; /* LSFL_ */
448 unsigned long ls_scan_time;
446 struct kobject ls_kobj; 449 struct kobject ls_kobj;
447 450
448 struct dlm_rsbtable *ls_rsbtbl; 451 struct dlm_rsbtable *ls_rsbtbl;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 499e16759e96..d910501de6d2 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;
@@ -211,19 +212,41 @@ void dlm_lockspace_exit(void)
211 kset_unregister(dlm_kset); 212 kset_unregister(dlm_kset);
212} 213}
213 214
215static struct dlm_ls *find_ls_to_scan(void)
216{
217 struct dlm_ls *ls;
218
219 spin_lock(&lslist_lock);
220 list_for_each_entry(ls, &lslist, ls_list) {
221 if (time_after_eq(jiffies, ls->ls_scan_time +
222 dlm_config.ci_scan_secs * HZ)) {
223 spin_unlock(&lslist_lock);
224 return ls;
225 }
226 }
227 spin_unlock(&lslist_lock);
228 return NULL;
229}
230
214static int dlm_scand(void *data) 231static int dlm_scand(void *data)
215{ 232{
216 struct dlm_ls *ls; 233 struct dlm_ls *ls;
234 int timeout_jiffies = dlm_config.ci_scan_secs * HZ;
217 235
218 while (!kthread_should_stop()) { 236 while (!kthread_should_stop()) {
219 list_for_each_entry(ls, &lslist, ls_list) { 237 ls = find_ls_to_scan();
238 if (ls) {
220 if (dlm_lock_recovery_try(ls)) { 239 if (dlm_lock_recovery_try(ls)) {
240 ls->ls_scan_time = jiffies;
221 dlm_scan_rsbs(ls); 241 dlm_scan_rsbs(ls);
222 dlm_scan_timeout(ls); 242 dlm_scan_timeout(ls);
223 dlm_unlock_recovery(ls); 243 dlm_unlock_recovery(ls);
244 } else {
245 ls->ls_scan_time += HZ;
224 } 246 }
247 } else {
248 schedule_timeout_interruptible(timeout_jiffies);
225 } 249 }
226 schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
227 } 250 }
228 return 0; 251 return 0;
229} 252}
@@ -246,23 +269,6 @@ static void dlm_scand_stop(void)
246 kthread_stop(scand_task); 269 kthread_stop(scand_task);
247} 270}
248 271
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) 272struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
267{ 273{
268 struct dlm_ls *ls; 274 struct dlm_ls *ls;
@@ -327,6 +333,7 @@ static void remove_lockspace(struct dlm_ls *ls)
327 for (;;) { 333 for (;;) {
328 spin_lock(&lslist_lock); 334 spin_lock(&lslist_lock);
329 if (ls->ls_count == 0) { 335 if (ls->ls_count == 0) {
336 WARN_ON(ls->ls_create_count != 0);
330 list_del(&ls->ls_list); 337 list_del(&ls->ls_list);
331 spin_unlock(&lslist_lock); 338 spin_unlock(&lslist_lock);
332 return; 339 return;
@@ -381,7 +388,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
381 uint32_t flags, int lvblen) 388 uint32_t flags, int lvblen)
382{ 389{
383 struct dlm_ls *ls; 390 struct dlm_ls *ls;
384 int i, size, error = -ENOMEM; 391 int i, size, error;
385 int do_unreg = 0; 392 int do_unreg = 0;
386 393
387 if (namelen > DLM_LOCKSPACE_LEN) 394 if (namelen > DLM_LOCKSPACE_LEN)
@@ -393,12 +400,37 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
393 if (!try_module_get(THIS_MODULE)) 400 if (!try_module_get(THIS_MODULE))
394 return -EINVAL; 401 return -EINVAL;
395 402
396 ls = dlm_find_lockspace_name(name, namelen); 403 if (!dlm_user_daemon_available()) {
397 if (ls) { 404 module_put(THIS_MODULE);
398 *lockspace = ls; 405 return -EUNATCH;
406 }
407
408 error = 0;
409
410 spin_lock(&lslist_lock);
411 list_for_each_entry(ls, &lslist, ls_list) {
412 WARN_ON(ls->ls_create_count <= 0);
413 if (ls->ls_namelen != namelen)
414 continue;
415 if (memcmp(ls->ls_name, name, namelen))
416 continue;
417 if (flags & DLM_LSFL_NEWEXCL) {
418 error = -EEXIST;
419 break;
420 }
421 ls->ls_create_count++;
399 module_put(THIS_MODULE); 422 module_put(THIS_MODULE);
400 return -EEXIST; 423 error = 1; /* not an error, return 0 */
424 break;
401 } 425 }
426 spin_unlock(&lslist_lock);
427
428 if (error < 0)
429 goto out;
430 if (error)
431 goto ret_zero;
432
433 error = -ENOMEM;
402 434
403 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL); 435 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
404 if (!ls) 436 if (!ls)
@@ -408,6 +440,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
408 ls->ls_lvblen = lvblen; 440 ls->ls_lvblen = lvblen;
409 ls->ls_count = 0; 441 ls->ls_count = 0;
410 ls->ls_flags = 0; 442 ls->ls_flags = 0;
443 ls->ls_scan_time = jiffies;
411 444
412 if (flags & DLM_LSFL_TIMEWARN) 445 if (flags & DLM_LSFL_TIMEWARN)
413 set_bit(LSFL_TIMEWARN, &ls->ls_flags); 446 set_bit(LSFL_TIMEWARN, &ls->ls_flags);
@@ -418,8 +451,9 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
418 ls->ls_allocation = GFP_KERNEL; 451 ls->ls_allocation = GFP_KERNEL;
419 452
420 /* ls_exflags are forced to match among nodes, and we don't 453 /* ls_exflags are forced to match among nodes, and we don't
421 need to require all nodes to have TIMEWARN or FS set */ 454 need to require all nodes to have some flags set */
422 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS)); 455 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
456 DLM_LSFL_NEWEXCL));
423 457
424 size = dlm_config.ci_rsbtbl_size; 458 size = dlm_config.ci_rsbtbl_size;
425 ls->ls_rsbtbl_size = size; 459 ls->ls_rsbtbl_size = size;
@@ -510,6 +544,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
510 down_write(&ls->ls_in_recovery); 544 down_write(&ls->ls_in_recovery);
511 545
512 spin_lock(&lslist_lock); 546 spin_lock(&lslist_lock);
547 ls->ls_create_count = 1;
513 list_add(&ls->ls_list, &lslist); 548 list_add(&ls->ls_list, &lslist);
514 spin_unlock(&lslist_lock); 549 spin_unlock(&lslist_lock);
515 550
@@ -548,7 +583,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
548 dlm_create_debug_file(ls); 583 dlm_create_debug_file(ls);
549 584
550 log_debug(ls, "join complete"); 585 log_debug(ls, "join complete");
551 586 ret_zero:
552 *lockspace = ls; 587 *lockspace = ls;
553 return 0; 588 return 0;
554 589
@@ -635,13 +670,34 @@ static int release_lockspace(struct dlm_ls *ls, int force)
635 struct dlm_lkb *lkb; 670 struct dlm_lkb *lkb;
636 struct dlm_rsb *rsb; 671 struct dlm_rsb *rsb;
637 struct list_head *head; 672 struct list_head *head;
638 int i; 673 int i, busy, rv;
639 int busy = lockspace_busy(ls); 674
675 busy = lockspace_busy(ls);
676
677 spin_lock(&lslist_lock);
678 if (ls->ls_create_count == 1) {
679 if (busy > force)
680 rv = -EBUSY;
681 else {
682 /* remove_lockspace takes ls off lslist */
683 ls->ls_create_count = 0;
684 rv = 0;
685 }
686 } else if (ls->ls_create_count > 1) {
687 rv = --ls->ls_create_count;
688 } else {
689 rv = -EINVAL;
690 }
691 spin_unlock(&lslist_lock);
640 692
641 if (busy > force) 693 if (rv) {
642 return -EBUSY; 694 log_debug(ls, "release_lockspace no remove %d", rv);
695 return rv;
696 }
697
698 dlm_device_deregister(ls);
643 699
644 if (force < 3) 700 if (force < 3 && dlm_user_daemon_available())
645 do_uevent(ls, 0); 701 do_uevent(ls, 0);
646 702
647 dlm_recoverd_stop(ls); 703 dlm_recoverd_stop(ls);
@@ -720,15 +776,10 @@ static int release_lockspace(struct dlm_ls *ls, int force)
720 dlm_clear_members(ls); 776 dlm_clear_members(ls);
721 dlm_clear_members_gone(ls); 777 dlm_clear_members_gone(ls);
722 kfree(ls->ls_node_array); 778 kfree(ls->ls_node_array);
779 log_debug(ls, "release_lockspace final free");
723 kobject_put(&ls->ls_kobj); 780 kobject_put(&ls->ls_kobj);
724 /* The ls structure will be freed when the kobject is done with */ 781 /* The ls structure will be freed when the kobject is done with */
725 782
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); 783 module_put(THIS_MODULE);
733 return 0; 784 return 0;
734} 785}
@@ -750,11 +801,38 @@ static int release_lockspace(struct dlm_ls *ls, int force)
750int dlm_release_lockspace(void *lockspace, int force) 801int dlm_release_lockspace(void *lockspace, int force)
751{ 802{
752 struct dlm_ls *ls; 803 struct dlm_ls *ls;
804 int error;
753 805
754 ls = dlm_find_lockspace_local(lockspace); 806 ls = dlm_find_lockspace_local(lockspace);
755 if (!ls) 807 if (!ls)
756 return -EINVAL; 808 return -EINVAL;
757 dlm_put_lockspace(ls); 809 dlm_put_lockspace(ls);
758 return release_lockspace(ls, force); 810
811 mutex_lock(&ls_lock);
812 error = release_lockspace(ls, force);
813 if (!error)
814 ls_count--;
815 else if (!ls_count)
816 threads_stop();
817 mutex_unlock(&ls_lock);
818
819 return error;
820}
821
822void dlm_stop_lockspaces(void)
823{
824 struct dlm_ls *ls;
825
826 restart:
827 spin_lock(&lslist_lock);
828 list_for_each_entry(ls, &lslist, ls_list) {
829 if (!test_bit(LSFL_RUNNING, &ls->ls_flags))
830 continue;
831 spin_unlock(&lslist_lock);
832 log_error(ls, "no userland control daemon, stopping lockspace");
833 dlm_ls_stop(ls);
834 goto restart;
835 }
836 spin_unlock(&lslist_lock);
759} 837}
760 838
diff --git a/fs/dlm/lockspace.h b/fs/dlm/lockspace.h
index 891eabbdd021..f879f87901f8 100644
--- a/fs/dlm/lockspace.h
+++ b/fs/dlm/lockspace.h
@@ -20,6 +20,7 @@ struct dlm_ls *dlm_find_lockspace_global(uint32_t id);
20struct dlm_ls *dlm_find_lockspace_local(void *id); 20struct dlm_ls *dlm_find_lockspace_local(void *id);
21struct dlm_ls *dlm_find_lockspace_device(int minor); 21struct dlm_ls *dlm_find_lockspace_device(int minor);
22void dlm_put_lockspace(struct dlm_ls *ls); 22void dlm_put_lockspace(struct dlm_ls *ls);
23void dlm_stop_lockspaces(void);
23 24
24#endif /* __LOCKSPACE_DOT_H__ */ 25#endif /* __LOCKSPACE_DOT_H__ */
25 26
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index 34f14a14fb4e..b3832c67194a 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved. 2 * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
3 * 3 *
4 * This copyrighted material is made available to anyone wishing to use, 4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions 5 * modify, copy, or redistribute it subject to the terms and conditions
@@ -15,7 +15,6 @@
15#include <linux/poll.h> 15#include <linux/poll.h>
16#include <linux/signal.h> 16#include <linux/signal.h>
17#include <linux/spinlock.h> 17#include <linux/spinlock.h>
18#include <linux/smp_lock.h>
19#include <linux/dlm.h> 18#include <linux/dlm.h>
20#include <linux/dlm_device.h> 19#include <linux/dlm_device.h>
21 20
@@ -27,6 +26,8 @@
27 26
28static const char name_prefix[] = "dlm"; 27static const char name_prefix[] = "dlm";
29static const struct file_operations device_fops; 28static const struct file_operations device_fops;
29static atomic_t dlm_monitor_opened;
30static int dlm_monitor_unused = 1;
30 31
31#ifdef CONFIG_COMPAT 32#ifdef CONFIG_COMPAT
32 33
@@ -340,10 +341,15 @@ static int device_user_deadlock(struct dlm_user_proc *proc,
340 return error; 341 return error;
341} 342}
342 343
343static int create_misc_device(struct dlm_ls *ls, char *name) 344static int dlm_device_register(struct dlm_ls *ls, char *name)
344{ 345{
345 int error, len; 346 int error, len;
346 347
348 /* The device is already registered. This happens when the
349 lockspace is created multiple times from userspace. */
350 if (ls->ls_device.name)
351 return 0;
352
347 error = -ENOMEM; 353 error = -ENOMEM;
348 len = strlen(name) + strlen(name_prefix) + 2; 354 len = strlen(name) + strlen(name_prefix) + 2;
349 ls->ls_device.name = kzalloc(len, GFP_KERNEL); 355 ls->ls_device.name = kzalloc(len, GFP_KERNEL);
@@ -363,6 +369,22 @@ fail:
363 return error; 369 return error;
364} 370}
365 371
372int dlm_device_deregister(struct dlm_ls *ls)
373{
374 int error;
375
376 /* The device is not registered. This happens when the lockspace
377 was never used from userspace, or when device_create_lockspace()
378 calls dlm_release_lockspace() after the register fails. */
379 if (!ls->ls_device.name)
380 return 0;
381
382 error = misc_deregister(&ls->ls_device);
383 if (!error)
384 kfree(ls->ls_device.name);
385 return error;
386}
387
366static int device_user_purge(struct dlm_user_proc *proc, 388static int device_user_purge(struct dlm_user_proc *proc,
367 struct dlm_purge_params *params) 389 struct dlm_purge_params *params)
368{ 390{
@@ -397,7 +419,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params)
397 if (!ls) 419 if (!ls)
398 return -ENOENT; 420 return -ENOENT;
399 421
400 error = create_misc_device(ls, params->name); 422 error = dlm_device_register(ls, params->name);
401 dlm_put_lockspace(ls); 423 dlm_put_lockspace(ls);
402 424
403 if (error) 425 if (error)
@@ -421,31 +443,22 @@ static int device_remove_lockspace(struct dlm_lspace_params *params)
421 if (!ls) 443 if (!ls)
422 return -ENOENT; 444 return -ENOENT;
423 445
424 /* Deregister the misc device first, so we don't have
425 * a device that's not attached to a lockspace. If
426 * dlm_release_lockspace fails then we can recreate it
427 */
428 error = misc_deregister(&ls->ls_device);
429 if (error) {
430 dlm_put_lockspace(ls);
431 goto out;
432 }
433 kfree(ls->ls_device.name);
434
435 if (params->flags & DLM_USER_LSFLG_FORCEFREE) 446 if (params->flags & DLM_USER_LSFLG_FORCEFREE)
436 force = 2; 447 force = 2;
437 448
438 lockspace = ls->ls_local_handle; 449 lockspace = ls->ls_local_handle;
450 dlm_put_lockspace(ls);
439 451
440 /* dlm_release_lockspace waits for references to go to zero, 452 /* The final dlm_release_lockspace waits for references to go to
441 so all processes will need to close their device for the ls 453 zero, so all processes will need to close their device for the
442 before the release will procede */ 454 ls before the release will proceed. release also calls the
455 device_deregister above. Converting a positive return value
456 from release to zero means that userspace won't know when its
457 release was the final one, but it shouldn't need to know. */
443 458
444 dlm_put_lockspace(ls);
445 error = dlm_release_lockspace(lockspace, force); 459 error = dlm_release_lockspace(lockspace, force);
446 if (error) 460 if (error > 0)
447 create_misc_device(ls, ls->ls_name); 461 error = 0;
448 out:
449 return error; 462 return error;
450} 463}
451 464
@@ -623,17 +636,13 @@ static int device_open(struct inode *inode, struct file *file)
623 struct dlm_user_proc *proc; 636 struct dlm_user_proc *proc;
624 struct dlm_ls *ls; 637 struct dlm_ls *ls;
625 638
626 lock_kernel();
627 ls = dlm_find_lockspace_device(iminor(inode)); 639 ls = dlm_find_lockspace_device(iminor(inode));
628 if (!ls) { 640 if (!ls)
629 unlock_kernel();
630 return -ENOENT; 641 return -ENOENT;
631 }
632 642
633 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL); 643 proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL);
634 if (!proc) { 644 if (!proc) {
635 dlm_put_lockspace(ls); 645 dlm_put_lockspace(ls);
636 unlock_kernel();
637 return -ENOMEM; 646 return -ENOMEM;
638 } 647 }
639 648
@@ -645,7 +654,6 @@ static int device_open(struct inode *inode, struct file *file)
645 spin_lock_init(&proc->locks_spin); 654 spin_lock_init(&proc->locks_spin);
646 init_waitqueue_head(&proc->wait); 655 init_waitqueue_head(&proc->wait);
647 file->private_data = proc; 656 file->private_data = proc;
648 unlock_kernel();
649 657
650 return 0; 658 return 0;
651} 659}
@@ -878,9 +886,28 @@ static unsigned int device_poll(struct file *file, poll_table *wait)
878 return 0; 886 return 0;
879} 887}
880 888
889int dlm_user_daemon_available(void)
890{
891 /* dlm_controld hasn't started (or, has started, but not
892 properly populated configfs) */
893
894 if (!dlm_our_nodeid())
895 return 0;
896
897 /* This is to deal with versions of dlm_controld that don't
898 know about the monitor device. We assume that if the
899 dlm_controld was started (above), but the monitor device
900 was never opened, that it's an old version. dlm_controld
901 should open the monitor device before populating configfs. */
902
903 if (dlm_monitor_unused)
904 return 1;
905
906 return atomic_read(&dlm_monitor_opened) ? 1 : 0;
907}
908
881static int ctl_device_open(struct inode *inode, struct file *file) 909static int ctl_device_open(struct inode *inode, struct file *file)
882{ 910{
883 cycle_kernel_lock();
884 file->private_data = NULL; 911 file->private_data = NULL;
885 return 0; 912 return 0;
886} 913}
@@ -890,6 +917,20 @@ static int ctl_device_close(struct inode *inode, struct file *file)
890 return 0; 917 return 0;
891} 918}
892 919
920static int monitor_device_open(struct inode *inode, struct file *file)
921{
922 atomic_inc(&dlm_monitor_opened);
923 dlm_monitor_unused = 0;
924 return 0;
925}
926
927static int monitor_device_close(struct inode *inode, struct file *file)
928{
929 if (atomic_dec_and_test(&dlm_monitor_opened))
930 dlm_stop_lockspaces();
931 return 0;
932}
933
893static const struct file_operations device_fops = { 934static const struct file_operations device_fops = {
894 .open = device_open, 935 .open = device_open,
895 .release = device_close, 936 .release = device_close,
@@ -913,19 +954,42 @@ static struct miscdevice ctl_device = {
913 .minor = MISC_DYNAMIC_MINOR, 954 .minor = MISC_DYNAMIC_MINOR,
914}; 955};
915 956
957static const struct file_operations monitor_device_fops = {
958 .open = monitor_device_open,
959 .release = monitor_device_close,
960 .owner = THIS_MODULE,
961};
962
963static struct miscdevice monitor_device = {
964 .name = "dlm-monitor",
965 .fops = &monitor_device_fops,
966 .minor = MISC_DYNAMIC_MINOR,
967};
968
916int __init dlm_user_init(void) 969int __init dlm_user_init(void)
917{ 970{
918 int error; 971 int error;
919 972
973 atomic_set(&dlm_monitor_opened, 0);
974
920 error = misc_register(&ctl_device); 975 error = misc_register(&ctl_device);
921 if (error) 976 if (error) {
922 log_print("misc_register failed for control device"); 977 log_print("misc_register failed for control device");
978 goto out;
979 }
923 980
981 error = misc_register(&monitor_device);
982 if (error) {
983 log_print("misc_register failed for monitor device");
984 misc_deregister(&ctl_device);
985 }
986 out:
924 return error; 987 return error;
925} 988}
926 989
927void dlm_user_exit(void) 990void dlm_user_exit(void)
928{ 991{
929 misc_deregister(&ctl_device); 992 misc_deregister(&ctl_device);
993 misc_deregister(&monitor_device);
930} 994}
931 995
diff --git a/fs/dlm/user.h b/fs/dlm/user.h
index d38e9f3e4151..35eb6a13d616 100644
--- a/fs/dlm/user.h
+++ b/fs/dlm/user.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2006 Red Hat, Inc. All rights reserved. 2 * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
3 * 3 *
4 * This copyrighted material is made available to anyone wishing to use, 4 * This copyrighted material is made available to anyone wishing to use,
5 * modify, copy, or redistribute it subject to the terms and conditions 5 * modify, copy, or redistribute it subject to the terms and conditions
@@ -12,5 +12,7 @@
12void dlm_user_add_ast(struct dlm_lkb *lkb, int type); 12void dlm_user_add_ast(struct dlm_lkb *lkb, int type);
13int dlm_user_init(void); 13int dlm_user_init(void);
14void dlm_user_exit(void); 14void dlm_user_exit(void);
15int dlm_device_deregister(struct dlm_ls *ls);
16int dlm_user_daemon_available(void);
15 17
16#endif 18#endif
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
index 09d78c216f48..0c4cbe6c8285 100644
--- a/fs/gfs2/locking/dlm/mount.c
+++ b/fs/gfs2/locking/dlm/mount.c
@@ -144,7 +144,8 @@ static int gdlm_mount(char *table_name, char *host_data,
144 144
145 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), 145 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
146 &ls->dlm_lockspace, 146 &ls->dlm_lockspace,
147 DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0), 147 DLM_LSFL_FS | DLM_LSFL_NEWEXCL |
148 (nodir ? DLM_LSFL_NODIR : 0),
148 GDLM_LVB_SIZE); 149 GDLM_LVB_SIZE);
149 if (error) { 150 if (error) {
150 log_error("dlm_new_lockspace error %d", error); 151 log_error("dlm_new_lockspace error %d", error);
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 203a025e30e5..b9cd38603fd8 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -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
@@ -65,9 +65,12 @@ struct dlm_lksb {
65 char * sb_lvbptr; 65 char * sb_lvbptr;
66}; 66};
67 67
68/* dlm_new_lockspace() flags */
69
68#define DLM_LSFL_NODIR 0x00000001 70#define DLM_LSFL_NODIR 0x00000001
69#define DLM_LSFL_TIMEWARN 0x00000002 71#define DLM_LSFL_TIMEWARN 0x00000002
70#define DLM_LSFL_FS 0x00000004 72#define DLM_LSFL_FS 0x00000004
73#define DLM_LSFL_NEWEXCL 0x00000008
71 74
72#ifdef __KERNEL__ 75#ifdef __KERNEL__
73 76
diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
index c6034508fed9..3060783c4191 100644
--- a/include/linux/dlm_device.h
+++ b/include/linux/dlm_device.h
@@ -26,7 +26,7 @@
26/* Version of the device interface */ 26/* Version of the device interface */
27#define DLM_DEVICE_VERSION_MAJOR 6 27#define DLM_DEVICE_VERSION_MAJOR 6
28#define DLM_DEVICE_VERSION_MINOR 0 28#define DLM_DEVICE_VERSION_MINOR 0
29#define DLM_DEVICE_VERSION_PATCH 0 29#define DLM_DEVICE_VERSION_PATCH 1
30 30
31/* struct passed to the lock write */ 31/* struct passed to the lock write */
32struct dlm_lock_params { 32struct dlm_lock_params {