diff options
Diffstat (limited to 'fs/dlm')
-rw-r--r-- | fs/dlm/ast.c | 4 | ||||
-rw-r--r-- | fs/dlm/config.c | 79 | ||||
-rw-r--r-- | fs/dlm/config.h | 2 | ||||
-rw-r--r-- | fs/dlm/dlm_internal.h | 46 | ||||
-rw-r--r-- | fs/dlm/lockspace.c | 15 | ||||
-rw-r--r-- | fs/dlm/lowcomms.c | 215 | ||||
-rw-r--r-- | fs/dlm/lowcomms.h | 2 | ||||
-rw-r--r-- | fs/dlm/main.c | 2 | ||||
-rw-r--r-- | fs/dlm/member.c | 17 | ||||
-rw-r--r-- | fs/dlm/netlink.c | 8 | ||||
-rw-r--r-- | fs/dlm/rcom.c | 2 | ||||
-rw-r--r-- | fs/dlm/recoverd.c | 27 | ||||
-rw-r--r-- | fs/dlm/recoverd.h | 1 | ||||
-rw-r--r-- | fs/dlm/user.c | 7 |
14 files changed, 293 insertions, 134 deletions
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c index 63dc19c54d5a..27a6ba9aaeec 100644 --- a/fs/dlm/ast.c +++ b/fs/dlm/ast.c | |||
@@ -15,8 +15,8 @@ | |||
15 | #include "lock.h" | 15 | #include "lock.h" |
16 | #include "user.h" | 16 | #include "user.h" |
17 | 17 | ||
18 | static uint64_t dlm_cb_seq; | 18 | static uint64_t dlm_cb_seq; |
19 | static spinlock_t dlm_cb_seq_spin; | 19 | static DEFINE_SPINLOCK(dlm_cb_seq_spin); |
20 | 20 | ||
21 | static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb) | 21 | static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb) |
22 | { | 22 | { |
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 9ccf7346834a..a0387dd8b1f0 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c | |||
@@ -750,6 +750,7 @@ static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf, | |||
750 | static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) | 750 | static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) |
751 | { | 751 | { |
752 | struct sockaddr_storage *addr; | 752 | struct sockaddr_storage *addr; |
753 | int rv; | ||
753 | 754 | ||
754 | if (len != sizeof(struct sockaddr_storage)) | 755 | if (len != sizeof(struct sockaddr_storage)) |
755 | return -EINVAL; | 756 | return -EINVAL; |
@@ -762,6 +763,13 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) | |||
762 | return -ENOMEM; | 763 | return -ENOMEM; |
763 | 764 | ||
764 | memcpy(addr, buf, len); | 765 | memcpy(addr, buf, len); |
766 | |||
767 | rv = dlm_lowcomms_addr(cm->nodeid, addr, len); | ||
768 | if (rv) { | ||
769 | kfree(addr); | ||
770 | return rv; | ||
771 | } | ||
772 | |||
765 | cm->addr[cm->addr_count++] = addr; | 773 | cm->addr[cm->addr_count++] = addr; |
766 | return len; | 774 | return len; |
767 | } | 775 | } |
@@ -878,34 +886,7 @@ static void put_space(struct dlm_space *sp) | |||
878 | config_item_put(&sp->group.cg_item); | 886 | config_item_put(&sp->group.cg_item); |
879 | } | 887 | } |
880 | 888 | ||
881 | static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y) | 889 | static struct dlm_comm *get_comm(int nodeid) |
882 | { | ||
883 | switch (x->ss_family) { | ||
884 | case AF_INET: { | ||
885 | struct sockaddr_in *sinx = (struct sockaddr_in *)x; | ||
886 | struct sockaddr_in *siny = (struct sockaddr_in *)y; | ||
887 | if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr) | ||
888 | return 0; | ||
889 | if (sinx->sin_port != siny->sin_port) | ||
890 | return 0; | ||
891 | break; | ||
892 | } | ||
893 | case AF_INET6: { | ||
894 | struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x; | ||
895 | struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y; | ||
896 | if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr)) | ||
897 | return 0; | ||
898 | if (sinx->sin6_port != siny->sin6_port) | ||
899 | return 0; | ||
900 | break; | ||
901 | } | ||
902 | default: | ||
903 | return 0; | ||
904 | } | ||
905 | return 1; | ||
906 | } | ||
907 | |||
908 | static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) | ||
909 | { | 890 | { |
910 | struct config_item *i; | 891 | struct config_item *i; |
911 | struct dlm_comm *cm = NULL; | 892 | struct dlm_comm *cm = NULL; |
@@ -919,19 +900,11 @@ static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) | |||
919 | list_for_each_entry(i, &comm_list->cg_children, ci_entry) { | 900 | list_for_each_entry(i, &comm_list->cg_children, ci_entry) { |
920 | cm = config_item_to_comm(i); | 901 | cm = config_item_to_comm(i); |
921 | 902 | ||
922 | if (nodeid) { | 903 | if (cm->nodeid != nodeid) |
923 | if (cm->nodeid != nodeid) | 904 | continue; |
924 | continue; | 905 | found = 1; |
925 | found = 1; | 906 | config_item_get(i); |
926 | config_item_get(i); | 907 | break; |
927 | break; | ||
928 | } else { | ||
929 | if (!cm->addr_count || !addr_compare(cm->addr[0], addr)) | ||
930 | continue; | ||
931 | found = 1; | ||
932 | config_item_get(i); | ||
933 | break; | ||
934 | } | ||
935 | } | 908 | } |
936 | mutex_unlock(&clusters_root.subsys.su_mutex); | 909 | mutex_unlock(&clusters_root.subsys.su_mutex); |
937 | 910 | ||
@@ -995,7 +968,7 @@ int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, | |||
995 | 968 | ||
996 | int dlm_comm_seq(int nodeid, uint32_t *seq) | 969 | int dlm_comm_seq(int nodeid, uint32_t *seq) |
997 | { | 970 | { |
998 | struct dlm_comm *cm = get_comm(nodeid, NULL); | 971 | struct dlm_comm *cm = get_comm(nodeid); |
999 | if (!cm) | 972 | if (!cm) |
1000 | return -EEXIST; | 973 | return -EEXIST; |
1001 | *seq = cm->seq; | 974 | *seq = cm->seq; |
@@ -1003,28 +976,6 @@ int dlm_comm_seq(int nodeid, uint32_t *seq) | |||
1003 | return 0; | 976 | return 0; |
1004 | } | 977 | } |
1005 | 978 | ||
1006 | int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) | ||
1007 | { | ||
1008 | struct dlm_comm *cm = get_comm(nodeid, NULL); | ||
1009 | if (!cm) | ||
1010 | return -EEXIST; | ||
1011 | if (!cm->addr_count) | ||
1012 | return -ENOENT; | ||
1013 | memcpy(addr, cm->addr[0], sizeof(*addr)); | ||
1014 | put_comm(cm); | ||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) | ||
1019 | { | ||
1020 | struct dlm_comm *cm = get_comm(0, addr); | ||
1021 | if (!cm) | ||
1022 | return -EEXIST; | ||
1023 | *nodeid = cm->nodeid; | ||
1024 | put_comm(cm); | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | int dlm_our_nodeid(void) | 979 | int dlm_our_nodeid(void) |
1029 | { | 980 | { |
1030 | return local_comm ? local_comm->nodeid : 0; | 981 | return local_comm ? local_comm->nodeid : 0; |
diff --git a/fs/dlm/config.h b/fs/dlm/config.h index dbd35a08f3a5..f30697bc2780 100644 --- a/fs/dlm/config.h +++ b/fs/dlm/config.h | |||
@@ -46,8 +46,6 @@ void dlm_config_exit(void); | |||
46 | int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, | 46 | int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, |
47 | int *count_out); | 47 | int *count_out); |
48 | int dlm_comm_seq(int nodeid, uint32_t *seq); | 48 | int dlm_comm_seq(int nodeid, uint32_t *seq); |
49 | int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr); | ||
50 | int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid); | ||
51 | int dlm_our_nodeid(void); | 49 | int dlm_our_nodeid(void); |
52 | int dlm_our_addr(struct sockaddr_storage *addr, int num); | 50 | int dlm_our_addr(struct sockaddr_storage *addr, int num); |
53 | 51 | ||
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 9d3e485f88c8..871c1abf6029 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -604,6 +604,7 @@ struct dlm_ls { | |||
604 | struct idr ls_recover_idr; | 604 | struct idr ls_recover_idr; |
605 | spinlock_t ls_recover_idr_lock; | 605 | spinlock_t ls_recover_idr_lock; |
606 | wait_queue_head_t ls_wait_general; | 606 | wait_queue_head_t ls_wait_general; |
607 | wait_queue_head_t ls_recover_lock_wait; | ||
607 | struct mutex ls_clear_proc_locks; | 608 | struct mutex ls_clear_proc_locks; |
608 | 609 | ||
609 | struct list_head ls_root_list; /* root resources */ | 610 | struct list_head ls_root_list; /* root resources */ |
@@ -616,15 +617,40 @@ struct dlm_ls { | |||
616 | char ls_name[1]; | 617 | char ls_name[1]; |
617 | }; | 618 | }; |
618 | 619 | ||
619 | #define LSFL_WORK 0 | 620 | /* |
620 | #define LSFL_RUNNING 1 | 621 | * LSFL_RECOVER_STOP - dlm_ls_stop() sets this to tell dlm recovery routines |
621 | #define LSFL_RECOVERY_STOP 2 | 622 | * that they should abort what they're doing so new recovery can be started. |
622 | #define LSFL_RCOM_READY 3 | 623 | * |
623 | #define LSFL_RCOM_WAIT 4 | 624 | * LSFL_RECOVER_DOWN - dlm_ls_stop() sets this to tell dlm_recoverd that it |
624 | #define LSFL_UEVENT_WAIT 5 | 625 | * should do down_write() on the in_recovery rw_semaphore. (doing down_write |
625 | #define LSFL_TIMEWARN 6 | 626 | * within dlm_ls_stop causes complaints about the lock acquired/released |
626 | #define LSFL_CB_DELAY 7 | 627 | * in different contexts.) |
627 | #define LSFL_NODIR 8 | 628 | * |
629 | * LSFL_RECOVER_LOCK - dlm_recoverd holds the in_recovery rw_semaphore. | ||
630 | * It sets this after it is done with down_write() on the in_recovery | ||
631 | * rw_semaphore and clears it after it has released the rw_semaphore. | ||
632 | * | ||
633 | * LSFL_RECOVER_WORK - dlm_ls_start() sets this to tell dlm_recoverd that it | ||
634 | * should begin recovery of the lockspace. | ||
635 | * | ||
636 | * LSFL_RUNNING - set when normal locking activity is enabled. | ||
637 | * dlm_ls_stop() clears this to tell dlm locking routines that they should | ||
638 | * quit what they are doing so recovery can run. dlm_recoverd sets | ||
639 | * this after recovery is finished. | ||
640 | */ | ||
641 | |||
642 | #define LSFL_RECOVER_STOP 0 | ||
643 | #define LSFL_RECOVER_DOWN 1 | ||
644 | #define LSFL_RECOVER_LOCK 2 | ||
645 | #define LSFL_RECOVER_WORK 3 | ||
646 | #define LSFL_RUNNING 4 | ||
647 | |||
648 | #define LSFL_RCOM_READY 5 | ||
649 | #define LSFL_RCOM_WAIT 6 | ||
650 | #define LSFL_UEVENT_WAIT 7 | ||
651 | #define LSFL_TIMEWARN 8 | ||
652 | #define LSFL_CB_DELAY 9 | ||
653 | #define LSFL_NODIR 10 | ||
628 | 654 | ||
629 | /* much of this is just saving user space pointers associated with the | 655 | /* much of this is just saving user space pointers associated with the |
630 | lock that we pass back to the user lib with an ast */ | 656 | lock that we pass back to the user lib with an ast */ |
@@ -667,7 +693,7 @@ static inline int dlm_locking_stopped(struct dlm_ls *ls) | |||
667 | 693 | ||
668 | static inline int dlm_recovery_stopped(struct dlm_ls *ls) | 694 | static inline int dlm_recovery_stopped(struct dlm_ls *ls) |
669 | { | 695 | { |
670 | return test_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); | 696 | return test_bit(LSFL_RECOVER_STOP, &ls->ls_flags); |
671 | } | 697 | } |
672 | 698 | ||
673 | static inline int dlm_no_directory(struct dlm_ls *ls) | 699 | static inline int dlm_no_directory(struct dlm_ls *ls) |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 952557d00ccd..2e99fb0c9737 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -582,8 +582,6 @@ static int new_lockspace(const char *name, const char *cluster, | |||
582 | INIT_LIST_HEAD(&ls->ls_root_list); | 582 | INIT_LIST_HEAD(&ls->ls_root_list); |
583 | init_rwsem(&ls->ls_root_sem); | 583 | init_rwsem(&ls->ls_root_sem); |
584 | 584 | ||
585 | down_write(&ls->ls_in_recovery); | ||
586 | |||
587 | spin_lock(&lslist_lock); | 585 | spin_lock(&lslist_lock); |
588 | ls->ls_create_count = 1; | 586 | ls->ls_create_count = 1; |
589 | list_add(&ls->ls_list, &lslist); | 587 | list_add(&ls->ls_list, &lslist); |
@@ -597,13 +595,24 @@ static int new_lockspace(const char *name, const char *cluster, | |||
597 | } | 595 | } |
598 | } | 596 | } |
599 | 597 | ||
600 | /* needs to find ls in lslist */ | 598 | init_waitqueue_head(&ls->ls_recover_lock_wait); |
599 | |||
600 | /* | ||
601 | * Once started, dlm_recoverd first looks for ls in lslist, then | ||
602 | * initializes ls_in_recovery as locked in "down" mode. We need | ||
603 | * to wait for the wakeup from dlm_recoverd because in_recovery | ||
604 | * has to start out in down mode. | ||
605 | */ | ||
606 | |||
601 | error = dlm_recoverd_start(ls); | 607 | error = dlm_recoverd_start(ls); |
602 | if (error) { | 608 | if (error) { |
603 | log_error(ls, "can't start dlm_recoverd %d", error); | 609 | log_error(ls, "can't start dlm_recoverd %d", error); |
604 | goto out_callback; | 610 | goto out_callback; |
605 | } | 611 | } |
606 | 612 | ||
613 | wait_event(ls->ls_recover_lock_wait, | ||
614 | test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags)); | ||
615 | |||
607 | ls->ls_kobj.kset = dlm_kset; | 616 | ls->ls_kobj.kset = dlm_kset; |
608 | error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL, | 617 | error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL, |
609 | "%s", ls->ls_name); | 618 | "%s", ls->ls_name); |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 5c1b0e38c7a4..331ea4f94efd 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -140,6 +140,16 @@ struct writequeue_entry { | |||
140 | struct connection *con; | 140 | struct connection *con; |
141 | }; | 141 | }; |
142 | 142 | ||
143 | struct dlm_node_addr { | ||
144 | struct list_head list; | ||
145 | int nodeid; | ||
146 | int addr_count; | ||
147 | struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; | ||
148 | }; | ||
149 | |||
150 | static LIST_HEAD(dlm_node_addrs); | ||
151 | static DEFINE_SPINLOCK(dlm_node_addrs_spin); | ||
152 | |||
143 | static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; | 153 | static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; |
144 | static int dlm_local_count; | 154 | static int dlm_local_count; |
145 | static int dlm_allow_conn; | 155 | static int dlm_allow_conn; |
@@ -264,31 +274,146 @@ static struct connection *assoc2con(int assoc_id) | |||
264 | return NULL; | 274 | return NULL; |
265 | } | 275 | } |
266 | 276 | ||
267 | static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr) | 277 | static struct dlm_node_addr *find_node_addr(int nodeid) |
278 | { | ||
279 | struct dlm_node_addr *na; | ||
280 | |||
281 | list_for_each_entry(na, &dlm_node_addrs, list) { | ||
282 | if (na->nodeid == nodeid) | ||
283 | return na; | ||
284 | } | ||
285 | return NULL; | ||
286 | } | ||
287 | |||
288 | static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y) | ||
289 | { | ||
290 | switch (x->ss_family) { | ||
291 | case AF_INET: { | ||
292 | struct sockaddr_in *sinx = (struct sockaddr_in *)x; | ||
293 | struct sockaddr_in *siny = (struct sockaddr_in *)y; | ||
294 | if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr) | ||
295 | return 0; | ||
296 | if (sinx->sin_port != siny->sin_port) | ||
297 | return 0; | ||
298 | break; | ||
299 | } | ||
300 | case AF_INET6: { | ||
301 | struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x; | ||
302 | struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y; | ||
303 | if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr)) | ||
304 | return 0; | ||
305 | if (sinx->sin6_port != siny->sin6_port) | ||
306 | return 0; | ||
307 | break; | ||
308 | } | ||
309 | default: | ||
310 | return 0; | ||
311 | } | ||
312 | return 1; | ||
313 | } | ||
314 | |||
315 | static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out, | ||
316 | struct sockaddr *sa_out) | ||
268 | { | 317 | { |
269 | struct sockaddr_storage addr; | 318 | struct sockaddr_storage sas; |
270 | int error; | 319 | struct dlm_node_addr *na; |
271 | 320 | ||
272 | if (!dlm_local_count) | 321 | if (!dlm_local_count) |
273 | return -1; | 322 | return -1; |
274 | 323 | ||
275 | error = dlm_nodeid_to_addr(nodeid, &addr); | 324 | spin_lock(&dlm_node_addrs_spin); |
276 | if (error) | 325 | na = find_node_addr(nodeid); |
277 | return error; | 326 | if (na && na->addr_count) |
327 | memcpy(&sas, na->addr[0], sizeof(struct sockaddr_storage)); | ||
328 | spin_unlock(&dlm_node_addrs_spin); | ||
329 | |||
330 | if (!na) | ||
331 | return -EEXIST; | ||
332 | |||
333 | if (!na->addr_count) | ||
334 | return -ENOENT; | ||
335 | |||
336 | if (sas_out) | ||
337 | memcpy(sas_out, &sas, sizeof(struct sockaddr_storage)); | ||
338 | |||
339 | if (!sa_out) | ||
340 | return 0; | ||
278 | 341 | ||
279 | if (dlm_local_addr[0]->ss_family == AF_INET) { | 342 | if (dlm_local_addr[0]->ss_family == AF_INET) { |
280 | struct sockaddr_in *in4 = (struct sockaddr_in *) &addr; | 343 | struct sockaddr_in *in4 = (struct sockaddr_in *) &sas; |
281 | struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr; | 344 | struct sockaddr_in *ret4 = (struct sockaddr_in *) sa_out; |
282 | ret4->sin_addr.s_addr = in4->sin_addr.s_addr; | 345 | ret4->sin_addr.s_addr = in4->sin_addr.s_addr; |
283 | } else { | 346 | } else { |
284 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &addr; | 347 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &sas; |
285 | struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr; | 348 | struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) sa_out; |
286 | ret6->sin6_addr = in6->sin6_addr; | 349 | ret6->sin6_addr = in6->sin6_addr; |
287 | } | 350 | } |
288 | 351 | ||
289 | return 0; | 352 | return 0; |
290 | } | 353 | } |
291 | 354 | ||
355 | static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) | ||
356 | { | ||
357 | struct dlm_node_addr *na; | ||
358 | int rv = -EEXIST; | ||
359 | |||
360 | spin_lock(&dlm_node_addrs_spin); | ||
361 | list_for_each_entry(na, &dlm_node_addrs, list) { | ||
362 | if (!na->addr_count) | ||
363 | continue; | ||
364 | |||
365 | if (!addr_compare(na->addr[0], addr)) | ||
366 | continue; | ||
367 | |||
368 | *nodeid = na->nodeid; | ||
369 | rv = 0; | ||
370 | break; | ||
371 | } | ||
372 | spin_unlock(&dlm_node_addrs_spin); | ||
373 | return rv; | ||
374 | } | ||
375 | |||
376 | int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len) | ||
377 | { | ||
378 | struct sockaddr_storage *new_addr; | ||
379 | struct dlm_node_addr *new_node, *na; | ||
380 | |||
381 | new_node = kzalloc(sizeof(struct dlm_node_addr), GFP_NOFS); | ||
382 | if (!new_node) | ||
383 | return -ENOMEM; | ||
384 | |||
385 | new_addr = kzalloc(sizeof(struct sockaddr_storage), GFP_NOFS); | ||
386 | if (!new_addr) { | ||
387 | kfree(new_node); | ||
388 | return -ENOMEM; | ||
389 | } | ||
390 | |||
391 | memcpy(new_addr, addr, len); | ||
392 | |||
393 | spin_lock(&dlm_node_addrs_spin); | ||
394 | na = find_node_addr(nodeid); | ||
395 | if (!na) { | ||
396 | new_node->nodeid = nodeid; | ||
397 | new_node->addr[0] = new_addr; | ||
398 | new_node->addr_count = 1; | ||
399 | list_add(&new_node->list, &dlm_node_addrs); | ||
400 | spin_unlock(&dlm_node_addrs_spin); | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | if (na->addr_count >= DLM_MAX_ADDR_COUNT) { | ||
405 | spin_unlock(&dlm_node_addrs_spin); | ||
406 | kfree(new_addr); | ||
407 | kfree(new_node); | ||
408 | return -ENOSPC; | ||
409 | } | ||
410 | |||
411 | na->addr[na->addr_count++] = new_addr; | ||
412 | spin_unlock(&dlm_node_addrs_spin); | ||
413 | kfree(new_node); | ||
414 | return 0; | ||
415 | } | ||
416 | |||
292 | /* Data available on socket or listen socket received a connect */ | 417 | /* Data available on socket or listen socket received a connect */ |
293 | static void lowcomms_data_ready(struct sock *sk, int count_unused) | 418 | static void lowcomms_data_ready(struct sock *sk, int count_unused) |
294 | { | 419 | { |
@@ -348,7 +473,7 @@ int dlm_lowcomms_connect_node(int nodeid) | |||
348 | } | 473 | } |
349 | 474 | ||
350 | /* Make a socket active */ | 475 | /* Make a socket active */ |
351 | static int add_sock(struct socket *sock, struct connection *con) | 476 | static void add_sock(struct socket *sock, struct connection *con) |
352 | { | 477 | { |
353 | con->sock = sock; | 478 | con->sock = sock; |
354 | 479 | ||
@@ -358,7 +483,6 @@ static int add_sock(struct socket *sock, struct connection *con) | |||
358 | con->sock->sk->sk_state_change = lowcomms_state_change; | 483 | con->sock->sk->sk_state_change = lowcomms_state_change; |
359 | con->sock->sk->sk_user_data = con; | 484 | con->sock->sk->sk_user_data = con; |
360 | con->sock->sk->sk_allocation = GFP_NOFS; | 485 | con->sock->sk->sk_allocation = GFP_NOFS; |
361 | return 0; | ||
362 | } | 486 | } |
363 | 487 | ||
364 | /* Add the port number to an IPv6 or 4 sockaddr and return the address | 488 | /* Add the port number to an IPv6 or 4 sockaddr and return the address |
@@ -510,7 +634,7 @@ static void process_sctp_notification(struct connection *con, | |||
510 | return; | 634 | return; |
511 | } | 635 | } |
512 | make_sockaddr(&prim.ssp_addr, 0, &addr_len); | 636 | make_sockaddr(&prim.ssp_addr, 0, &addr_len); |
513 | if (dlm_addr_to_nodeid(&prim.ssp_addr, &nodeid)) { | 637 | if (addr_to_nodeid(&prim.ssp_addr, &nodeid)) { |
514 | unsigned char *b=(unsigned char *)&prim.ssp_addr; | 638 | unsigned char *b=(unsigned char *)&prim.ssp_addr; |
515 | log_print("reject connect from unknown addr"); | 639 | log_print("reject connect from unknown addr"); |
516 | print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, | 640 | print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, |
@@ -747,7 +871,7 @@ static int tcp_accept_from_sock(struct connection *con) | |||
747 | 871 | ||
748 | /* Get the new node's NODEID */ | 872 | /* Get the new node's NODEID */ |
749 | make_sockaddr(&peeraddr, 0, &len); | 873 | make_sockaddr(&peeraddr, 0, &len); |
750 | if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) { | 874 | if (addr_to_nodeid(&peeraddr, &nodeid)) { |
751 | unsigned char *b=(unsigned char *)&peeraddr; | 875 | unsigned char *b=(unsigned char *)&peeraddr; |
752 | log_print("connect from non cluster node"); | 876 | log_print("connect from non cluster node"); |
753 | print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, | 877 | print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, |
@@ -862,7 +986,7 @@ static void sctp_init_assoc(struct connection *con) | |||
862 | if (con->retries++ > MAX_CONNECT_RETRIES) | 986 | if (con->retries++ > MAX_CONNECT_RETRIES) |
863 | return; | 987 | return; |
864 | 988 | ||
865 | if (nodeid_to_addr(con->nodeid, (struct sockaddr *)&rem_addr)) { | 989 | if (nodeid_to_addr(con->nodeid, NULL, (struct sockaddr *)&rem_addr)) { |
866 | log_print("no address for nodeid %d", con->nodeid); | 990 | log_print("no address for nodeid %d", con->nodeid); |
867 | return; | 991 | return; |
868 | } | 992 | } |
@@ -928,11 +1052,11 @@ static void sctp_init_assoc(struct connection *con) | |||
928 | /* Connect a new socket to its peer */ | 1052 | /* Connect a new socket to its peer */ |
929 | static void tcp_connect_to_sock(struct connection *con) | 1053 | static void tcp_connect_to_sock(struct connection *con) |
930 | { | 1054 | { |
931 | int result = -EHOSTUNREACH; | ||
932 | struct sockaddr_storage saddr, src_addr; | 1055 | struct sockaddr_storage saddr, src_addr; |
933 | int addr_len; | 1056 | int addr_len; |
934 | struct socket *sock = NULL; | 1057 | struct socket *sock = NULL; |
935 | int one = 1; | 1058 | int one = 1; |
1059 | int result; | ||
936 | 1060 | ||
937 | if (con->nodeid == 0) { | 1061 | if (con->nodeid == 0) { |
938 | log_print("attempt to connect sock 0 foiled"); | 1062 | log_print("attempt to connect sock 0 foiled"); |
@@ -944,10 +1068,8 @@ static void tcp_connect_to_sock(struct connection *con) | |||
944 | goto out; | 1068 | goto out; |
945 | 1069 | ||
946 | /* Some odd races can cause double-connects, ignore them */ | 1070 | /* Some odd races can cause double-connects, ignore them */ |
947 | if (con->sock) { | 1071 | if (con->sock) |
948 | result = 0; | ||
949 | goto out; | 1072 | goto out; |
950 | } | ||
951 | 1073 | ||
952 | /* Create a socket to communicate with */ | 1074 | /* Create a socket to communicate with */ |
953 | result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM, | 1075 | result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM, |
@@ -956,8 +1078,11 @@ static void tcp_connect_to_sock(struct connection *con) | |||
956 | goto out_err; | 1078 | goto out_err; |
957 | 1079 | ||
958 | memset(&saddr, 0, sizeof(saddr)); | 1080 | memset(&saddr, 0, sizeof(saddr)); |
959 | if (dlm_nodeid_to_addr(con->nodeid, &saddr)) | 1081 | result = nodeid_to_addr(con->nodeid, &saddr, NULL); |
1082 | if (result < 0) { | ||
1083 | log_print("no address for nodeid %d", con->nodeid); | ||
960 | goto out_err; | 1084 | goto out_err; |
1085 | } | ||
961 | 1086 | ||
962 | sock->sk->sk_user_data = con; | 1087 | sock->sk->sk_user_data = con; |
963 | con->rx_action = receive_from_sock; | 1088 | con->rx_action = receive_from_sock; |
@@ -983,8 +1108,7 @@ static void tcp_connect_to_sock(struct connection *con) | |||
983 | kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one, | 1108 | kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one, |
984 | sizeof(one)); | 1109 | sizeof(one)); |
985 | 1110 | ||
986 | result = | 1111 | result = sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len, |
987 | sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len, | ||
988 | O_NONBLOCK); | 1112 | O_NONBLOCK); |
989 | if (result == -EINPROGRESS) | 1113 | if (result == -EINPROGRESS) |
990 | result = 0; | 1114 | result = 0; |
@@ -1002,11 +1126,17 @@ out_err: | |||
1002 | * Some errors are fatal and this list might need adjusting. For other | 1126 | * Some errors are fatal and this list might need adjusting. For other |
1003 | * errors we try again until the max number of retries is reached. | 1127 | * errors we try again until the max number of retries is reached. |
1004 | */ | 1128 | */ |
1005 | if (result != -EHOSTUNREACH && result != -ENETUNREACH && | 1129 | if (result != -EHOSTUNREACH && |
1006 | result != -ENETDOWN && result != -EINVAL | 1130 | result != -ENETUNREACH && |
1007 | && result != -EPROTONOSUPPORT) { | 1131 | result != -ENETDOWN && |
1132 | result != -EINVAL && | ||
1133 | result != -EPROTONOSUPPORT) { | ||
1134 | log_print("connect %d try %d error %d", con->nodeid, | ||
1135 | con->retries, result); | ||
1136 | mutex_unlock(&con->sock_mutex); | ||
1137 | msleep(1000); | ||
1008 | lowcomms_connect_sock(con); | 1138 | lowcomms_connect_sock(con); |
1009 | result = 0; | 1139 | return; |
1010 | } | 1140 | } |
1011 | out: | 1141 | out: |
1012 | mutex_unlock(&con->sock_mutex); | 1142 | mutex_unlock(&con->sock_mutex); |
@@ -1044,10 +1174,8 @@ static struct socket *tcp_create_listen_sock(struct connection *con, | |||
1044 | if (result < 0) { | 1174 | if (result < 0) { |
1045 | log_print("Failed to set SO_REUSEADDR on socket: %d", result); | 1175 | log_print("Failed to set SO_REUSEADDR on socket: %d", result); |
1046 | } | 1176 | } |
1047 | sock->sk->sk_user_data = con; | ||
1048 | con->rx_action = tcp_accept_from_sock; | 1177 | con->rx_action = tcp_accept_from_sock; |
1049 | con->connect_action = tcp_connect_to_sock; | 1178 | con->connect_action = tcp_connect_to_sock; |
1050 | con->sock = sock; | ||
1051 | 1179 | ||
1052 | /* Bind to our port */ | 1180 | /* Bind to our port */ |
1053 | make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len); | 1181 | make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len); |
@@ -1358,8 +1486,7 @@ static void send_to_sock(struct connection *con) | |||
1358 | } | 1486 | } |
1359 | cond_resched(); | 1487 | cond_resched(); |
1360 | goto out; | 1488 | goto out; |
1361 | } | 1489 | } else if (ret < 0) |
1362 | if (ret <= 0) | ||
1363 | goto send_error; | 1490 | goto send_error; |
1364 | } | 1491 | } |
1365 | 1492 | ||
@@ -1376,7 +1503,6 @@ static void send_to_sock(struct connection *con) | |||
1376 | if (e->len == 0 && e->users == 0) { | 1503 | if (e->len == 0 && e->users == 0) { |
1377 | list_del(&e->list); | 1504 | list_del(&e->list); |
1378 | free_entry(e); | 1505 | free_entry(e); |
1379 | continue; | ||
1380 | } | 1506 | } |
1381 | } | 1507 | } |
1382 | spin_unlock(&con->writequeue_lock); | 1508 | spin_unlock(&con->writequeue_lock); |
@@ -1394,7 +1520,6 @@ out_connect: | |||
1394 | mutex_unlock(&con->sock_mutex); | 1520 | mutex_unlock(&con->sock_mutex); |
1395 | if (!test_bit(CF_INIT_PENDING, &con->flags)) | 1521 | if (!test_bit(CF_INIT_PENDING, &con->flags)) |
1396 | lowcomms_connect_sock(con); | 1522 | lowcomms_connect_sock(con); |
1397 | return; | ||
1398 | } | 1523 | } |
1399 | 1524 | ||
1400 | static void clean_one_writequeue(struct connection *con) | 1525 | static void clean_one_writequeue(struct connection *con) |
@@ -1414,6 +1539,7 @@ static void clean_one_writequeue(struct connection *con) | |||
1414 | int dlm_lowcomms_close(int nodeid) | 1539 | int dlm_lowcomms_close(int nodeid) |
1415 | { | 1540 | { |
1416 | struct connection *con; | 1541 | struct connection *con; |
1542 | struct dlm_node_addr *na; | ||
1417 | 1543 | ||
1418 | log_print("closing connection to node %d", nodeid); | 1544 | log_print("closing connection to node %d", nodeid); |
1419 | con = nodeid2con(nodeid, 0); | 1545 | con = nodeid2con(nodeid, 0); |
@@ -1428,6 +1554,17 @@ int dlm_lowcomms_close(int nodeid) | |||
1428 | clean_one_writequeue(con); | 1554 | clean_one_writequeue(con); |
1429 | close_connection(con, true); | 1555 | close_connection(con, true); |
1430 | } | 1556 | } |
1557 | |||
1558 | spin_lock(&dlm_node_addrs_spin); | ||
1559 | na = find_node_addr(nodeid); | ||
1560 | if (na) { | ||
1561 | list_del(&na->list); | ||
1562 | while (na->addr_count--) | ||
1563 | kfree(na->addr[na->addr_count]); | ||
1564 | kfree(na); | ||
1565 | } | ||
1566 | spin_unlock(&dlm_node_addrs_spin); | ||
1567 | |||
1431 | return 0; | 1568 | return 0; |
1432 | } | 1569 | } |
1433 | 1570 | ||
@@ -1577,3 +1714,17 @@ fail_destroy: | |||
1577 | fail: | 1714 | fail: |
1578 | return error; | 1715 | return error; |
1579 | } | 1716 | } |
1717 | |||
1718 | void dlm_lowcomms_exit(void) | ||
1719 | { | ||
1720 | struct dlm_node_addr *na, *safe; | ||
1721 | |||
1722 | spin_lock(&dlm_node_addrs_spin); | ||
1723 | list_for_each_entry_safe(na, safe, &dlm_node_addrs, list) { | ||
1724 | list_del(&na->list); | ||
1725 | while (na->addr_count--) | ||
1726 | kfree(na->addr[na->addr_count]); | ||
1727 | kfree(na); | ||
1728 | } | ||
1729 | spin_unlock(&dlm_node_addrs_spin); | ||
1730 | } | ||
diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h index 1311e6426287..67462e54fc2f 100644 --- a/fs/dlm/lowcomms.h +++ b/fs/dlm/lowcomms.h | |||
@@ -16,10 +16,12 @@ | |||
16 | 16 | ||
17 | int dlm_lowcomms_start(void); | 17 | int dlm_lowcomms_start(void); |
18 | void dlm_lowcomms_stop(void); | 18 | void dlm_lowcomms_stop(void); |
19 | void dlm_lowcomms_exit(void); | ||
19 | int dlm_lowcomms_close(int nodeid); | 20 | int dlm_lowcomms_close(int nodeid); |
20 | void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc); | 21 | void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc); |
21 | void dlm_lowcomms_commit_buffer(void *mh); | 22 | void dlm_lowcomms_commit_buffer(void *mh); |
22 | int dlm_lowcomms_connect_node(int nodeid); | 23 | int dlm_lowcomms_connect_node(int nodeid); |
24 | int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len); | ||
23 | 25 | ||
24 | #endif /* __LOWCOMMS_DOT_H__ */ | 26 | #endif /* __LOWCOMMS_DOT_H__ */ |
25 | 27 | ||
diff --git a/fs/dlm/main.c b/fs/dlm/main.c index 5a59efa0bb46..079c0bd71ab7 100644 --- a/fs/dlm/main.c +++ b/fs/dlm/main.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "user.h" | 17 | #include "user.h" |
18 | #include "memory.h" | 18 | #include "memory.h" |
19 | #include "config.h" | 19 | #include "config.h" |
20 | #include "lowcomms.h" | ||
20 | 21 | ||
21 | static int __init init_dlm(void) | 22 | static int __init init_dlm(void) |
22 | { | 23 | { |
@@ -78,6 +79,7 @@ static void __exit exit_dlm(void) | |||
78 | dlm_config_exit(); | 79 | dlm_config_exit(); |
79 | dlm_memory_exit(); | 80 | dlm_memory_exit(); |
80 | dlm_lockspace_exit(); | 81 | dlm_lockspace_exit(); |
82 | dlm_lowcomms_exit(); | ||
81 | dlm_unregister_debugfs(); | 83 | dlm_unregister_debugfs(); |
82 | } | 84 | } |
83 | 85 | ||
diff --git a/fs/dlm/member.c b/fs/dlm/member.c index 862640a36d5c..476557b54921 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c | |||
@@ -616,13 +616,13 @@ int dlm_ls_stop(struct dlm_ls *ls) | |||
616 | down_write(&ls->ls_recv_active); | 616 | down_write(&ls->ls_recv_active); |
617 | 617 | ||
618 | /* | 618 | /* |
619 | * Abort any recovery that's in progress (see RECOVERY_STOP, | 619 | * Abort any recovery that's in progress (see RECOVER_STOP, |
620 | * dlm_recovery_stopped()) and tell any other threads running in the | 620 | * dlm_recovery_stopped()) and tell any other threads running in the |
621 | * dlm to quit any processing (see RUNNING, dlm_locking_stopped()). | 621 | * dlm to quit any processing (see RUNNING, dlm_locking_stopped()). |
622 | */ | 622 | */ |
623 | 623 | ||
624 | spin_lock(&ls->ls_recover_lock); | 624 | spin_lock(&ls->ls_recover_lock); |
625 | set_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); | 625 | set_bit(LSFL_RECOVER_STOP, &ls->ls_flags); |
626 | new = test_and_clear_bit(LSFL_RUNNING, &ls->ls_flags); | 626 | new = test_and_clear_bit(LSFL_RUNNING, &ls->ls_flags); |
627 | ls->ls_recover_seq++; | 627 | ls->ls_recover_seq++; |
628 | spin_unlock(&ls->ls_recover_lock); | 628 | spin_unlock(&ls->ls_recover_lock); |
@@ -642,12 +642,16 @@ int dlm_ls_stop(struct dlm_ls *ls) | |||
642 | * when recovery is complete. | 642 | * when recovery is complete. |
643 | */ | 643 | */ |
644 | 644 | ||
645 | if (new) | 645 | if (new) { |
646 | down_write(&ls->ls_in_recovery); | 646 | set_bit(LSFL_RECOVER_DOWN, &ls->ls_flags); |
647 | wake_up_process(ls->ls_recoverd_task); | ||
648 | wait_event(ls->ls_recover_lock_wait, | ||
649 | test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags)); | ||
650 | } | ||
647 | 651 | ||
648 | /* | 652 | /* |
649 | * The recoverd suspend/resume makes sure that dlm_recoverd (if | 653 | * The recoverd suspend/resume makes sure that dlm_recoverd (if |
650 | * running) has noticed RECOVERY_STOP above and quit processing the | 654 | * running) has noticed RECOVER_STOP above and quit processing the |
651 | * previous recovery. | 655 | * previous recovery. |
652 | */ | 656 | */ |
653 | 657 | ||
@@ -709,7 +713,8 @@ int dlm_ls_start(struct dlm_ls *ls) | |||
709 | kfree(rv_old); | 713 | kfree(rv_old); |
710 | } | 714 | } |
711 | 715 | ||
712 | dlm_recoverd_kick(ls); | 716 | set_bit(LSFL_RECOVER_WORK, &ls->ls_flags); |
717 | wake_up_process(ls->ls_recoverd_task); | ||
713 | return 0; | 718 | return 0; |
714 | 719 | ||
715 | fail: | 720 | fail: |
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index ef17e0169da1..60a327863b11 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include "dlm_internal.h" | 14 | #include "dlm_internal.h" |
15 | 15 | ||
16 | static uint32_t dlm_nl_seqnum; | 16 | static uint32_t dlm_nl_seqnum; |
17 | static uint32_t listener_nlpid; | 17 | static uint32_t listener_nlportid; |
18 | 18 | ||
19 | static struct genl_family family = { | 19 | static struct genl_family family = { |
20 | .id = GENL_ID_GENERATE, | 20 | .id = GENL_ID_GENERATE, |
@@ -64,13 +64,13 @@ static int send_data(struct sk_buff *skb) | |||
64 | return rv; | 64 | return rv; |
65 | } | 65 | } |
66 | 66 | ||
67 | return genlmsg_unicast(&init_net, skb, listener_nlpid); | 67 | return genlmsg_unicast(&init_net, skb, listener_nlportid); |
68 | } | 68 | } |
69 | 69 | ||
70 | static int user_cmd(struct sk_buff *skb, struct genl_info *info) | 70 | static int user_cmd(struct sk_buff *skb, struct genl_info *info) |
71 | { | 71 | { |
72 | listener_nlpid = info->snd_pid; | 72 | listener_nlportid = info->snd_portid; |
73 | printk("user_cmd nlpid %u\n", listener_nlpid); | 73 | printk("user_cmd nlpid %u\n", listener_nlportid); |
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 87f1a56eab32..9d61947d473a 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c | |||
@@ -581,7 +581,7 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) | |||
581 | 581 | ||
582 | spin_lock(&ls->ls_recover_lock); | 582 | spin_lock(&ls->ls_recover_lock); |
583 | status = ls->ls_recover_status; | 583 | status = ls->ls_recover_status; |
584 | stop = test_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); | 584 | stop = test_bit(LSFL_RECOVER_STOP, &ls->ls_flags); |
585 | seq = ls->ls_recover_seq; | 585 | seq = ls->ls_recover_seq; |
586 | spin_unlock(&ls->ls_recover_lock); | 586 | spin_unlock(&ls->ls_recover_lock); |
587 | 587 | ||
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 88ce65ff021e..32f9f8926ec3 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c | |||
@@ -41,6 +41,7 @@ static int enable_locking(struct dlm_ls *ls, uint64_t seq) | |||
41 | set_bit(LSFL_RUNNING, &ls->ls_flags); | 41 | set_bit(LSFL_RUNNING, &ls->ls_flags); |
42 | /* unblocks processes waiting to enter the dlm */ | 42 | /* unblocks processes waiting to enter the dlm */ |
43 | up_write(&ls->ls_in_recovery); | 43 | up_write(&ls->ls_in_recovery); |
44 | clear_bit(LSFL_RECOVER_LOCK, &ls->ls_flags); | ||
44 | error = 0; | 45 | error = 0; |
45 | } | 46 | } |
46 | spin_unlock(&ls->ls_recover_lock); | 47 | spin_unlock(&ls->ls_recover_lock); |
@@ -262,7 +263,7 @@ static void do_ls_recovery(struct dlm_ls *ls) | |||
262 | rv = ls->ls_recover_args; | 263 | rv = ls->ls_recover_args; |
263 | ls->ls_recover_args = NULL; | 264 | ls->ls_recover_args = NULL; |
264 | if (rv && ls->ls_recover_seq == rv->seq) | 265 | if (rv && ls->ls_recover_seq == rv->seq) |
265 | clear_bit(LSFL_RECOVERY_STOP, &ls->ls_flags); | 266 | clear_bit(LSFL_RECOVER_STOP, &ls->ls_flags); |
266 | spin_unlock(&ls->ls_recover_lock); | 267 | spin_unlock(&ls->ls_recover_lock); |
267 | 268 | ||
268 | if (rv) { | 269 | if (rv) { |
@@ -282,26 +283,34 @@ static int dlm_recoverd(void *arg) | |||
282 | return -1; | 283 | return -1; |
283 | } | 284 | } |
284 | 285 | ||
286 | down_write(&ls->ls_in_recovery); | ||
287 | set_bit(LSFL_RECOVER_LOCK, &ls->ls_flags); | ||
288 | wake_up(&ls->ls_recover_lock_wait); | ||
289 | |||
285 | while (!kthread_should_stop()) { | 290 | while (!kthread_should_stop()) { |
286 | set_current_state(TASK_INTERRUPTIBLE); | 291 | set_current_state(TASK_INTERRUPTIBLE); |
287 | if (!test_bit(LSFL_WORK, &ls->ls_flags)) | 292 | if (!test_bit(LSFL_RECOVER_WORK, &ls->ls_flags) && |
293 | !test_bit(LSFL_RECOVER_DOWN, &ls->ls_flags)) | ||
288 | schedule(); | 294 | schedule(); |
289 | set_current_state(TASK_RUNNING); | 295 | set_current_state(TASK_RUNNING); |
290 | 296 | ||
291 | if (test_and_clear_bit(LSFL_WORK, &ls->ls_flags)) | 297 | if (test_and_clear_bit(LSFL_RECOVER_DOWN, &ls->ls_flags)) { |
298 | down_write(&ls->ls_in_recovery); | ||
299 | set_bit(LSFL_RECOVER_LOCK, &ls->ls_flags); | ||
300 | wake_up(&ls->ls_recover_lock_wait); | ||
301 | } | ||
302 | |||
303 | if (test_and_clear_bit(LSFL_RECOVER_WORK, &ls->ls_flags)) | ||
292 | do_ls_recovery(ls); | 304 | do_ls_recovery(ls); |
293 | } | 305 | } |
294 | 306 | ||
307 | if (test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags)) | ||
308 | up_write(&ls->ls_in_recovery); | ||
309 | |||
295 | dlm_put_lockspace(ls); | 310 | dlm_put_lockspace(ls); |
296 | return 0; | 311 | return 0; |
297 | } | 312 | } |
298 | 313 | ||
299 | void dlm_recoverd_kick(struct dlm_ls *ls) | ||
300 | { | ||
301 | set_bit(LSFL_WORK, &ls->ls_flags); | ||
302 | wake_up_process(ls->ls_recoverd_task); | ||
303 | } | ||
304 | |||
305 | int dlm_recoverd_start(struct dlm_ls *ls) | 314 | int dlm_recoverd_start(struct dlm_ls *ls) |
306 | { | 315 | { |
307 | struct task_struct *p; | 316 | struct task_struct *p; |
diff --git a/fs/dlm/recoverd.h b/fs/dlm/recoverd.h index 866657c5d69d..8856079733fa 100644 --- a/fs/dlm/recoverd.h +++ b/fs/dlm/recoverd.h | |||
@@ -14,7 +14,6 @@ | |||
14 | #ifndef __RECOVERD_DOT_H__ | 14 | #ifndef __RECOVERD_DOT_H__ |
15 | #define __RECOVERD_DOT_H__ | 15 | #define __RECOVERD_DOT_H__ |
16 | 16 | ||
17 | void dlm_recoverd_kick(struct dlm_ls *ls); | ||
18 | void dlm_recoverd_stop(struct dlm_ls *ls); | 17 | void dlm_recoverd_stop(struct dlm_ls *ls); |
19 | int dlm_recoverd_start(struct dlm_ls *ls); | 18 | int dlm_recoverd_start(struct dlm_ls *ls); |
20 | void dlm_recoverd_suspend(struct dlm_ls *ls); | 19 | void dlm_recoverd_suspend(struct dlm_ls *ls); |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index eb4ed9ba3098..7ff49852b0cb 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -503,6 +503,13 @@ static ssize_t device_write(struct file *file, const char __user *buf, | |||
503 | #endif | 503 | #endif |
504 | return -EINVAL; | 504 | return -EINVAL; |
505 | 505 | ||
506 | #ifdef CONFIG_COMPAT | ||
507 | if (count > sizeof(struct dlm_write_request32) + DLM_RESNAME_MAXLEN) | ||
508 | #else | ||
509 | if (count > sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN) | ||
510 | #endif | ||
511 | return -EINVAL; | ||
512 | |||
506 | kbuf = kzalloc(count + 1, GFP_NOFS); | 513 | kbuf = kzalloc(count + 1, GFP_NOFS); |
507 | if (!kbuf) | 514 | if (!kbuf) |
508 | return -ENOMEM; | 515 | return -ENOMEM; |