Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dlm: add recovery callbacks

These new callbacks notify the dlm user about lock recovery.
GFS2, and possibly others, need to be aware of when the dlm
will be doing lock recovery for a failed lockspace member.

In the past, this coordination has been done between dlm and
file system daemons in userspace, which then direct their
kernel counterparts. These callbacks allow the same
coordination directly, and more simply.

Signed-off-by: David Teigland <teigland@redhat.com>

+336 -175
+74 -58
fs/dlm/config.c
··· 2 2 ******************************************************************************* 3 3 ** 4 4 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 5 - ** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. 5 + ** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. 6 6 ** 7 7 ** This copyrighted material is made available to anyone wishing to use, 8 8 ** modify, copy, or redistribute it subject to the terms and conditions ··· 17 17 #include <linux/slab.h> 18 18 #include <linux/in.h> 19 19 #include <linux/in6.h> 20 + #include <linux/dlmconstants.h> 20 21 #include <net/ipv6.h> 21 22 #include <net/sock.h> 22 23 ··· 37 36 static struct config_group *space_list; 38 37 static struct config_group *comm_list; 39 38 static struct dlm_comm *local_comm; 39 + static uint32_t dlm_comm_count; 40 40 41 41 struct dlm_clusters; 42 42 struct dlm_cluster; ··· 105 103 unsigned int cl_timewarn_cs; 106 104 unsigned int cl_waitwarn_us; 107 105 unsigned int cl_new_rsb_count; 106 + unsigned int cl_recover_callbacks; 107 + char cl_cluster_name[DLM_LOCKSPACE_LEN]; 108 108 }; 109 109 110 110 enum { ··· 122 118 CLUSTER_ATTR_TIMEWARN_CS, 123 119 CLUSTER_ATTR_WAITWARN_US, 124 120 CLUSTER_ATTR_NEW_RSB_COUNT, 121 + CLUSTER_ATTR_RECOVER_CALLBACKS, 122 + CLUSTER_ATTR_CLUSTER_NAME, 125 123 }; 126 124 127 125 struct cluster_attribute { 128 126 struct configfs_attribute attr; 129 127 ssize_t (*show)(struct dlm_cluster *, char *); 130 128 ssize_t (*store)(struct dlm_cluster *, const char *, size_t); 129 + }; 130 + 131 + static ssize_t cluster_cluster_name_read(struct dlm_cluster *cl, char *buf) 132 + { 133 + return sprintf(buf, "%s\n", cl->cl_cluster_name); 134 + } 135 + 136 + static ssize_t cluster_cluster_name_write(struct dlm_cluster *cl, 137 + const char *buf, size_t len) 138 + { 139 + strncpy(dlm_config.ci_cluster_name, buf, DLM_LOCKSPACE_LEN); 140 + strncpy(cl->cl_cluster_name, buf, DLM_LOCKSPACE_LEN); 141 + return len; 142 + } 143 + 144 + static struct cluster_attribute cluster_attr_cluster_name = { 145 + .attr = { .ca_owner = THIS_MODULE, 146 + .ca_name = "cluster_name", 147 + .ca_mode = S_IRUGO | S_IWUSR }, 148 + .show = cluster_cluster_name_read, 149 + .store = cluster_cluster_name_write, 131 150 }; 132 151 133 152 static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, ··· 198 171 CLUSTER_ATTR(timewarn_cs, 1); 199 172 CLUSTER_ATTR(waitwarn_us, 0); 200 173 CLUSTER_ATTR(new_rsb_count, 0); 174 + CLUSTER_ATTR(recover_callbacks, 0); 201 175 202 176 static struct configfs_attribute *cluster_attrs[] = { 203 177 [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, ··· 213 185 [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr, 214 186 [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr, 215 187 [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr, 188 + [CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks.attr, 189 + [CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name.attr, 216 190 NULL, 217 191 }; 218 192 ··· 323 293 324 294 struct dlm_comm { 325 295 struct config_item item; 296 + int seq; 326 297 int nodeid; 327 298 int local; 328 299 int addr_count; ··· 340 309 int nodeid; 341 310 int weight; 342 311 int new; 312 + int comm_seq; /* copy of cm->seq when nd->nodeid is set */ 343 313 }; 344 314 345 315 static struct configfs_group_operations clusters_ops = { ··· 487 455 cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs; 488 456 cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us; 489 457 cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count; 458 + cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks; 459 + memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name, 460 + DLM_LOCKSPACE_LEN); 490 461 491 462 space_list = &sps->ss_group; 492 463 comm_list = &cms->cs_group; ··· 593 558 return ERR_PTR(-ENOMEM); 594 559 595 560 config_item_init_type_name(&cm->item, name, &comm_type); 561 + 562 + cm->seq = dlm_comm_count++; 563 + if (!cm->seq) 564 + cm->seq = dlm_comm_count++; 565 + 596 566 cm->nodeid = -1; 597 567 cm->local = 0; 598 568 cm->addr_count = 0; ··· 841 801 static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf, 842 802 size_t len) 843 803 { 804 + uint32_t seq = 0; 844 805 nd->nodeid = simple_strtol(buf, NULL, 0); 806 + dlm_comm_seq(nd->nodeid, &seq); 807 + nd->comm_seq = seq; 845 808 return len; 846 809 } 847 810 ··· 951 908 } 952 909 953 910 /* caller must free mem */ 954 - int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, 955 - int **new_out, int *new_count_out) 911 + int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, 912 + int *count_out) 956 913 { 957 914 struct dlm_space *sp; 958 915 struct dlm_node *nd; 959 - int i = 0, rv = 0, ids_count = 0, new_count = 0; 960 - int *ids, *new; 916 + struct dlm_config_node *nodes, *node; 917 + int rv, count; 961 918 962 919 sp = get_space(lsname); 963 920 if (!sp) ··· 970 927 goto out; 971 928 } 972 929 973 - ids_count = sp->members_count; 930 + count = sp->members_count; 974 931 975 - ids = kcalloc(ids_count, sizeof(int), GFP_NOFS); 976 - if (!ids) { 932 + nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS); 933 + if (!nodes) { 977 934 rv = -ENOMEM; 978 935 goto out; 979 936 } 980 937 938 + node = nodes; 981 939 list_for_each_entry(nd, &sp->members, list) { 982 - ids[i++] = nd->nodeid; 983 - if (nd->new) 984 - new_count++; 940 + node->nodeid = nd->nodeid; 941 + node->weight = nd->weight; 942 + node->new = nd->new; 943 + node->comm_seq = nd->comm_seq; 944 + node++; 945 + 946 + nd->new = 0; 985 947 } 986 948 987 - if (ids_count != i) 988 - printk(KERN_ERR "dlm: bad nodeid count %d %d\n", ids_count, i); 989 - 990 - if (!new_count) 991 - goto out_ids; 992 - 993 - new = kcalloc(new_count, sizeof(int), GFP_NOFS); 994 - if (!new) { 995 - kfree(ids); 996 - rv = -ENOMEM; 997 - goto out; 998 - } 999 - 1000 - i = 0; 1001 - list_for_each_entry(nd, &sp->members, list) { 1002 - if (nd->new) { 1003 - new[i++] = nd->nodeid; 1004 - nd->new = 0; 1005 - } 1006 - } 1007 - *new_count_out = new_count; 1008 - *new_out = new; 1009 - 1010 - out_ids: 1011 - *ids_count_out = ids_count; 1012 - *ids_out = ids; 949 + *count_out = count; 950 + *nodes_out = nodes; 951 + rv = 0; 1013 952 out: 1014 953 mutex_unlock(&sp->members_lock); 1015 954 put_space(sp); 1016 955 return rv; 1017 956 } 1018 957 1019 - int dlm_node_weight(char *lsname, int nodeid) 958 + int dlm_comm_seq(int nodeid, uint32_t *seq) 1020 959 { 1021 - struct dlm_space *sp; 1022 - struct dlm_node *nd; 1023 - int w = -EEXIST; 1024 - 1025 - sp = get_space(lsname); 1026 - if (!sp) 1027 - goto out; 1028 - 1029 - mutex_lock(&sp->members_lock); 1030 - list_for_each_entry(nd, &sp->members, list) { 1031 - if (nd->nodeid != nodeid) 1032 - continue; 1033 - w = nd->weight; 1034 - break; 1035 - } 1036 - mutex_unlock(&sp->members_lock); 1037 - put_space(sp); 1038 - out: 1039 - return w; 960 + struct dlm_comm *cm = get_comm(nodeid, NULL); 961 + if (!cm) 962 + return -EEXIST; 963 + *seq = cm->seq; 964 + put_comm(cm); 965 + return 0; 1040 966 } 1041 967 1042 968 int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) ··· 1059 1047 #define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */ 1060 1048 #define DEFAULT_WAITWARN_US 0 1061 1049 #define DEFAULT_NEW_RSB_COUNT 128 1050 + #define DEFAULT_RECOVER_CALLBACKS 0 1051 + #define DEFAULT_CLUSTER_NAME "" 1062 1052 1063 1053 struct dlm_config_info dlm_config = { 1064 1054 .ci_tcp_port = DEFAULT_TCP_PORT, ··· 1074 1060 .ci_protocol = DEFAULT_PROTOCOL, 1075 1061 .ci_timewarn_cs = DEFAULT_TIMEWARN_CS, 1076 1062 .ci_waitwarn_us = DEFAULT_WAITWARN_US, 1077 - .ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT 1063 + .ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT, 1064 + .ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS, 1065 + .ci_cluster_name = DEFAULT_CLUSTER_NAME 1078 1066 }; 1079 1067
+13 -4
fs/dlm/config.h
··· 2 2 ******************************************************************************* 3 3 ** 4 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-2011 Red Hat, Inc. All rights reserved. 6 6 ** 7 7 ** This copyrighted material is made available to anyone wishing to use, 8 8 ** modify, copy, or redistribute it subject to the terms and conditions ··· 13 13 14 14 #ifndef __CONFIG_DOT_H__ 15 15 #define __CONFIG_DOT_H__ 16 + 17 + struct dlm_config_node { 18 + int nodeid; 19 + int weight; 20 + int new; 21 + uint32_t comm_seq; 22 + }; 16 23 17 24 #define DLM_MAX_ADDR_COUNT 3 18 25 ··· 36 29 int ci_timewarn_cs; 37 30 int ci_waitwarn_us; 38 31 int ci_new_rsb_count; 32 + int ci_recover_callbacks; 33 + char ci_cluster_name[DLM_LOCKSPACE_LEN]; 39 34 }; 40 35 41 36 extern struct dlm_config_info dlm_config; 42 37 43 38 int dlm_config_init(void); 44 39 void dlm_config_exit(void); 45 - int dlm_node_weight(char *lsname, int nodeid); 46 - int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, 47 - int **new_out, int *new_count_out); 40 + int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, 41 + int *count_out); 42 + int dlm_comm_seq(int nodeid, uint32_t *seq); 48 43 int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr); 49 44 int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid); 50 45 int dlm_our_nodeid(void);
+7 -14
fs/dlm/dlm_internal.h
··· 2 2 ******************************************************************************* 3 3 ** 4 4 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 5 - ** Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved. 5 + ** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. 6 6 ** 7 7 ** This copyrighted material is made available to anyone wishing to use, 8 8 ** modify, copy, or redistribute it subject to the terms and conditions ··· 119 119 int weight; 120 120 int slot; 121 121 int slot_prev; 122 + int comm_seq; 122 123 uint32_t generation; 123 - }; 124 - 125 - /* 126 - * low nodeid saves array of these in ls_slots 127 - */ 128 - 129 - struct dlm_slot { 130 - int nodeid; 131 - int slot; 132 124 }; 133 125 134 126 /* ··· 129 137 130 138 struct dlm_recover { 131 139 struct list_head list; 132 - int *nodeids; /* nodeids of all members */ 133 - int node_count; 134 - int *new; /* nodeids of new members */ 135 - int new_count; 140 + struct dlm_config_node *nodes; 141 + int nodes_count; 136 142 uint64_t seq; 137 143 }; 138 144 ··· 573 583 574 584 struct list_head ls_root_list; /* root resources */ 575 585 struct rw_semaphore ls_root_sem; /* protect root_list */ 586 + 587 + const struct dlm_lockspace_ops *ls_ops; 588 + void *ls_ops_arg; 576 589 577 590 int ls_namelen; 578 591 char ls_name[1];
+35 -8
fs/dlm/lockspace.c
··· 2 2 ******************************************************************************* 3 3 ** 4 4 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 5 - ** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. 5 + ** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. 6 6 ** 7 7 ** This copyrighted material is made available to anyone wishing to use, 8 8 ** modify, copy, or redistribute it subject to the terms and conditions ··· 386 386 dlm_lowcomms_stop(); 387 387 } 388 388 389 - static int new_lockspace(const char *name, int namelen, void **lockspace, 390 - uint32_t flags, int lvblen) 389 + static int new_lockspace(const char *name, const char *cluster, 390 + uint32_t flags, int lvblen, 391 + const struct dlm_lockspace_ops *ops, void *ops_arg, 392 + int *ops_result, dlm_lockspace_t **lockspace) 391 393 { 392 394 struct dlm_ls *ls; 393 395 int i, size, error; 394 396 int do_unreg = 0; 397 + int namelen = strlen(name); 395 398 396 399 if (namelen > DLM_LOCKSPACE_LEN) 397 400 return -EINVAL; ··· 406 403 return -EINVAL; 407 404 408 405 if (!dlm_user_daemon_available()) { 409 - module_put(THIS_MODULE); 410 - return -EUNATCH; 406 + log_print("dlm user daemon not available"); 407 + error = -EUNATCH; 408 + goto out; 409 + } 410 + 411 + if (ops && ops_result) { 412 + if (!dlm_config.ci_recover_callbacks) 413 + *ops_result = -EOPNOTSUPP; 414 + else 415 + *ops_result = 0; 416 + } 417 + 418 + if (dlm_config.ci_recover_callbacks && cluster && 419 + strncmp(cluster, dlm_config.ci_cluster_name, DLM_LOCKSPACE_LEN)) { 420 + log_print("dlm cluster name %s mismatch %s", 421 + dlm_config.ci_cluster_name, cluster); 422 + error = -EBADR; 423 + goto out; 411 424 } 412 425 413 426 error = 0; ··· 460 441 ls->ls_count = 0; 461 442 ls->ls_flags = 0; 462 443 ls->ls_scan_time = jiffies; 444 + 445 + if (ops && dlm_config.ci_recover_callbacks) { 446 + ls->ls_ops = ops; 447 + ls->ls_ops_arg = ops_arg; 448 + } 463 449 464 450 if (flags & DLM_LSFL_TIMEWARN) 465 451 set_bit(LSFL_TIMEWARN, &ls->ls_flags); ··· 643 619 return error; 644 620 } 645 621 646 - int dlm_new_lockspace(const char *name, int namelen, void **lockspace, 647 - uint32_t flags, int lvblen) 622 + int dlm_new_lockspace(const char *name, const char *cluster, 623 + uint32_t flags, int lvblen, 624 + const struct dlm_lockspace_ops *ops, void *ops_arg, 625 + int *ops_result, dlm_lockspace_t **lockspace) 648 626 { 649 627 int error = 0; 650 628 ··· 656 630 if (error) 657 631 goto out; 658 632 659 - error = new_lockspace(name, namelen, lockspace, flags, lvblen); 633 + error = new_lockspace(name, cluster, flags, lvblen, ops, ops_arg, 634 + ops_result, lockspace); 660 635 if (!error) 661 636 ls_count++; 662 637 if (error > 0)
+127 -74
fs/dlm/member.c
··· 1 1 /****************************************************************************** 2 2 ******************************************************************************* 3 3 ** 4 - ** Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved. 4 + ** Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved. 5 5 ** 6 6 ** This copyrighted material is made available to anyone wishing to use, 7 7 ** modify, copy, or redistribute it subject to the terms and conditions ··· 27 27 } 28 28 29 29 void dlm_slot_save(struct dlm_ls *ls, struct dlm_rcom *rc, 30 - struct dlm_member *memb) 30 + struct dlm_member *memb) 31 31 { 32 32 struct rcom_config *rf = (struct rcom_config *)rc->rc_buf; 33 33 ··· 317 317 } 318 318 } 319 319 320 - static int dlm_add_member(struct dlm_ls *ls, int nodeid) 320 + static int dlm_add_member(struct dlm_ls *ls, struct dlm_config_node *node) 321 321 { 322 322 struct dlm_member *memb; 323 - int w, error; 323 + int error; 324 324 325 325 memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS); 326 326 if (!memb) 327 327 return -ENOMEM; 328 328 329 - w = dlm_node_weight(ls->ls_name, nodeid); 330 - if (w < 0) { 331 - kfree(memb); 332 - return w; 333 - } 334 - 335 - error = dlm_lowcomms_connect_node(nodeid); 329 + error = dlm_lowcomms_connect_node(node->nodeid); 336 330 if (error < 0) { 337 331 kfree(memb); 338 332 return error; 339 333 } 340 334 341 - memb->nodeid = nodeid; 342 - memb->weight = w; 335 + memb->nodeid = node->nodeid; 336 + memb->weight = node->weight; 337 + memb->comm_seq = node->comm_seq; 343 338 add_ordered_member(ls, memb); 344 339 ls->ls_num_nodes++; 345 340 return 0; 346 341 } 347 342 348 - static void dlm_remove_member(struct dlm_ls *ls, struct dlm_member *memb) 343 + static struct dlm_member *find_memb(struct list_head *head, int nodeid) 349 344 { 350 - list_move(&memb->list, &ls->ls_nodes_gone); 351 - ls->ls_num_nodes--; 345 + struct dlm_member *memb; 346 + 347 + list_for_each_entry(memb, head, list) { 348 + if (memb->nodeid == nodeid) 349 + return memb; 350 + } 351 + return NULL; 352 352 } 353 353 354 354 int dlm_is_member(struct dlm_ls *ls, int nodeid) 355 355 { 356 - struct dlm_member *memb; 357 - 358 - list_for_each_entry(memb, &ls->ls_nodes, list) { 359 - if (memb->nodeid == nodeid) 360 - return 1; 361 - } 356 + if (find_memb(&ls->ls_nodes, nodeid)) 357 + return 1; 362 358 return 0; 363 359 } 364 360 365 361 int dlm_is_removed(struct dlm_ls *ls, int nodeid) 366 362 { 367 - struct dlm_member *memb; 368 - 369 - list_for_each_entry(memb, &ls->ls_nodes_gone, list) { 370 - if (memb->nodeid == nodeid) 371 - return 1; 372 - } 363 + if (find_memb(&ls->ls_nodes_gone, nodeid)) 364 + return 1; 373 365 return 0; 374 366 } 375 367 ··· 452 460 return error; 453 461 } 454 462 463 + static void dlm_lsop_recover_prep(struct dlm_ls *ls) 464 + { 465 + if (!ls->ls_ops || !ls->ls_ops->recover_prep) 466 + return; 467 + ls->ls_ops->recover_prep(ls->ls_ops_arg); 468 + } 469 + 470 + static void dlm_lsop_recover_slot(struct dlm_ls *ls, struct dlm_member *memb) 471 + { 472 + struct dlm_slot slot; 473 + uint32_t seq; 474 + int error; 475 + 476 + if (!ls->ls_ops || !ls->ls_ops->recover_slot) 477 + return; 478 + 479 + /* if there is no comms connection with this node 480 + or the present comms connection is newer 481 + than the one when this member was added, then 482 + we consider the node to have failed (versus 483 + being removed due to dlm_release_lockspace) */ 484 + 485 + error = dlm_comm_seq(memb->nodeid, &seq); 486 + 487 + if (!error && seq == memb->comm_seq) 488 + return; 489 + 490 + slot.nodeid = memb->nodeid; 491 + slot.slot = memb->slot; 492 + 493 + ls->ls_ops->recover_slot(ls->ls_ops_arg, &slot); 494 + } 495 + 496 + void dlm_lsop_recover_done(struct dlm_ls *ls) 497 + { 498 + struct dlm_member *memb; 499 + struct dlm_slot *slots; 500 + int i, num; 501 + 502 + if (!ls->ls_ops || !ls->ls_ops->recover_done) 503 + return; 504 + 505 + num = ls->ls_num_nodes; 506 + 507 + slots = kzalloc(num * sizeof(struct dlm_slot), GFP_KERNEL); 508 + if (!slots) 509 + return; 510 + 511 + i = 0; 512 + list_for_each_entry(memb, &ls->ls_nodes, list) { 513 + if (i == num) { 514 + log_error(ls, "dlm_lsop_recover_done bad num %d", num); 515 + goto out; 516 + } 517 + slots[i].nodeid = memb->nodeid; 518 + slots[i].slot = memb->slot; 519 + i++; 520 + } 521 + 522 + ls->ls_ops->recover_done(ls->ls_ops_arg, slots, num, 523 + ls->ls_slot, ls->ls_generation); 524 + out: 525 + kfree(slots); 526 + } 527 + 528 + static struct dlm_config_node *find_config_node(struct dlm_recover *rv, 529 + int nodeid) 530 + { 531 + int i; 532 + 533 + for (i = 0; i < rv->nodes_count; i++) { 534 + if (rv->nodes[i].nodeid == nodeid) 535 + return &rv->nodes[i]; 536 + } 537 + return NULL; 538 + } 539 + 455 540 int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) 456 541 { 457 542 struct dlm_member *memb, *safe; 458 - int i, error, found, pos = 0, neg = 0, low = -1; 543 + struct dlm_config_node *node; 544 + int i, error, neg = 0, low = -1; 459 545 460 546 /* previously removed members that we've not finished removing need to 461 547 count as a negative change so the "neg" recovery steps will happen */ ··· 546 476 /* move departed members from ls_nodes to ls_nodes_gone */ 547 477 548 478 list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) { 549 - found = 0; 550 - for (i = 0; i < rv->node_count; i++) { 551 - if (memb->nodeid == rv->nodeids[i]) { 552 - found = 1; 553 - break; 554 - } 555 - } 556 - 557 - if (!found) { 558 - neg++; 559 - dlm_remove_member(ls, memb); 560 - log_debug(ls, "remove member %d", memb->nodeid); 561 - } 562 - } 563 - 564 - /* Add an entry to ls_nodes_gone for members that were removed and 565 - then added again, so that previous state for these nodes will be 566 - cleared during recovery. */ 567 - 568 - for (i = 0; i < rv->new_count; i++) { 569 - if (!dlm_is_member(ls, rv->new[i])) 479 + node = find_config_node(rv, memb->nodeid); 480 + if (node && !node->new) 570 481 continue; 571 - log_debug(ls, "new nodeid %d is a re-added member", rv->new[i]); 572 482 573 - memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS); 574 - if (!memb) 575 - return -ENOMEM; 576 - memb->nodeid = rv->new[i]; 577 - list_add_tail(&memb->list, &ls->ls_nodes_gone); 483 + if (!node) { 484 + log_debug(ls, "remove member %d", memb->nodeid); 485 + } else { 486 + /* removed and re-added */ 487 + log_debug(ls, "remove member %d comm_seq %u %u", 488 + memb->nodeid, memb->comm_seq, node->comm_seq); 489 + } 490 + 578 491 neg++; 492 + list_move(&memb->list, &ls->ls_nodes_gone); 493 + ls->ls_num_nodes--; 494 + dlm_lsop_recover_slot(ls, memb); 579 495 } 580 496 581 497 /* add new members to ls_nodes */ 582 498 583 - for (i = 0; i < rv->node_count; i++) { 584 - if (dlm_is_member(ls, rv->nodeids[i])) 499 + for (i = 0; i < rv->nodes_count; i++) { 500 + node = &rv->nodes[i]; 501 + if (dlm_is_member(ls, node->nodeid)) 585 502 continue; 586 - dlm_add_member(ls, rv->nodeids[i]); 587 - pos++; 588 - log_debug(ls, "add member %d", rv->nodeids[i]); 503 + dlm_add_member(ls, node); 504 + log_debug(ls, "add member %d", node->nodeid); 589 505 } 590 506 591 507 list_for_each_entry(memb, &ls->ls_nodes, list) { ··· 665 609 666 610 if (!ls->ls_recover_begin) 667 611 ls->ls_recover_begin = jiffies; 612 + 613 + dlm_lsop_recover_prep(ls); 668 614 return 0; 669 615 } 670 616 671 617 int dlm_ls_start(struct dlm_ls *ls) 672 618 { 673 619 struct dlm_recover *rv = NULL, *rv_old; 674 - int *ids = NULL, *new = NULL; 675 - int error, ids_count = 0, new_count = 0; 620 + struct dlm_config_node *nodes; 621 + int error, count; 676 622 677 623 rv = kzalloc(sizeof(struct dlm_recover), GFP_NOFS); 678 624 if (!rv) 679 625 return -ENOMEM; 680 626 681 - error = dlm_nodeid_list(ls->ls_name, &ids, &ids_count, 682 - &new, &new_count); 627 + error = dlm_config_nodes(ls->ls_name, &nodes, &count); 683 628 if (error < 0) 684 629 goto fail; 685 630 ··· 695 638 goto fail; 696 639 } 697 640 698 - rv->nodeids = ids; 699 - rv->node_count = ids_count; 700 - rv->new = new; 701 - rv->new_count = new_count; 641 + rv->nodes = nodes; 642 + rv->nodes_count = count; 702 643 rv->seq = ++ls->ls_recover_seq; 703 644 rv_old = ls->ls_recover_args; 704 645 ls->ls_recover_args = rv; ··· 704 649 705 650 if (rv_old) { 706 651 log_error(ls, "unused recovery %llx %d", 707 - (unsigned long long)rv_old->seq, rv_old->node_count); 708 - kfree(rv_old->nodeids); 709 - kfree(rv_old->new); 652 + (unsigned long long)rv_old->seq, rv_old->nodes_count); 653 + kfree(rv_old->nodes); 710 654 kfree(rv_old); 711 655 } 712 656 ··· 714 660 715 661 fail: 716 662 kfree(rv); 717 - kfree(ids); 718 - kfree(new); 663 + kfree(nodes); 719 664 return error; 720 665 } 721 666
+2 -1
fs/dlm/member.h
··· 1 1 /****************************************************************************** 2 2 ******************************************************************************* 3 3 ** 4 - ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. 4 + ** Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved. 5 5 ** 6 6 ** This copyrighted material is made available to anyone wishing to use, 7 7 ** modify, copy, or redistribute it subject to the terms and conditions ··· 27 27 int dlm_slots_copy_in(struct dlm_ls *ls); 28 28 int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size, 29 29 struct dlm_slot **slots_out, uint32_t *gen_out); 30 + void dlm_lsop_recover_done(struct dlm_ls *ls); 30 31 31 32 #endif /* __MEMBER_DOT_H__ */ 32 33
+5 -5
fs/dlm/recoverd.c
··· 2 2 ******************************************************************************* 3 3 ** 4 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-2011 Red Hat, Inc. All rights reserved. 6 6 ** 7 7 ** This copyrighted material is made available to anyone wishing to use, 8 8 ** modify, copy, or redistribute it subject to the terms and conditions ··· 227 227 228 228 dlm_grant_after_purge(ls); 229 229 230 - log_debug(ls, "dlm_recover %llx done: %u ms", 231 - (unsigned long long)rv->seq, 230 + log_debug(ls, "dlm_recover %llx generation %u done: %u ms", 231 + (unsigned long long)rv->seq, ls->ls_generation, 232 232 jiffies_to_msecs(jiffies - start)); 233 233 mutex_unlock(&ls->ls_recoverd_active); 234 234 235 + dlm_lsop_recover_done(ls); 235 236 return 0; 236 237 237 238 fail: ··· 260 259 261 260 if (rv) { 262 261 ls_recover(ls, rv); 263 - kfree(rv->nodeids); 264 - kfree(rv->new); 262 + kfree(rv->nodes); 265 263 kfree(rv); 266 264 } 267 265 }
+3 -2
fs/dlm/user.c
··· 392 392 if (!capable(CAP_SYS_ADMIN)) 393 393 return -EPERM; 394 394 395 - error = dlm_new_lockspace(params->name, strlen(params->name), 396 - &lockspace, params->flags, DLM_USER_LVB_LEN); 395 + error = dlm_new_lockspace(params->name, NULL, params->flags, 396 + DLM_USER_LVB_LEN, NULL, NULL, NULL, 397 + &lockspace); 397 398 if (error) 398 399 return error; 399 400
+2 -2
fs/gfs2/lock_dlm.c
··· 195 195 return -EINVAL; 196 196 } 197 197 198 - error = dlm_new_lockspace(fsname, strlen(fsname), &ls->ls_dlm, 198 + error = dlm_new_lockspace(fsname, NULL, 199 199 DLM_LSFL_FS | DLM_LSFL_NEWEXCL | 200 200 (ls->ls_nodir ? DLM_LSFL_NODIR : 0), 201 - GDLM_LVB_SIZE); 201 + GDLM_LVB_SIZE, NULL, NULL, NULL, &ls->ls_dlm); 202 202 if (error) 203 203 printk(KERN_ERR "dlm_new_lockspace error %d", error); 204 204
+2 -2
fs/ocfs2/stack_user.c
··· 827 827 goto out; 828 828 } 829 829 830 - rc = dlm_new_lockspace(conn->cc_name, strlen(conn->cc_name), 831 - &fsdlm, DLM_LSFL_FS, DLM_LVB_LEN); 830 + rc = dlm_new_lockspace(conn->cc_name, NULL, DLM_LSFL_FS, DLM_LVB_LEN, 831 + NULL, NULL, NULL, &fsdlm); 832 832 if (rc) { 833 833 ocfs2_live_connection_drop(control); 834 834 goto out;
+66 -5
include/linux/dlm.h
··· 2 2 ******************************************************************************* 3 3 ** 4 4 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 5 - ** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. 5 + ** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. 6 6 ** 7 7 ** This copyrighted material is made available to anyone wishing to use, 8 8 ** modify, copy, or redistribute it subject to the terms and conditions ··· 74 74 75 75 #ifdef __KERNEL__ 76 76 77 + struct dlm_slot { 78 + int nodeid; /* 1 to MAX_INT */ 79 + int slot; /* 1 to MAX_INT */ 80 + }; 81 + 82 + /* 83 + * recover_prep: called before the dlm begins lock recovery. 84 + * Notfies lockspace user that locks from failed members will be granted. 85 + * recover_slot: called after recover_prep and before recover_done. 86 + * Identifies a failed lockspace member. 87 + * recover_done: called after the dlm completes lock recovery. 88 + * Identifies lockspace members and lockspace generation number. 89 + */ 90 + 91 + struct dlm_lockspace_ops { 92 + void (*recover_prep) (void *ops_arg); 93 + void (*recover_slot) (void *ops_arg, struct dlm_slot *slot); 94 + void (*recover_done) (void *ops_arg, struct dlm_slot *slots, 95 + int num_slots, int our_slot, uint32_t generation); 96 + }; 97 + 77 98 /* 78 99 * dlm_new_lockspace 79 100 * 80 - * Starts a lockspace with the given name. If the named lockspace exists in 81 - * the cluster, the calling node joins it. 101 + * Create/join a lockspace. 102 + * 103 + * name: lockspace name, null terminated, up to DLM_LOCKSPACE_LEN (not 104 + * including terminating null). 105 + * 106 + * cluster: cluster name, null terminated, up to DLM_LOCKSPACE_LEN (not 107 + * including terminating null). Optional. When cluster is null, it 108 + * is not used. When set, dlm_new_lockspace() returns -EBADR if cluster 109 + * is not equal to the dlm cluster name. 110 + * 111 + * flags: 112 + * DLM_LSFL_NODIR 113 + * The dlm should not use a resource directory, but statically assign 114 + * resource mastery to nodes based on the name hash that is otherwise 115 + * used to select the directory node. Must be the same on all nodes. 116 + * DLM_LSFL_TIMEWARN 117 + * The dlm should emit netlink messages if locks have been waiting 118 + * for a configurable amount of time. (Unused.) 119 + * DLM_LSFL_FS 120 + * The lockspace user is in the kernel (i.e. filesystem). Enables 121 + * direct bast/cast callbacks. 122 + * DLM_LSFL_NEWEXCL 123 + * dlm_new_lockspace() should return -EEXIST if the lockspace exists. 124 + * 125 + * lvblen: length of lvb in bytes. Must be multiple of 8. 126 + * dlm_new_lockspace() returns an error if this does not match 127 + * what other nodes are using. 128 + * 129 + * ops: callbacks that indicate lockspace recovery points so the 130 + * caller can coordinate its recovery and know lockspace members. 131 + * This is only used by the initial dlm_new_lockspace() call. 132 + * Optional. 133 + * 134 + * ops_arg: arg for ops callbacks. 135 + * 136 + * ops_result: tells caller if the ops callbacks (if provided) will 137 + * be used or not. 0: will be used, -EXXX will not be used. 138 + * -EOPNOTSUPP: the dlm does not have recovery_callbacks enabled. 139 + * 140 + * lockspace: handle for dlm functions 82 141 */ 83 142 84 - int dlm_new_lockspace(const char *name, int namelen, 85 - dlm_lockspace_t **lockspace, uint32_t flags, int lvblen); 143 + int dlm_new_lockspace(const char *name, const char *cluster, 144 + uint32_t flags, int lvblen, 145 + const struct dlm_lockspace_ops *ops, void *ops_arg, 146 + int *ops_result, dlm_lockspace_t **lockspace); 86 147 87 148 /* 88 149 * dlm_release_lockspace