diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 17:55:55 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 17:55:55 -0500 |
| commit | 49d41bae46f15da528ef9848fd7c9d38582aa8e9 (patch) | |
| tree | 76907a9a5066642a32cb238ef8d8367fc612d064 /fs/dlm | |
| parent | 7b3480f8b701170c046e1ed362946f5f0d005e13 (diff) | |
| parent | 60f98d1839376d30e13f3e452dce2433fad3060e (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm:
dlm: add recovery callbacks
dlm: add node slots and generation
dlm: move recovery barrier calls
dlm: convert rsb list to rb_tree
Diffstat (limited to 'fs/dlm')
| -rw-r--r-- | fs/dlm/config.c | 130 | ||||
| -rw-r--r-- | fs/dlm/config.h | 17 | ||||
| -rw-r--r-- | fs/dlm/debug_fs.c | 28 | ||||
| -rw-r--r-- | fs/dlm/dir.c | 1 | ||||
| -rw-r--r-- | fs/dlm/dlm_internal.h | 60 | ||||
| -rw-r--r-- | fs/dlm/lock.c | 87 | ||||
| -rw-r--r-- | fs/dlm/lockspace.c | 71 | ||||
| -rw-r--r-- | fs/dlm/member.c | 486 | ||||
| -rw-r--r-- | fs/dlm/member.h | 10 | ||||
| -rw-r--r-- | fs/dlm/rcom.c | 99 | ||||
| -rw-r--r-- | fs/dlm/rcom.h | 2 | ||||
| -rw-r--r-- | fs/dlm/recover.c | 87 | ||||
| -rw-r--r-- | fs/dlm/recoverd.c | 53 | ||||
| -rw-r--r-- | fs/dlm/user.c | 5 |
14 files changed, 873 insertions, 263 deletions
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 6cf72fcc0d0c..e7e327d43fa5 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.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-2008 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2011 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 |
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/in.h> | 18 | #include <linux/in.h> |
| 19 | #include <linux/in6.h> | 19 | #include <linux/in6.h> |
| 20 | #include <linux/dlmconstants.h> | ||
| 20 | #include <net/ipv6.h> | 21 | #include <net/ipv6.h> |
| 21 | #include <net/sock.h> | 22 | #include <net/sock.h> |
| 22 | 23 | ||
| @@ -36,6 +37,7 @@ | |||
| 36 | static struct config_group *space_list; | 37 | static struct config_group *space_list; |
| 37 | static struct config_group *comm_list; | 38 | static struct config_group *comm_list; |
| 38 | static struct dlm_comm *local_comm; | 39 | static struct dlm_comm *local_comm; |
| 40 | static uint32_t dlm_comm_count; | ||
| 39 | 41 | ||
| 40 | struct dlm_clusters; | 42 | struct dlm_clusters; |
| 41 | struct dlm_cluster; | 43 | struct dlm_cluster; |
| @@ -103,6 +105,8 @@ struct dlm_cluster { | |||
| 103 | unsigned int cl_timewarn_cs; | 105 | unsigned int cl_timewarn_cs; |
| 104 | unsigned int cl_waitwarn_us; | 106 | unsigned int cl_waitwarn_us; |
| 105 | unsigned int cl_new_rsb_count; | 107 | unsigned int cl_new_rsb_count; |
| 108 | unsigned int cl_recover_callbacks; | ||
| 109 | char cl_cluster_name[DLM_LOCKSPACE_LEN]; | ||
| 106 | }; | 110 | }; |
| 107 | 111 | ||
| 108 | enum { | 112 | enum { |
| @@ -118,6 +122,8 @@ enum { | |||
| 118 | CLUSTER_ATTR_TIMEWARN_CS, | 122 | CLUSTER_ATTR_TIMEWARN_CS, |
| 119 | CLUSTER_ATTR_WAITWARN_US, | 123 | CLUSTER_ATTR_WAITWARN_US, |
| 120 | CLUSTER_ATTR_NEW_RSB_COUNT, | 124 | CLUSTER_ATTR_NEW_RSB_COUNT, |
| 125 | CLUSTER_ATTR_RECOVER_CALLBACKS, | ||
| 126 | CLUSTER_ATTR_CLUSTER_NAME, | ||
| 121 | }; | 127 | }; |
| 122 | 128 | ||
| 123 | struct cluster_attribute { | 129 | struct cluster_attribute { |
| @@ -126,6 +132,27 @@ struct cluster_attribute { | |||
| 126 | ssize_t (*store)(struct dlm_cluster *, const char *, size_t); | 132 | ssize_t (*store)(struct dlm_cluster *, const char *, size_t); |
| 127 | }; | 133 | }; |
| 128 | 134 | ||
| 135 | static ssize_t cluster_cluster_name_read(struct dlm_cluster *cl, char *buf) | ||
| 136 | { | ||
| 137 | return sprintf(buf, "%s\n", cl->cl_cluster_name); | ||
| 138 | } | ||
| 139 | |||
| 140 | static ssize_t cluster_cluster_name_write(struct dlm_cluster *cl, | ||
| 141 | const char *buf, size_t len) | ||
| 142 | { | ||
| 143 | strncpy(dlm_config.ci_cluster_name, buf, DLM_LOCKSPACE_LEN); | ||
| 144 | strncpy(cl->cl_cluster_name, buf, DLM_LOCKSPACE_LEN); | ||
| 145 | return len; | ||
| 146 | } | ||
| 147 | |||
| 148 | static struct cluster_attribute cluster_attr_cluster_name = { | ||
| 149 | .attr = { .ca_owner = THIS_MODULE, | ||
| 150 | .ca_name = "cluster_name", | ||
| 151 | .ca_mode = S_IRUGO | S_IWUSR }, | ||
| 152 | .show = cluster_cluster_name_read, | ||
| 153 | .store = cluster_cluster_name_write, | ||
| 154 | }; | ||
| 155 | |||
| 129 | static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, | 156 | static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, |
| 130 | int *info_field, int check_zero, | 157 | int *info_field, int check_zero, |
| 131 | const char *buf, size_t len) | 158 | const char *buf, size_t len) |
| @@ -171,6 +198,7 @@ CLUSTER_ATTR(protocol, 0); | |||
| 171 | CLUSTER_ATTR(timewarn_cs, 1); | 198 | CLUSTER_ATTR(timewarn_cs, 1); |
| 172 | CLUSTER_ATTR(waitwarn_us, 0); | 199 | CLUSTER_ATTR(waitwarn_us, 0); |
| 173 | CLUSTER_ATTR(new_rsb_count, 0); | 200 | CLUSTER_ATTR(new_rsb_count, 0); |
| 201 | CLUSTER_ATTR(recover_callbacks, 0); | ||
| 174 | 202 | ||
| 175 | static struct configfs_attribute *cluster_attrs[] = { | 203 | static struct configfs_attribute *cluster_attrs[] = { |
| 176 | [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, | 204 | [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, |
| @@ -185,6 +213,8 @@ static struct configfs_attribute *cluster_attrs[] = { | |||
| 185 | [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr, | 213 | [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr, |
| 186 | [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr, | 214 | [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr, |
| 187 | [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr, | 215 | [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr, |
| 216 | [CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks.attr, | ||
| 217 | [CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name.attr, | ||
| 188 | NULL, | 218 | NULL, |
| 189 | }; | 219 | }; |
| 190 | 220 | ||
| @@ -293,6 +323,7 @@ struct dlm_comms { | |||
| 293 | 323 | ||
| 294 | struct dlm_comm { | 324 | struct dlm_comm { |
| 295 | struct config_item item; | 325 | struct config_item item; |
| 326 | int seq; | ||
| 296 | int nodeid; | 327 | int nodeid; |
| 297 | int local; | 328 | int local; |
| 298 | int addr_count; | 329 | int addr_count; |
| @@ -309,6 +340,7 @@ struct dlm_node { | |||
| 309 | int nodeid; | 340 | int nodeid; |
| 310 | int weight; | 341 | int weight; |
| 311 | int new; | 342 | int new; |
| 343 | int comm_seq; /* copy of cm->seq when nd->nodeid is set */ | ||
| 312 | }; | 344 | }; |
| 313 | 345 | ||
| 314 | static struct configfs_group_operations clusters_ops = { | 346 | static struct configfs_group_operations clusters_ops = { |
| @@ -455,6 +487,9 @@ static struct config_group *make_cluster(struct config_group *g, | |||
| 455 | cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs; | 487 | cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs; |
| 456 | cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us; | 488 | cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us; |
| 457 | cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count; | 489 | cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count; |
| 490 | cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks; | ||
| 491 | memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name, | ||
| 492 | DLM_LOCKSPACE_LEN); | ||
| 458 | 493 | ||
| 459 | space_list = &sps->ss_group; | 494 | space_list = &sps->ss_group; |
| 460 | comm_list = &cms->cs_group; | 495 | comm_list = &cms->cs_group; |
| @@ -558,6 +593,11 @@ static struct config_item *make_comm(struct config_group *g, const char *name) | |||
| 558 | return ERR_PTR(-ENOMEM); | 593 | return ERR_PTR(-ENOMEM); |
| 559 | 594 | ||
| 560 | config_item_init_type_name(&cm->item, name, &comm_type); | 595 | config_item_init_type_name(&cm->item, name, &comm_type); |
| 596 | |||
| 597 | cm->seq = dlm_comm_count++; | ||
| 598 | if (!cm->seq) | ||
| 599 | cm->seq = dlm_comm_count++; | ||
| 600 | |||
| 561 | cm->nodeid = -1; | 601 | cm->nodeid = -1; |
| 562 | cm->local = 0; | 602 | cm->local = 0; |
| 563 | cm->addr_count = 0; | 603 | cm->addr_count = 0; |
| @@ -801,7 +841,10 @@ static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf) | |||
| 801 | static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf, | 841 | static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf, |
| 802 | size_t len) | 842 | size_t len) |
| 803 | { | 843 | { |
| 844 | uint32_t seq = 0; | ||
| 804 | nd->nodeid = simple_strtol(buf, NULL, 0); | 845 | nd->nodeid = simple_strtol(buf, NULL, 0); |
| 846 | dlm_comm_seq(nd->nodeid, &seq); | ||
| 847 | nd->comm_seq = seq; | ||
| 805 | return len; | 848 | return len; |
| 806 | } | 849 | } |
| 807 | 850 | ||
| @@ -908,13 +951,13 @@ static void put_comm(struct dlm_comm *cm) | |||
| 908 | } | 951 | } |
| 909 | 952 | ||
| 910 | /* caller must free mem */ | 953 | /* caller must free mem */ |
| 911 | int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, | 954 | int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, |
| 912 | int **new_out, int *new_count_out) | 955 | int *count_out) |
| 913 | { | 956 | { |
| 914 | struct dlm_space *sp; | 957 | struct dlm_space *sp; |
| 915 | struct dlm_node *nd; | 958 | struct dlm_node *nd; |
| 916 | int i = 0, rv = 0, ids_count = 0, new_count = 0; | 959 | struct dlm_config_node *nodes, *node; |
| 917 | int *ids, *new; | 960 | int rv, count; |
| 918 | 961 | ||
| 919 | sp = get_space(lsname); | 962 | sp = get_space(lsname); |
| 920 | if (!sp) | 963 | if (!sp) |
| @@ -927,73 +970,42 @@ int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, | |||
| 927 | goto out; | 970 | goto out; |
| 928 | } | 971 | } |
| 929 | 972 | ||
| 930 | ids_count = sp->members_count; | 973 | count = sp->members_count; |
| 931 | 974 | ||
| 932 | ids = kcalloc(ids_count, sizeof(int), GFP_NOFS); | 975 | nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS); |
| 933 | if (!ids) { | 976 | if (!nodes) { |
| 934 | rv = -ENOMEM; | 977 | rv = -ENOMEM; |
| 935 | goto out; | 978 | goto out; |
| 936 | } | 979 | } |
| 937 | 980 | ||
| 981 | node = nodes; | ||
| 938 | list_for_each_entry(nd, &sp->members, list) { | 982 | list_for_each_entry(nd, &sp->members, list) { |
| 939 | ids[i++] = nd->nodeid; | 983 | node->nodeid = nd->nodeid; |
| 940 | if (nd->new) | 984 | node->weight = nd->weight; |
| 941 | new_count++; | 985 | node->new = nd->new; |
| 942 | } | 986 | node->comm_seq = nd->comm_seq; |
| 943 | 987 | node++; | |
| 944 | if (ids_count != i) | ||
| 945 | printk(KERN_ERR "dlm: bad nodeid count %d %d\n", ids_count, i); | ||
| 946 | |||
| 947 | if (!new_count) | ||
| 948 | goto out_ids; | ||
| 949 | 988 | ||
| 950 | new = kcalloc(new_count, sizeof(int), GFP_NOFS); | 989 | nd->new = 0; |
| 951 | if (!new) { | ||
| 952 | kfree(ids); | ||
| 953 | rv = -ENOMEM; | ||
| 954 | goto out; | ||
| 955 | } | 990 | } |
| 956 | 991 | ||
| 957 | i = 0; | 992 | *count_out = count; |
| 958 | list_for_each_entry(nd, &sp->members, list) { | 993 | *nodes_out = nodes; |
| 959 | if (nd->new) { | 994 | rv = 0; |
| 960 | new[i++] = nd->nodeid; | ||
| 961 | nd->new = 0; | ||
| 962 | } | ||
| 963 | } | ||
| 964 | *new_count_out = new_count; | ||
| 965 | *new_out = new; | ||
| 966 | |||
| 967 | out_ids: | ||
| 968 | *ids_count_out = ids_count; | ||
| 969 | *ids_out = ids; | ||
| 970 | out: | 995 | out: |
| 971 | mutex_unlock(&sp->members_lock); | 996 | mutex_unlock(&sp->members_lock); |
| 972 | put_space(sp); | 997 | put_space(sp); |
| 973 | return rv; | 998 | return rv; |
| 974 | } | 999 | } |
| 975 | 1000 | ||
| 976 | int dlm_node_weight(char *lsname, int nodeid) | 1001 | int dlm_comm_seq(int nodeid, uint32_t *seq) |
| 977 | { | 1002 | { |
| 978 | struct dlm_space *sp; | 1003 | struct dlm_comm *cm = get_comm(nodeid, NULL); |
| 979 | struct dlm_node *nd; | 1004 | if (!cm) |
| 980 | int w = -EEXIST; | 1005 | return -EEXIST; |
| 981 | 1006 | *seq = cm->seq; | |
| 982 | sp = get_space(lsname); | 1007 | put_comm(cm); |
| 983 | if (!sp) | 1008 | return 0; |
| 984 | goto out; | ||
| 985 | |||
| 986 | mutex_lock(&sp->members_lock); | ||
| 987 | list_for_each_entry(nd, &sp->members, list) { | ||
| 988 | if (nd->nodeid != nodeid) | ||
| 989 | continue; | ||
| 990 | w = nd->weight; | ||
| 991 | break; | ||
| 992 | } | ||
| 993 | mutex_unlock(&sp->members_lock); | ||
| 994 | put_space(sp); | ||
| 995 | out: | ||
| 996 | return w; | ||
| 997 | } | 1009 | } |
| 998 | 1010 | ||
| 999 | int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) | 1011 | int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) |
| @@ -1047,6 +1059,8 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num) | |||
| 1047 | #define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */ | 1059 | #define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */ |
| 1048 | #define DEFAULT_WAITWARN_US 0 | 1060 | #define DEFAULT_WAITWARN_US 0 |
| 1049 | #define DEFAULT_NEW_RSB_COUNT 128 | 1061 | #define DEFAULT_NEW_RSB_COUNT 128 |
| 1062 | #define DEFAULT_RECOVER_CALLBACKS 0 | ||
| 1063 | #define DEFAULT_CLUSTER_NAME "" | ||
| 1050 | 1064 | ||
| 1051 | struct dlm_config_info dlm_config = { | 1065 | struct dlm_config_info dlm_config = { |
| 1052 | .ci_tcp_port = DEFAULT_TCP_PORT, | 1066 | .ci_tcp_port = DEFAULT_TCP_PORT, |
| @@ -1060,6 +1074,8 @@ struct dlm_config_info dlm_config = { | |||
| 1060 | .ci_protocol = DEFAULT_PROTOCOL, | 1074 | .ci_protocol = DEFAULT_PROTOCOL, |
| 1061 | .ci_timewarn_cs = DEFAULT_TIMEWARN_CS, | 1075 | .ci_timewarn_cs = DEFAULT_TIMEWARN_CS, |
| 1062 | .ci_waitwarn_us = DEFAULT_WAITWARN_US, | 1076 | .ci_waitwarn_us = DEFAULT_WAITWARN_US, |
| 1063 | .ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT | 1077 | .ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT, |
| 1078 | .ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS, | ||
| 1079 | .ci_cluster_name = DEFAULT_CLUSTER_NAME | ||
| 1064 | }; | 1080 | }; |
| 1065 | 1081 | ||
diff --git a/fs/dlm/config.h b/fs/dlm/config.h index 3099d0dd26c0..9f5e3663bb0c 100644 --- a/fs/dlm/config.h +++ b/fs/dlm/config.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-2011 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 |
| @@ -14,6 +14,13 @@ | |||
| 14 | #ifndef __CONFIG_DOT_H__ | 14 | #ifndef __CONFIG_DOT_H__ |
| 15 | #define __CONFIG_DOT_H__ | 15 | #define __CONFIG_DOT_H__ |
| 16 | 16 | ||
| 17 | struct dlm_config_node { | ||
| 18 | int nodeid; | ||
| 19 | int weight; | ||
| 20 | int new; | ||
| 21 | uint32_t comm_seq; | ||
| 22 | }; | ||
| 23 | |||
| 17 | #define DLM_MAX_ADDR_COUNT 3 | 24 | #define DLM_MAX_ADDR_COUNT 3 |
| 18 | 25 | ||
| 19 | struct dlm_config_info { | 26 | struct dlm_config_info { |
| @@ -29,15 +36,17 @@ struct dlm_config_info { | |||
| 29 | int ci_timewarn_cs; | 36 | int ci_timewarn_cs; |
| 30 | int ci_waitwarn_us; | 37 | int ci_waitwarn_us; |
| 31 | int ci_new_rsb_count; | 38 | int ci_new_rsb_count; |
| 39 | int ci_recover_callbacks; | ||
| 40 | char ci_cluster_name[DLM_LOCKSPACE_LEN]; | ||
| 32 | }; | 41 | }; |
| 33 | 42 | ||
| 34 | extern struct dlm_config_info dlm_config; | 43 | extern struct dlm_config_info dlm_config; |
| 35 | 44 | ||
| 36 | int dlm_config_init(void); | 45 | int dlm_config_init(void); |
| 37 | void dlm_config_exit(void); | 46 | void dlm_config_exit(void); |
| 38 | int dlm_node_weight(char *lsname, int nodeid); | 47 | int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, |
| 39 | int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, | 48 | int *count_out); |
| 40 | int **new_out, int *new_count_out); | 49 | int dlm_comm_seq(int nodeid, uint32_t *seq); |
| 41 | int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr); | 50 | int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr); |
| 42 | int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid); | 51 | int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid); |
| 43 | int dlm_our_nodeid(void); | 52 | int dlm_our_nodeid(void); |
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 59779237e2b4..3dca2b39e83f 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c | |||
| @@ -393,6 +393,7 @@ static const struct seq_operations format3_seq_ops; | |||
| 393 | 393 | ||
| 394 | static void *table_seq_start(struct seq_file *seq, loff_t *pos) | 394 | static void *table_seq_start(struct seq_file *seq, loff_t *pos) |
| 395 | { | 395 | { |
| 396 | struct rb_node *node; | ||
| 396 | struct dlm_ls *ls = seq->private; | 397 | struct dlm_ls *ls = seq->private; |
| 397 | struct rsbtbl_iter *ri; | 398 | struct rsbtbl_iter *ri; |
| 398 | struct dlm_rsb *r; | 399 | struct dlm_rsb *r; |
| @@ -418,9 +419,10 @@ static void *table_seq_start(struct seq_file *seq, loff_t *pos) | |||
| 418 | ri->format = 3; | 419 | ri->format = 3; |
| 419 | 420 | ||
| 420 | spin_lock(&ls->ls_rsbtbl[bucket].lock); | 421 | spin_lock(&ls->ls_rsbtbl[bucket].lock); |
| 421 | if (!list_empty(&ls->ls_rsbtbl[bucket].list)) { | 422 | if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) { |
| 422 | list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list, | 423 | for (node = rb_first(&ls->ls_rsbtbl[bucket].keep); node; |
| 423 | res_hashchain) { | 424 | node = rb_next(node)) { |
| 425 | r = rb_entry(node, struct dlm_rsb, res_hashnode); | ||
| 424 | if (!entry--) { | 426 | if (!entry--) { |
| 425 | dlm_hold_rsb(r); | 427 | dlm_hold_rsb(r); |
| 426 | ri->rsb = r; | 428 | ri->rsb = r; |
| @@ -449,9 +451,9 @@ static void *table_seq_start(struct seq_file *seq, loff_t *pos) | |||
| 449 | } | 451 | } |
| 450 | 452 | ||
| 451 | spin_lock(&ls->ls_rsbtbl[bucket].lock); | 453 | spin_lock(&ls->ls_rsbtbl[bucket].lock); |
| 452 | if (!list_empty(&ls->ls_rsbtbl[bucket].list)) { | 454 | if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) { |
| 453 | r = list_first_entry(&ls->ls_rsbtbl[bucket].list, | 455 | node = rb_first(&ls->ls_rsbtbl[bucket].keep); |
| 454 | struct dlm_rsb, res_hashchain); | 456 | r = rb_entry(node, struct dlm_rsb, res_hashnode); |
| 455 | dlm_hold_rsb(r); | 457 | dlm_hold_rsb(r); |
| 456 | ri->rsb = r; | 458 | ri->rsb = r; |
| 457 | ri->bucket = bucket; | 459 | ri->bucket = bucket; |
| @@ -467,7 +469,7 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos) | |||
| 467 | { | 469 | { |
| 468 | struct dlm_ls *ls = seq->private; | 470 | struct dlm_ls *ls = seq->private; |
| 469 | struct rsbtbl_iter *ri = iter_ptr; | 471 | struct rsbtbl_iter *ri = iter_ptr; |
| 470 | struct list_head *next; | 472 | struct rb_node *next; |
| 471 | struct dlm_rsb *r, *rp; | 473 | struct dlm_rsb *r, *rp; |
| 472 | loff_t n = *pos; | 474 | loff_t n = *pos; |
| 473 | unsigned bucket; | 475 | unsigned bucket; |
| @@ -480,10 +482,10 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos) | |||
| 480 | 482 | ||
| 481 | spin_lock(&ls->ls_rsbtbl[bucket].lock); | 483 | spin_lock(&ls->ls_rsbtbl[bucket].lock); |
| 482 | rp = ri->rsb; | 484 | rp = ri->rsb; |
| 483 | next = rp->res_hashchain.next; | 485 | next = rb_next(&rp->res_hashnode); |
| 484 | 486 | ||
| 485 | if (next != &ls->ls_rsbtbl[bucket].list) { | 487 | if (next) { |
| 486 | r = list_entry(next, struct dlm_rsb, res_hashchain); | 488 | r = rb_entry(next, struct dlm_rsb, res_hashnode); |
| 487 | dlm_hold_rsb(r); | 489 | dlm_hold_rsb(r); |
| 488 | ri->rsb = r; | 490 | ri->rsb = r; |
| 489 | spin_unlock(&ls->ls_rsbtbl[bucket].lock); | 491 | spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
| @@ -511,9 +513,9 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos) | |||
| 511 | } | 513 | } |
| 512 | 514 | ||
| 513 | spin_lock(&ls->ls_rsbtbl[bucket].lock); | 515 | spin_lock(&ls->ls_rsbtbl[bucket].lock); |
| 514 | if (!list_empty(&ls->ls_rsbtbl[bucket].list)) { | 516 | if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) { |
| 515 | r = list_first_entry(&ls->ls_rsbtbl[bucket].list, | 517 | next = rb_first(&ls->ls_rsbtbl[bucket].keep); |
| 516 | struct dlm_rsb, res_hashchain); | 518 | r = rb_entry(next, struct dlm_rsb, res_hashnode); |
| 517 | dlm_hold_rsb(r); | 519 | dlm_hold_rsb(r); |
| 518 | ri->rsb = r; | 520 | ri->rsb = r; |
| 519 | ri->bucket = bucket; | 521 | ri->bucket = bucket; |
diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c index 7b84c1dbc82e..83641574b016 100644 --- a/fs/dlm/dir.c +++ b/fs/dlm/dir.c | |||
| @@ -290,7 +290,6 @@ int dlm_recover_directory(struct dlm_ls *ls) | |||
| 290 | 290 | ||
| 291 | out_status: | 291 | out_status: |
| 292 | error = 0; | 292 | error = 0; |
| 293 | dlm_set_recover_status(ls, DLM_RS_DIR); | ||
| 294 | log_debug(ls, "dlm_recover_directory %d entries", count); | 293 | log_debug(ls, "dlm_recover_directory %d entries", count); |
| 295 | out_free: | 294 | out_free: |
| 296 | kfree(last_name); | 295 | kfree(last_name); |
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index fe2860c02449..3a564d197e99 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-2010 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2011 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 |
| @@ -103,8 +103,8 @@ struct dlm_dirtable { | |||
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | struct dlm_rsbtable { | 105 | struct dlm_rsbtable { |
| 106 | struct list_head list; | 106 | struct rb_root keep; |
| 107 | struct list_head toss; | 107 | struct rb_root toss; |
| 108 | spinlock_t lock; | 108 | spinlock_t lock; |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| @@ -117,6 +117,10 @@ struct dlm_member { | |||
| 117 | struct list_head list; | 117 | struct list_head list; |
| 118 | int nodeid; | 118 | int nodeid; |
| 119 | int weight; | 119 | int weight; |
| 120 | int slot; | ||
| 121 | int slot_prev; | ||
| 122 | int comm_seq; | ||
| 123 | uint32_t generation; | ||
| 120 | }; | 124 | }; |
| 121 | 125 | ||
| 122 | /* | 126 | /* |
| @@ -125,10 +129,8 @@ struct dlm_member { | |||
| 125 | 129 | ||
| 126 | struct dlm_recover { | 130 | struct dlm_recover { |
| 127 | struct list_head list; | 131 | struct list_head list; |
| 128 | int *nodeids; /* nodeids of all members */ | 132 | struct dlm_config_node *nodes; |
| 129 | int node_count; | 133 | int nodes_count; |
| 130 | int *new; /* nodeids of new members */ | ||
| 131 | int new_count; | ||
| 132 | uint64_t seq; | 134 | uint64_t seq; |
| 133 | }; | 135 | }; |
| 134 | 136 | ||
| @@ -285,7 +287,10 @@ struct dlm_rsb { | |||
| 285 | unsigned long res_toss_time; | 287 | unsigned long res_toss_time; |
| 286 | uint32_t res_first_lkid; | 288 | uint32_t res_first_lkid; |
| 287 | struct list_head res_lookup; /* lkbs waiting on first */ | 289 | struct list_head res_lookup; /* lkbs waiting on first */ |
| 288 | struct list_head res_hashchain; /* rsbtbl */ | 290 | union { |
| 291 | struct list_head res_hashchain; | ||
| 292 | struct rb_node res_hashnode; /* rsbtbl */ | ||
| 293 | }; | ||
| 289 | struct list_head res_grantqueue; | 294 | struct list_head res_grantqueue; |
| 290 | struct list_head res_convertqueue; | 295 | struct list_head res_convertqueue; |
| 291 | struct list_head res_waitqueue; | 296 | struct list_head res_waitqueue; |
| @@ -334,7 +339,9 @@ static inline int rsb_flag(struct dlm_rsb *r, enum rsb_flags flag) | |||
| 334 | /* dlm_header is first element of all structs sent between nodes */ | 339 | /* dlm_header is first element of all structs sent between nodes */ |
| 335 | 340 | ||
| 336 | #define DLM_HEADER_MAJOR 0x00030000 | 341 | #define DLM_HEADER_MAJOR 0x00030000 |
| 337 | #define DLM_HEADER_MINOR 0x00000000 | 342 | #define DLM_HEADER_MINOR 0x00000001 |
| 343 | |||
| 344 | #define DLM_HEADER_SLOTS 0x00000001 | ||
| 338 | 345 | ||
| 339 | #define DLM_MSG 1 | 346 | #define DLM_MSG 1 |
| 340 | #define DLM_RCOM 2 | 347 | #define DLM_RCOM 2 |
| @@ -422,10 +429,34 @@ union dlm_packet { | |||
| 422 | struct dlm_rcom rcom; | 429 | struct dlm_rcom rcom; |
| 423 | }; | 430 | }; |
| 424 | 431 | ||
| 432 | #define DLM_RSF_NEED_SLOTS 0x00000001 | ||
| 433 | |||
| 434 | /* RCOM_STATUS data */ | ||
| 435 | struct rcom_status { | ||
| 436 | __le32 rs_flags; | ||
| 437 | __le32 rs_unused1; | ||
| 438 | __le64 rs_unused2; | ||
| 439 | }; | ||
| 440 | |||
| 441 | /* RCOM_STATUS_REPLY data */ | ||
| 425 | struct rcom_config { | 442 | struct rcom_config { |
| 426 | __le32 rf_lvblen; | 443 | __le32 rf_lvblen; |
| 427 | __le32 rf_lsflags; | 444 | __le32 rf_lsflags; |
| 428 | __le64 rf_unused; | 445 | |
| 446 | /* DLM_HEADER_SLOTS adds: */ | ||
| 447 | __le32 rf_flags; | ||
| 448 | __le16 rf_our_slot; | ||
| 449 | __le16 rf_num_slots; | ||
| 450 | __le32 rf_generation; | ||
| 451 | __le32 rf_unused1; | ||
| 452 | __le64 rf_unused2; | ||
| 453 | }; | ||
| 454 | |||
| 455 | struct rcom_slot { | ||
| 456 | __le32 ro_nodeid; | ||
| 457 | __le16 ro_slot; | ||
| 458 | __le16 ro_unused1; | ||
| 459 | __le64 ro_unused2; | ||
| 429 | }; | 460 | }; |
| 430 | 461 | ||
| 431 | struct rcom_lock { | 462 | struct rcom_lock { |
| @@ -452,6 +483,7 @@ struct dlm_ls { | |||
| 452 | struct list_head ls_list; /* list of lockspaces */ | 483 | struct list_head ls_list; /* list of lockspaces */ |
| 453 | dlm_lockspace_t *ls_local_handle; | 484 | dlm_lockspace_t *ls_local_handle; |
| 454 | uint32_t ls_global_id; /* global unique lockspace ID */ | 485 | uint32_t ls_global_id; /* global unique lockspace ID */ |
| 486 | uint32_t ls_generation; | ||
| 455 | uint32_t ls_exflags; | 487 | uint32_t ls_exflags; |
| 456 | int ls_lvblen; | 488 | int ls_lvblen; |
| 457 | int ls_count; /* refcount of processes in | 489 | int ls_count; /* refcount of processes in |
| @@ -490,6 +522,11 @@ struct dlm_ls { | |||
| 490 | int ls_total_weight; | 522 | int ls_total_weight; |
| 491 | int *ls_node_array; | 523 | int *ls_node_array; |
| 492 | 524 | ||
| 525 | int ls_slot; | ||
| 526 | int ls_num_slots; | ||
| 527 | int ls_slots_size; | ||
| 528 | struct dlm_slot *ls_slots; | ||
| 529 | |||
| 493 | struct dlm_rsb ls_stub_rsb; /* for returning errors */ | 530 | struct dlm_rsb ls_stub_rsb; /* for returning errors */ |
| 494 | struct dlm_lkb ls_stub_lkb; /* for returning errors */ | 531 | struct dlm_lkb ls_stub_lkb; /* for returning errors */ |
| 495 | struct dlm_message ls_stub_ms; /* for faking a reply */ | 532 | struct dlm_message ls_stub_ms; /* for faking a reply */ |
| @@ -537,6 +574,9 @@ struct dlm_ls { | |||
| 537 | struct list_head ls_root_list; /* root resources */ | 574 | struct list_head ls_root_list; /* root resources */ |
| 538 | struct rw_semaphore ls_root_sem; /* protect root_list */ | 575 | struct rw_semaphore ls_root_sem; /* protect root_list */ |
| 539 | 576 | ||
| 577 | const struct dlm_lockspace_ops *ls_ops; | ||
| 578 | void *ls_ops_arg; | ||
| 579 | |||
| 540 | int ls_namelen; | 580 | int ls_namelen; |
| 541 | char ls_name[1]; | 581 | char ls_name[1]; |
| 542 | }; | 582 | }; |
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 83b5e32514e1..d47183043c59 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | L: receive_xxxx_reply() <- R: send_xxxx_reply() | 56 | L: receive_xxxx_reply() <- R: send_xxxx_reply() |
| 57 | */ | 57 | */ |
| 58 | #include <linux/types.h> | 58 | #include <linux/types.h> |
| 59 | #include <linux/rbtree.h> | ||
| 59 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
| 60 | #include "dlm_internal.h" | 61 | #include "dlm_internal.h" |
| 61 | #include <linux/dlm_device.h> | 62 | #include <linux/dlm_device.h> |
| @@ -380,6 +381,8 @@ static int get_rsb_struct(struct dlm_ls *ls, char *name, int len, | |||
| 380 | 381 | ||
| 381 | r = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, res_hashchain); | 382 | r = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, res_hashchain); |
| 382 | list_del(&r->res_hashchain); | 383 | list_del(&r->res_hashchain); |
| 384 | /* Convert the empty list_head to a NULL rb_node for tree usage: */ | ||
| 385 | memset(&r->res_hashnode, 0, sizeof(struct rb_node)); | ||
| 383 | ls->ls_new_rsb_count--; | 386 | ls->ls_new_rsb_count--; |
| 384 | spin_unlock(&ls->ls_new_rsb_spin); | 387 | spin_unlock(&ls->ls_new_rsb_spin); |
| 385 | 388 | ||
| @@ -388,7 +391,6 @@ static int get_rsb_struct(struct dlm_ls *ls, char *name, int len, | |||
| 388 | memcpy(r->res_name, name, len); | 391 | memcpy(r->res_name, name, len); |
| 389 | mutex_init(&r->res_mutex); | 392 | mutex_init(&r->res_mutex); |
| 390 | 393 | ||
| 391 | INIT_LIST_HEAD(&r->res_hashchain); | ||
| 392 | INIT_LIST_HEAD(&r->res_lookup); | 394 | INIT_LIST_HEAD(&r->res_lookup); |
| 393 | INIT_LIST_HEAD(&r->res_grantqueue); | 395 | INIT_LIST_HEAD(&r->res_grantqueue); |
| 394 | INIT_LIST_HEAD(&r->res_convertqueue); | 396 | INIT_LIST_HEAD(&r->res_convertqueue); |
| @@ -400,14 +402,31 @@ static int get_rsb_struct(struct dlm_ls *ls, char *name, int len, | |||
| 400 | return 0; | 402 | return 0; |
| 401 | } | 403 | } |
| 402 | 404 | ||
| 403 | static int search_rsb_list(struct list_head *head, char *name, int len, | 405 | static int rsb_cmp(struct dlm_rsb *r, const char *name, int nlen) |
| 406 | { | ||
| 407 | char maxname[DLM_RESNAME_MAXLEN]; | ||
| 408 | |||
| 409 | memset(maxname, 0, DLM_RESNAME_MAXLEN); | ||
| 410 | memcpy(maxname, name, nlen); | ||
| 411 | return memcmp(r->res_name, maxname, DLM_RESNAME_MAXLEN); | ||
| 412 | } | ||
| 413 | |||
| 414 | static int search_rsb_tree(struct rb_root *tree, char *name, int len, | ||
| 404 | unsigned int flags, struct dlm_rsb **r_ret) | 415 | unsigned int flags, struct dlm_rsb **r_ret) |
| 405 | { | 416 | { |
| 417 | struct rb_node *node = tree->rb_node; | ||
| 406 | struct dlm_rsb *r; | 418 | struct dlm_rsb *r; |
| 407 | int error = 0; | 419 | int error = 0; |
| 408 | 420 | int rc; | |
| 409 | list_for_each_entry(r, head, res_hashchain) { | 421 | |
| 410 | if (len == r->res_length && !memcmp(name, r->res_name, len)) | 422 | while (node) { |
| 423 | r = rb_entry(node, struct dlm_rsb, res_hashnode); | ||
| 424 | rc = rsb_cmp(r, name, len); | ||
| 425 | if (rc < 0) | ||
| 426 | node = node->rb_left; | ||
| 427 | else if (rc > 0) | ||
| 428 | node = node->rb_right; | ||
| 429 | else | ||
| 411 | goto found; | 430 | goto found; |
| 412 | } | 431 | } |
| 413 | *r_ret = NULL; | 432 | *r_ret = NULL; |
| @@ -420,22 +439,54 @@ static int search_rsb_list(struct list_head *head, char *name, int len, | |||
| 420 | return error; | 439 | return error; |
| 421 | } | 440 | } |
| 422 | 441 | ||
| 442 | static int rsb_insert(struct dlm_rsb *rsb, struct rb_root *tree) | ||
| 443 | { | ||
| 444 | struct rb_node **newn = &tree->rb_node; | ||
| 445 | struct rb_node *parent = NULL; | ||
| 446 | int rc; | ||
| 447 | |||
| 448 | while (*newn) { | ||
| 449 | struct dlm_rsb *cur = rb_entry(*newn, struct dlm_rsb, | ||
| 450 | res_hashnode); | ||
| 451 | |||
| 452 | parent = *newn; | ||
| 453 | rc = rsb_cmp(cur, rsb->res_name, rsb->res_length); | ||
| 454 | if (rc < 0) | ||
| 455 | newn = &parent->rb_left; | ||
| 456 | else if (rc > 0) | ||
| 457 | newn = &parent->rb_right; | ||
| 458 | else { | ||
| 459 | log_print("rsb_insert match"); | ||
| 460 | dlm_dump_rsb(rsb); | ||
| 461 | dlm_dump_rsb(cur); | ||
| 462 | return -EEXIST; | ||
| 463 | } | ||
| 464 | } | ||
| 465 | |||
| 466 | rb_link_node(&rsb->res_hashnode, parent, newn); | ||
| 467 | rb_insert_color(&rsb->res_hashnode, tree); | ||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | |||
| 423 | static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b, | 471 | static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b, |
| 424 | unsigned int flags, struct dlm_rsb **r_ret) | 472 | unsigned int flags, struct dlm_rsb **r_ret) |
| 425 | { | 473 | { |
| 426 | struct dlm_rsb *r; | 474 | struct dlm_rsb *r; |
| 427 | int error; | 475 | int error; |
| 428 | 476 | ||
| 429 | error = search_rsb_list(&ls->ls_rsbtbl[b].list, name, len, flags, &r); | 477 | error = search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, flags, &r); |
| 430 | if (!error) { | 478 | if (!error) { |
| 431 | kref_get(&r->res_ref); | 479 | kref_get(&r->res_ref); |
| 432 | goto out; | 480 | goto out; |
| 433 | } | 481 | } |
| 434 | error = search_rsb_list(&ls->ls_rsbtbl[b].toss, name, len, flags, &r); | 482 | error = search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, flags, &r); |
| 435 | if (error) | 483 | if (error) |
| 436 | goto out; | 484 | goto out; |
| 437 | 485 | ||
| 438 | list_move(&r->res_hashchain, &ls->ls_rsbtbl[b].list); | 486 | rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss); |
| 487 | error = rsb_insert(r, &ls->ls_rsbtbl[b].keep); | ||
| 488 | if (error) | ||
| 489 | return error; | ||
| 439 | 490 | ||
| 440 | if (dlm_no_directory(ls)) | 491 | if (dlm_no_directory(ls)) |
| 441 | goto out; | 492 | goto out; |
| @@ -527,8 +578,7 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen, | |||
| 527 | nodeid = 0; | 578 | nodeid = 0; |
| 528 | r->res_nodeid = nodeid; | 579 | r->res_nodeid = nodeid; |
| 529 | } | 580 | } |
| 530 | list_add(&r->res_hashchain, &ls->ls_rsbtbl[bucket].list); | 581 | error = rsb_insert(r, &ls->ls_rsbtbl[bucket].keep); |
| 531 | error = 0; | ||
| 532 | out_unlock: | 582 | out_unlock: |
| 533 | spin_unlock(&ls->ls_rsbtbl[bucket].lock); | 583 | spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
| 534 | out: | 584 | out: |
| @@ -556,7 +606,8 @@ static void toss_rsb(struct kref *kref) | |||
| 556 | 606 | ||
| 557 | DLM_ASSERT(list_empty(&r->res_root_list), dlm_print_rsb(r);); | 607 | DLM_ASSERT(list_empty(&r->res_root_list), dlm_print_rsb(r);); |
| 558 | kref_init(&r->res_ref); | 608 | kref_init(&r->res_ref); |
| 559 | list_move(&r->res_hashchain, &ls->ls_rsbtbl[r->res_bucket].toss); | 609 | rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[r->res_bucket].keep); |
| 610 | rsb_insert(r, &ls->ls_rsbtbl[r->res_bucket].toss); | ||
| 560 | r->res_toss_time = jiffies; | 611 | r->res_toss_time = jiffies; |
| 561 | if (r->res_lvbptr) { | 612 | if (r->res_lvbptr) { |
| 562 | dlm_free_lvb(r->res_lvbptr); | 613 | dlm_free_lvb(r->res_lvbptr); |
| @@ -1082,19 +1133,19 @@ static void dir_remove(struct dlm_rsb *r) | |||
| 1082 | r->res_name, r->res_length); | 1133 | r->res_name, r->res_length); |
| 1083 | } | 1134 | } |
| 1084 | 1135 | ||
| 1085 | /* FIXME: shouldn't this be able to exit as soon as one non-due rsb is | 1136 | /* FIXME: make this more efficient */ |
| 1086 | found since they are in order of newest to oldest? */ | ||
| 1087 | 1137 | ||
| 1088 | static int shrink_bucket(struct dlm_ls *ls, int b) | 1138 | static int shrink_bucket(struct dlm_ls *ls, int b) |
| 1089 | { | 1139 | { |
| 1140 | struct rb_node *n; | ||
| 1090 | struct dlm_rsb *r; | 1141 | struct dlm_rsb *r; |
| 1091 | int count = 0, found; | 1142 | int count = 0, found; |
| 1092 | 1143 | ||
| 1093 | for (;;) { | 1144 | for (;;) { |
| 1094 | found = 0; | 1145 | found = 0; |
| 1095 | spin_lock(&ls->ls_rsbtbl[b].lock); | 1146 | spin_lock(&ls->ls_rsbtbl[b].lock); |
| 1096 | list_for_each_entry_reverse(r, &ls->ls_rsbtbl[b].toss, | 1147 | for (n = rb_first(&ls->ls_rsbtbl[b].toss); n; n = rb_next(n)) { |
| 1097 | res_hashchain) { | 1148 | r = rb_entry(n, struct dlm_rsb, res_hashnode); |
| 1098 | if (!time_after_eq(jiffies, r->res_toss_time + | 1149 | if (!time_after_eq(jiffies, r->res_toss_time + |
| 1099 | dlm_config.ci_toss_secs * HZ)) | 1150 | dlm_config.ci_toss_secs * HZ)) |
| 1100 | continue; | 1151 | continue; |
| @@ -1108,7 +1159,7 @@ static int shrink_bucket(struct dlm_ls *ls, int b) | |||
| 1108 | } | 1159 | } |
| 1109 | 1160 | ||
| 1110 | if (kref_put(&r->res_ref, kill_rsb)) { | 1161 | if (kref_put(&r->res_ref, kill_rsb)) { |
| 1111 | list_del(&r->res_hashchain); | 1162 | rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss); |
| 1112 | spin_unlock(&ls->ls_rsbtbl[b].lock); | 1163 | spin_unlock(&ls->ls_rsbtbl[b].lock); |
| 1113 | 1164 | ||
| 1114 | if (is_master(r)) | 1165 | if (is_master(r)) |
| @@ -4441,10 +4492,12 @@ int dlm_purge_locks(struct dlm_ls *ls) | |||
| 4441 | 4492 | ||
| 4442 | static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket) | 4493 | static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket) |
| 4443 | { | 4494 | { |
| 4495 | struct rb_node *n; | ||
| 4444 | struct dlm_rsb *r, *r_ret = NULL; | 4496 | struct dlm_rsb *r, *r_ret = NULL; |
| 4445 | 4497 | ||
| 4446 | spin_lock(&ls->ls_rsbtbl[bucket].lock); | 4498 | spin_lock(&ls->ls_rsbtbl[bucket].lock); |
| 4447 | list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list, res_hashchain) { | 4499 | for (n = rb_first(&ls->ls_rsbtbl[bucket].keep); n; n = rb_next(n)) { |
| 4500 | r = rb_entry(n, struct dlm_rsb, res_hashnode); | ||
| 4448 | if (!rsb_flag(r, RSB_LOCKS_PURGED)) | 4501 | if (!rsb_flag(r, RSB_LOCKS_PURGED)) |
| 4449 | continue; | 4502 | continue; |
| 4450 | hold_rsb(r); | 4503 | hold_rsb(r); |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index a1d8f1af144b..a1ea25face82 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-2008 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2011 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 |
| @@ -386,12 +386,15 @@ static void threads_stop(void) | |||
| 386 | dlm_lowcomms_stop(); | 386 | dlm_lowcomms_stop(); |
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | static int new_lockspace(const char *name, int namelen, void **lockspace, | 389 | static int new_lockspace(const char *name, const char *cluster, |
| 390 | uint32_t flags, int lvblen) | 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 | struct dlm_ls *ls; | 394 | struct dlm_ls *ls; |
| 393 | int i, size, error; | 395 | int i, size, error; |
| 394 | int do_unreg = 0; | 396 | int do_unreg = 0; |
| 397 | int namelen = strlen(name); | ||
| 395 | 398 | ||
| 396 | if (namelen > DLM_LOCKSPACE_LEN) | 399 | if (namelen > DLM_LOCKSPACE_LEN) |
| 397 | return -EINVAL; | 400 | return -EINVAL; |
| @@ -403,8 +406,24 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, | |||
| 403 | return -EINVAL; | 406 | return -EINVAL; |
| 404 | 407 | ||
| 405 | if (!dlm_user_daemon_available()) { | 408 | if (!dlm_user_daemon_available()) { |
| 406 | module_put(THIS_MODULE); | 409 | log_print("dlm user daemon not available"); |
| 407 | return -EUNATCH; | 410 | error = -EUNATCH; |
| 411 | goto out; | ||
| 412 | } | ||
| 413 | |||
| 414 | if (ops && ops_result) { | ||
| 415 | if (!dlm_config.ci_recover_callbacks) | ||
| 416 | *ops_result = -EOPNOTSUPP; | ||
| 417 | else | ||
| 418 | *ops_result = 0; | ||
| 419 | } | ||
| 420 | |||
| 421 | if (dlm_config.ci_recover_callbacks && cluster && | ||
| 422 | strncmp(cluster, dlm_config.ci_cluster_name, DLM_LOCKSPACE_LEN)) { | ||
| 423 | log_print("dlm cluster name %s mismatch %s", | ||
| 424 | dlm_config.ci_cluster_name, cluster); | ||
| 425 | error = -EBADR; | ||
| 426 | goto out; | ||
| 408 | } | 427 | } |
| 409 | 428 | ||
| 410 | error = 0; | 429 | error = 0; |
| @@ -442,6 +461,11 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, | |||
| 442 | ls->ls_flags = 0; | 461 | ls->ls_flags = 0; |
| 443 | ls->ls_scan_time = jiffies; | 462 | ls->ls_scan_time = jiffies; |
| 444 | 463 | ||
| 464 | if (ops && dlm_config.ci_recover_callbacks) { | ||
| 465 | ls->ls_ops = ops; | ||
| 466 | ls->ls_ops_arg = ops_arg; | ||
| 467 | } | ||
| 468 | |||
| 445 | if (flags & DLM_LSFL_TIMEWARN) | 469 | if (flags & DLM_LSFL_TIMEWARN) |
| 446 | set_bit(LSFL_TIMEWARN, &ls->ls_flags); | 470 | set_bit(LSFL_TIMEWARN, &ls->ls_flags); |
| 447 | 471 | ||
| @@ -457,8 +481,8 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, | |||
| 457 | if (!ls->ls_rsbtbl) | 481 | if (!ls->ls_rsbtbl) |
| 458 | goto out_lsfree; | 482 | goto out_lsfree; |
| 459 | for (i = 0; i < size; i++) { | 483 | for (i = 0; i < size; i++) { |
| 460 | INIT_LIST_HEAD(&ls->ls_rsbtbl[i].list); | 484 | ls->ls_rsbtbl[i].keep.rb_node = NULL; |
| 461 | INIT_LIST_HEAD(&ls->ls_rsbtbl[i].toss); | 485 | ls->ls_rsbtbl[i].toss.rb_node = NULL; |
| 462 | spin_lock_init(&ls->ls_rsbtbl[i].lock); | 486 | spin_lock_init(&ls->ls_rsbtbl[i].lock); |
| 463 | } | 487 | } |
| 464 | 488 | ||
| @@ -525,6 +549,11 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, | |||
| 525 | if (!ls->ls_recover_buf) | 549 | if (!ls->ls_recover_buf) |
| 526 | goto out_dirfree; | 550 | goto out_dirfree; |
| 527 | 551 | ||
| 552 | ls->ls_slot = 0; | ||
| 553 | ls->ls_num_slots = 0; | ||
| 554 | ls->ls_slots_size = 0; | ||
| 555 | ls->ls_slots = NULL; | ||
| 556 | |||
| 528 | INIT_LIST_HEAD(&ls->ls_recover_list); | 557 | INIT_LIST_HEAD(&ls->ls_recover_list); |
| 529 | spin_lock_init(&ls->ls_recover_list_lock); | 558 | spin_lock_init(&ls->ls_recover_list_lock); |
| 530 | ls->ls_recover_list_count = 0; | 559 | ls->ls_recover_list_count = 0; |
| @@ -614,8 +643,10 @@ static int new_lockspace(const char *name, int namelen, void **lockspace, | |||
| 614 | return error; | 643 | return error; |
| 615 | } | 644 | } |
| 616 | 645 | ||
| 617 | int dlm_new_lockspace(const char *name, int namelen, void **lockspace, | 646 | int dlm_new_lockspace(const char *name, const char *cluster, |
| 618 | uint32_t flags, int lvblen) | 647 | uint32_t flags, int lvblen, |
| 648 | const struct dlm_lockspace_ops *ops, void *ops_arg, | ||
| 649 | int *ops_result, dlm_lockspace_t **lockspace) | ||
| 619 | { | 650 | { |
| 620 | int error = 0; | 651 | int error = 0; |
| 621 | 652 | ||
| @@ -625,7 +656,8 @@ int dlm_new_lockspace(const char *name, int namelen, void **lockspace, | |||
| 625 | if (error) | 656 | if (error) |
| 626 | goto out; | 657 | goto out; |
| 627 | 658 | ||
| 628 | error = new_lockspace(name, namelen, lockspace, flags, lvblen); | 659 | error = new_lockspace(name, cluster, flags, lvblen, ops, ops_arg, |
| 660 | ops_result, lockspace); | ||
| 629 | if (!error) | 661 | if (!error) |
| 630 | ls_count++; | 662 | ls_count++; |
| 631 | if (error > 0) | 663 | if (error > 0) |
| @@ -685,7 +717,7 @@ static int lockspace_busy(struct dlm_ls *ls, int force) | |||
| 685 | static int release_lockspace(struct dlm_ls *ls, int force) | 717 | static int release_lockspace(struct dlm_ls *ls, int force) |
| 686 | { | 718 | { |
| 687 | struct dlm_rsb *rsb; | 719 | struct dlm_rsb *rsb; |
| 688 | struct list_head *head; | 720 | struct rb_node *n; |
| 689 | int i, busy, rv; | 721 | int i, busy, rv; |
| 690 | 722 | ||
| 691 | busy = lockspace_busy(ls, force); | 723 | busy = lockspace_busy(ls, force); |
| @@ -746,20 +778,15 @@ static int release_lockspace(struct dlm_ls *ls, int force) | |||
| 746 | */ | 778 | */ |
| 747 | 779 | ||
| 748 | for (i = 0; i < ls->ls_rsbtbl_size; i++) { | 780 | for (i = 0; i < ls->ls_rsbtbl_size; i++) { |
| 749 | head = &ls->ls_rsbtbl[i].list; | 781 | while ((n = rb_first(&ls->ls_rsbtbl[i].keep))) { |
| 750 | while (!list_empty(head)) { | 782 | rsb = rb_entry(n, struct dlm_rsb, res_hashnode); |
| 751 | rsb = list_entry(head->next, struct dlm_rsb, | 783 | rb_erase(n, &ls->ls_rsbtbl[i].keep); |
| 752 | res_hashchain); | ||
| 753 | |||
| 754 | list_del(&rsb->res_hashchain); | ||
| 755 | dlm_free_rsb(rsb); | 784 | dlm_free_rsb(rsb); |
| 756 | } | 785 | } |
| 757 | 786 | ||
| 758 | head = &ls->ls_rsbtbl[i].toss; | 787 | while ((n = rb_first(&ls->ls_rsbtbl[i].toss))) { |
| 759 | while (!list_empty(head)) { | 788 | rsb = rb_entry(n, struct dlm_rsb, res_hashnode); |
| 760 | rsb = list_entry(head->next, struct dlm_rsb, | 789 | rb_erase(n, &ls->ls_rsbtbl[i].toss); |
| 761 | res_hashchain); | ||
| 762 | list_del(&rsb->res_hashchain); | ||
| 763 | dlm_free_rsb(rsb); | 790 | dlm_free_rsb(rsb); |
| 764 | } | 791 | } |
| 765 | } | 792 | } |
diff --git a/fs/dlm/member.c b/fs/dlm/member.c index b12532e553f8..862640a36d5c 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c | |||
| @@ -1,7 +1,7 @@ | |||
| 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 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
| 7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
| @@ -19,6 +19,280 @@ | |||
| 19 | #include "config.h" | 19 | #include "config.h" |
| 20 | #include "lowcomms.h" | 20 | #include "lowcomms.h" |
| 21 | 21 | ||
| 22 | int dlm_slots_version(struct dlm_header *h) | ||
| 23 | { | ||
| 24 | if ((h->h_version & 0x0000FFFF) < DLM_HEADER_SLOTS) | ||
| 25 | return 0; | ||
| 26 | return 1; | ||
| 27 | } | ||
| 28 | |||
| 29 | void dlm_slot_save(struct dlm_ls *ls, struct dlm_rcom *rc, | ||
| 30 | struct dlm_member *memb) | ||
| 31 | { | ||
| 32 | struct rcom_config *rf = (struct rcom_config *)rc->rc_buf; | ||
| 33 | |||
| 34 | if (!dlm_slots_version(&rc->rc_header)) | ||
| 35 | return; | ||
| 36 | |||
| 37 | memb->slot = le16_to_cpu(rf->rf_our_slot); | ||
| 38 | memb->generation = le32_to_cpu(rf->rf_generation); | ||
| 39 | } | ||
| 40 | |||
| 41 | void dlm_slots_copy_out(struct dlm_ls *ls, struct dlm_rcom *rc) | ||
| 42 | { | ||
| 43 | struct dlm_slot *slot; | ||
| 44 | struct rcom_slot *ro; | ||
| 45 | int i; | ||
| 46 | |||
| 47 | ro = (struct rcom_slot *)(rc->rc_buf + sizeof(struct rcom_config)); | ||
| 48 | |||
| 49 | /* ls_slots array is sparse, but not rcom_slots */ | ||
| 50 | |||
| 51 | for (i = 0; i < ls->ls_slots_size; i++) { | ||
| 52 | slot = &ls->ls_slots[i]; | ||
| 53 | if (!slot->nodeid) | ||
| 54 | continue; | ||
| 55 | ro->ro_nodeid = cpu_to_le32(slot->nodeid); | ||
| 56 | ro->ro_slot = cpu_to_le16(slot->slot); | ||
| 57 | ro++; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | #define SLOT_DEBUG_LINE 128 | ||
| 62 | |||
| 63 | static void log_debug_slots(struct dlm_ls *ls, uint32_t gen, int num_slots, | ||
| 64 | struct rcom_slot *ro0, struct dlm_slot *array, | ||
| 65 | int array_size) | ||
| 66 | { | ||
| 67 | char line[SLOT_DEBUG_LINE]; | ||
| 68 | int len = SLOT_DEBUG_LINE - 1; | ||
| 69 | int pos = 0; | ||
| 70 | int ret, i; | ||
| 71 | |||
| 72 | if (!dlm_config.ci_log_debug) | ||
| 73 | return; | ||
| 74 | |||
| 75 | memset(line, 0, sizeof(line)); | ||
| 76 | |||
| 77 | if (array) { | ||
| 78 | for (i = 0; i < array_size; i++) { | ||
| 79 | if (!array[i].nodeid) | ||
| 80 | continue; | ||
| 81 | |||
| 82 | ret = snprintf(line + pos, len - pos, " %d:%d", | ||
| 83 | array[i].slot, array[i].nodeid); | ||
| 84 | if (ret >= len - pos) | ||
| 85 | break; | ||
| 86 | pos += ret; | ||
| 87 | } | ||
| 88 | } else if (ro0) { | ||
| 89 | for (i = 0; i < num_slots; i++) { | ||
| 90 | ret = snprintf(line + pos, len - pos, " %d:%d", | ||
| 91 | ro0[i].ro_slot, ro0[i].ro_nodeid); | ||
| 92 | if (ret >= len - pos) | ||
| 93 | break; | ||
| 94 | pos += ret; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | log_debug(ls, "generation %u slots %d%s", gen, num_slots, line); | ||
| 99 | } | ||
| 100 | |||
| 101 | int dlm_slots_copy_in(struct dlm_ls *ls) | ||
| 102 | { | ||
| 103 | struct dlm_member *memb; | ||
| 104 | struct dlm_rcom *rc = ls->ls_recover_buf; | ||
| 105 | struct rcom_config *rf = (struct rcom_config *)rc->rc_buf; | ||
| 106 | struct rcom_slot *ro0, *ro; | ||
| 107 | int our_nodeid = dlm_our_nodeid(); | ||
| 108 | int i, num_slots; | ||
| 109 | uint32_t gen; | ||
| 110 | |||
| 111 | if (!dlm_slots_version(&rc->rc_header)) | ||
| 112 | return -1; | ||
| 113 | |||
| 114 | gen = le32_to_cpu(rf->rf_generation); | ||
| 115 | if (gen <= ls->ls_generation) { | ||
| 116 | log_error(ls, "dlm_slots_copy_in gen %u old %u", | ||
| 117 | gen, ls->ls_generation); | ||
| 118 | } | ||
| 119 | ls->ls_generation = gen; | ||
| 120 | |||
| 121 | num_slots = le16_to_cpu(rf->rf_num_slots); | ||
| 122 | if (!num_slots) | ||
| 123 | return -1; | ||
| 124 | |||
| 125 | ro0 = (struct rcom_slot *)(rc->rc_buf + sizeof(struct rcom_config)); | ||
| 126 | |||
| 127 | for (i = 0, ro = ro0; i < num_slots; i++, ro++) { | ||
| 128 | ro->ro_nodeid = le32_to_cpu(ro->ro_nodeid); | ||
| 129 | ro->ro_slot = le16_to_cpu(ro->ro_slot); | ||
| 130 | } | ||
| 131 | |||
| 132 | log_debug_slots(ls, gen, num_slots, ro0, NULL, 0); | ||
| 133 | |||
| 134 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
| 135 | for (i = 0, ro = ro0; i < num_slots; i++, ro++) { | ||
| 136 | if (ro->ro_nodeid != memb->nodeid) | ||
| 137 | continue; | ||
| 138 | memb->slot = ro->ro_slot; | ||
| 139 | memb->slot_prev = memb->slot; | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | |||
| 143 | if (memb->nodeid == our_nodeid) { | ||
| 144 | if (ls->ls_slot && ls->ls_slot != memb->slot) { | ||
| 145 | log_error(ls, "dlm_slots_copy_in our slot " | ||
| 146 | "changed %d %d", ls->ls_slot, | ||
| 147 | memb->slot); | ||
| 148 | return -1; | ||
| 149 | } | ||
| 150 | |||
| 151 | if (!ls->ls_slot) | ||
| 152 | ls->ls_slot = memb->slot; | ||
| 153 | } | ||
| 154 | |||
| 155 | if (!memb->slot) { | ||
| 156 | log_error(ls, "dlm_slots_copy_in nodeid %d no slot", | ||
| 157 | memb->nodeid); | ||
| 158 | return -1; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | /* for any nodes that do not support slots, we will not have set memb->slot | ||
| 166 | in wait_status_all(), so memb->slot will remain -1, and we will not | ||
| 167 | assign slots or set ls_num_slots here */ | ||
| 168 | |||
| 169 | int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size, | ||
| 170 | struct dlm_slot **slots_out, uint32_t *gen_out) | ||
| 171 | { | ||
| 172 | struct dlm_member *memb; | ||
| 173 | struct dlm_slot *array; | ||
| 174 | int our_nodeid = dlm_our_nodeid(); | ||
| 175 | int array_size, max_slots, i; | ||
| 176 | int need = 0; | ||
| 177 | int max = 0; | ||
| 178 | int num = 0; | ||
| 179 | uint32_t gen = 0; | ||
| 180 | |||
| 181 | /* our own memb struct will have slot -1 gen 0 */ | ||
| 182 | |||
| 183 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
| 184 | if (memb->nodeid == our_nodeid) { | ||
| 185 | memb->slot = ls->ls_slot; | ||
| 186 | memb->generation = ls->ls_generation; | ||
| 187 | break; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
| 192 | if (memb->generation > gen) | ||
| 193 | gen = memb->generation; | ||
| 194 | |||
| 195 | /* node doesn't support slots */ | ||
| 196 | |||
| 197 | if (memb->slot == -1) | ||
| 198 | return -1; | ||
| 199 | |||
| 200 | /* node needs a slot assigned */ | ||
| 201 | |||
| 202 | if (!memb->slot) | ||
| 203 | need++; | ||
| 204 | |||
| 205 | /* node has a slot assigned */ | ||
| 206 | |||
| 207 | num++; | ||
| 208 | |||
| 209 | if (!max || max < memb->slot) | ||
| 210 | max = memb->slot; | ||
| 211 | |||
| 212 | /* sanity check, once slot is assigned it shouldn't change */ | ||
| 213 | |||
| 214 | if (memb->slot_prev && memb->slot && memb->slot_prev != memb->slot) { | ||
| 215 | log_error(ls, "nodeid %d slot changed %d %d", | ||
| 216 | memb->nodeid, memb->slot_prev, memb->slot); | ||
| 217 | return -1; | ||
| 218 | } | ||
| 219 | memb->slot_prev = memb->slot; | ||
| 220 | } | ||
| 221 | |||
| 222 | array_size = max + need; | ||
| 223 | |||
| 224 | array = kzalloc(array_size * sizeof(struct dlm_slot), GFP_NOFS); | ||
| 225 | if (!array) | ||
| 226 | return -ENOMEM; | ||
| 227 | |||
| 228 | num = 0; | ||
| 229 | |||
| 230 | /* fill in slots (offsets) that are used */ | ||
| 231 | |||
| 232 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
| 233 | if (!memb->slot) | ||
| 234 | continue; | ||
| 235 | |||
| 236 | if (memb->slot > array_size) { | ||
| 237 | log_error(ls, "invalid slot number %d", memb->slot); | ||
| 238 | kfree(array); | ||
| 239 | return -1; | ||
| 240 | } | ||
| 241 | |||
| 242 | array[memb->slot - 1].nodeid = memb->nodeid; | ||
| 243 | array[memb->slot - 1].slot = memb->slot; | ||
| 244 | num++; | ||
| 245 | } | ||
| 246 | |||
| 247 | /* assign new slots from unused offsets */ | ||
| 248 | |||
| 249 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
| 250 | if (memb->slot) | ||
| 251 | continue; | ||
| 252 | |||
| 253 | for (i = 0; i < array_size; i++) { | ||
| 254 | if (array[i].nodeid) | ||
| 255 | continue; | ||
| 256 | |||
| 257 | memb->slot = i + 1; | ||
| 258 | memb->slot_prev = memb->slot; | ||
| 259 | array[i].nodeid = memb->nodeid; | ||
| 260 | array[i].slot = memb->slot; | ||
| 261 | num++; | ||
| 262 | |||
| 263 | if (!ls->ls_slot && memb->nodeid == our_nodeid) | ||
| 264 | ls->ls_slot = memb->slot; | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | |||
| 268 | if (!memb->slot) { | ||
| 269 | log_error(ls, "no free slot found"); | ||
| 270 | kfree(array); | ||
| 271 | return -1; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | gen++; | ||
| 276 | |||
| 277 | log_debug_slots(ls, gen, num, NULL, array, array_size); | ||
| 278 | |||
| 279 | max_slots = (dlm_config.ci_buffer_size - sizeof(struct dlm_rcom) - | ||
| 280 | sizeof(struct rcom_config)) / sizeof(struct rcom_slot); | ||
| 281 | |||
| 282 | if (num > max_slots) { | ||
| 283 | log_error(ls, "num_slots %d exceeds max_slots %d", | ||
| 284 | num, max_slots); | ||
| 285 | kfree(array); | ||
| 286 | return -1; | ||
| 287 | } | ||
| 288 | |||
| 289 | *gen_out = gen; | ||
| 290 | *slots_out = array; | ||
| 291 | *slots_size = array_size; | ||
| 292 | *num_slots = num; | ||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 22 | static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new) | 296 | static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new) |
| 23 | { | 297 | { |
| 24 | struct dlm_member *memb = NULL; | 298 | struct dlm_member *memb = NULL; |
| @@ -43,59 +317,51 @@ static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new) | |||
| 43 | } | 317 | } |
| 44 | } | 318 | } |
| 45 | 319 | ||
| 46 | 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) |
| 47 | { | 321 | { |
| 48 | struct dlm_member *memb; | 322 | struct dlm_member *memb; |
| 49 | int w, error; | 323 | int error; |
| 50 | 324 | ||
| 51 | memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS); | 325 | memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS); |
| 52 | if (!memb) | 326 | if (!memb) |
| 53 | return -ENOMEM; | 327 | return -ENOMEM; |
| 54 | 328 | ||
| 55 | w = dlm_node_weight(ls->ls_name, nodeid); | 329 | error = dlm_lowcomms_connect_node(node->nodeid); |
| 56 | if (w < 0) { | ||
| 57 | kfree(memb); | ||
| 58 | return w; | ||
| 59 | } | ||
| 60 | |||
| 61 | error = dlm_lowcomms_connect_node(nodeid); | ||
| 62 | if (error < 0) { | 330 | if (error < 0) { |
| 63 | kfree(memb); | 331 | kfree(memb); |
| 64 | return error; | 332 | return error; |
| 65 | } | 333 | } |
| 66 | 334 | ||
| 67 | memb->nodeid = nodeid; | 335 | memb->nodeid = node->nodeid; |
| 68 | memb->weight = w; | 336 | memb->weight = node->weight; |
| 337 | memb->comm_seq = node->comm_seq; | ||
| 69 | add_ordered_member(ls, memb); | 338 | add_ordered_member(ls, memb); |
| 70 | ls->ls_num_nodes++; | 339 | ls->ls_num_nodes++; |
| 71 | return 0; | 340 | return 0; |
| 72 | } | 341 | } |
| 73 | 342 | ||
| 74 | 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) |
| 75 | { | ||
| 76 | list_move(&memb->list, &ls->ls_nodes_gone); | ||
| 77 | ls->ls_num_nodes--; | ||
| 78 | } | ||
| 79 | |||
| 80 | int dlm_is_member(struct dlm_ls *ls, int nodeid) | ||
| 81 | { | 344 | { |
| 82 | struct dlm_member *memb; | 345 | struct dlm_member *memb; |
| 83 | 346 | ||
| 84 | list_for_each_entry(memb, &ls->ls_nodes, list) { | 347 | list_for_each_entry(memb, head, list) { |
| 85 | if (memb->nodeid == nodeid) | 348 | if (memb->nodeid == nodeid) |
| 86 | return 1; | 349 | return memb; |
| 87 | } | 350 | } |
| 351 | return NULL; | ||
| 352 | } | ||
| 353 | |||
| 354 | int dlm_is_member(struct dlm_ls *ls, int nodeid) | ||
| 355 | { | ||
| 356 | if (find_memb(&ls->ls_nodes, nodeid)) | ||
| 357 | return 1; | ||
| 88 | return 0; | 358 | return 0; |
| 89 | } | 359 | } |
| 90 | 360 | ||
| 91 | int dlm_is_removed(struct dlm_ls *ls, int nodeid) | 361 | int dlm_is_removed(struct dlm_ls *ls, int nodeid) |
| 92 | { | 362 | { |
| 93 | struct dlm_member *memb; | 363 | if (find_memb(&ls->ls_nodes_gone, nodeid)) |
| 94 | 364 | return 1; | |
| 95 | list_for_each_entry(memb, &ls->ls_nodes_gone, list) { | ||
| 96 | if (memb->nodeid == nodeid) | ||
| 97 | return 1; | ||
| 98 | } | ||
| 99 | return 0; | 365 | return 0; |
| 100 | } | 366 | } |
| 101 | 367 | ||
| @@ -176,7 +442,7 @@ static int ping_members(struct dlm_ls *ls) | |||
| 176 | error = dlm_recovery_stopped(ls); | 442 | error = dlm_recovery_stopped(ls); |
| 177 | if (error) | 443 | if (error) |
| 178 | break; | 444 | break; |
| 179 | error = dlm_rcom_status(ls, memb->nodeid); | 445 | error = dlm_rcom_status(ls, memb->nodeid, 0); |
| 180 | if (error) | 446 | if (error) |
| 181 | break; | 447 | break; |
| 182 | } | 448 | } |
| @@ -186,10 +452,88 @@ static int ping_members(struct dlm_ls *ls) | |||
| 186 | return error; | 452 | return error; |
| 187 | } | 453 | } |
| 188 | 454 | ||
| 455 | static void dlm_lsop_recover_prep(struct dlm_ls *ls) | ||
| 456 | { | ||
| 457 | if (!ls->ls_ops || !ls->ls_ops->recover_prep) | ||
| 458 | return; | ||
| 459 | ls->ls_ops->recover_prep(ls->ls_ops_arg); | ||
| 460 | } | ||
| 461 | |||
| 462 | static void dlm_lsop_recover_slot(struct dlm_ls *ls, struct dlm_member *memb) | ||
| 463 | { | ||
| 464 | struct dlm_slot slot; | ||
| 465 | uint32_t seq; | ||
| 466 | int error; | ||
| 467 | |||
| 468 | if (!ls->ls_ops || !ls->ls_ops->recover_slot) | ||
| 469 | return; | ||
| 470 | |||
| 471 | /* if there is no comms connection with this node | ||
| 472 | or the present comms connection is newer | ||
| 473 | than the one when this member was added, then | ||
| 474 | we consider the node to have failed (versus | ||
| 475 | being removed due to dlm_release_lockspace) */ | ||
| 476 | |||
| 477 | error = dlm_comm_seq(memb->nodeid, &seq); | ||
| 478 | |||
| 479 | if (!error && seq == memb->comm_seq) | ||
| 480 | return; | ||
| 481 | |||
| 482 | slot.nodeid = memb->nodeid; | ||
| 483 | slot.slot = memb->slot; | ||
| 484 | |||
| 485 | ls->ls_ops->recover_slot(ls->ls_ops_arg, &slot); | ||
| 486 | } | ||
| 487 | |||
| 488 | void dlm_lsop_recover_done(struct dlm_ls *ls) | ||
| 489 | { | ||
| 490 | struct dlm_member *memb; | ||
| 491 | struct dlm_slot *slots; | ||
| 492 | int i, num; | ||
| 493 | |||
| 494 | if (!ls->ls_ops || !ls->ls_ops->recover_done) | ||
| 495 | return; | ||
| 496 | |||
| 497 | num = ls->ls_num_nodes; | ||
| 498 | |||
| 499 | slots = kzalloc(num * sizeof(struct dlm_slot), GFP_KERNEL); | ||
| 500 | if (!slots) | ||
| 501 | return; | ||
| 502 | |||
| 503 | i = 0; | ||
| 504 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
| 505 | if (i == num) { | ||
| 506 | log_error(ls, "dlm_lsop_recover_done bad num %d", num); | ||
| 507 | goto out; | ||
| 508 | } | ||
| 509 | slots[i].nodeid = memb->nodeid; | ||
| 510 | slots[i].slot = memb->slot; | ||
| 511 | i++; | ||
| 512 | } | ||
| 513 | |||
| 514 | ls->ls_ops->recover_done(ls->ls_ops_arg, slots, num, | ||
| 515 | ls->ls_slot, ls->ls_generation); | ||
| 516 | out: | ||
| 517 | kfree(slots); | ||
| 518 | } | ||
| 519 | |||
| 520 | static struct dlm_config_node *find_config_node(struct dlm_recover *rv, | ||
| 521 | int nodeid) | ||
| 522 | { | ||
| 523 | int i; | ||
| 524 | |||
| 525 | for (i = 0; i < rv->nodes_count; i++) { | ||
| 526 | if (rv->nodes[i].nodeid == nodeid) | ||
| 527 | return &rv->nodes[i]; | ||
| 528 | } | ||
| 529 | return NULL; | ||
| 530 | } | ||
| 531 | |||
| 189 | int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) | 532 | int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) |
| 190 | { | 533 | { |
| 191 | struct dlm_member *memb, *safe; | 534 | struct dlm_member *memb, *safe; |
| 192 | int i, error, found, pos = 0, neg = 0, low = -1; | 535 | struct dlm_config_node *node; |
| 536 | int i, error, neg = 0, low = -1; | ||
| 193 | 537 | ||
| 194 | /* previously removed members that we've not finished removing need to | 538 | /* previously removed members that we've not finished removing need to |
| 195 | count as a negative change so the "neg" recovery steps will happen */ | 539 | count as a negative change so the "neg" recovery steps will happen */ |
| @@ -202,46 +546,32 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) | |||
| 202 | /* move departed members from ls_nodes to ls_nodes_gone */ | 546 | /* move departed members from ls_nodes to ls_nodes_gone */ |
| 203 | 547 | ||
| 204 | list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) { | 548 | list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) { |
| 205 | found = 0; | 549 | node = find_config_node(rv, memb->nodeid); |
| 206 | for (i = 0; i < rv->node_count; i++) { | 550 | if (node && !node->new) |
| 207 | if (memb->nodeid == rv->nodeids[i]) { | 551 | continue; |
| 208 | found = 1; | ||
| 209 | break; | ||
| 210 | } | ||
| 211 | } | ||
| 212 | 552 | ||
| 213 | if (!found) { | 553 | if (!node) { |
| 214 | neg++; | ||
| 215 | dlm_remove_member(ls, memb); | ||
| 216 | log_debug(ls, "remove member %d", memb->nodeid); | 554 | log_debug(ls, "remove member %d", memb->nodeid); |
| 555 | } else { | ||
| 556 | /* removed and re-added */ | ||
| 557 | log_debug(ls, "remove member %d comm_seq %u %u", | ||
| 558 | memb->nodeid, memb->comm_seq, node->comm_seq); | ||
| 217 | } | 559 | } |
| 218 | } | ||
| 219 | |||
| 220 | /* Add an entry to ls_nodes_gone for members that were removed and | ||
| 221 | then added again, so that previous state for these nodes will be | ||
| 222 | cleared during recovery. */ | ||
| 223 | |||
| 224 | for (i = 0; i < rv->new_count; i++) { | ||
| 225 | if (!dlm_is_member(ls, rv->new[i])) | ||
| 226 | continue; | ||
| 227 | log_debug(ls, "new nodeid %d is a re-added member", rv->new[i]); | ||
| 228 | 560 | ||
| 229 | memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS); | ||
| 230 | if (!memb) | ||
| 231 | return -ENOMEM; | ||
| 232 | memb->nodeid = rv->new[i]; | ||
| 233 | list_add_tail(&memb->list, &ls->ls_nodes_gone); | ||
| 234 | neg++; | 561 | neg++; |
| 562 | list_move(&memb->list, &ls->ls_nodes_gone); | ||
| 563 | ls->ls_num_nodes--; | ||
| 564 | dlm_lsop_recover_slot(ls, memb); | ||
| 235 | } | 565 | } |
| 236 | 566 | ||
| 237 | /* add new members to ls_nodes */ | 567 | /* add new members to ls_nodes */ |
| 238 | 568 | ||
| 239 | for (i = 0; i < rv->node_count; i++) { | 569 | for (i = 0; i < rv->nodes_count; i++) { |
| 240 | if (dlm_is_member(ls, rv->nodeids[i])) | 570 | node = &rv->nodes[i]; |
| 571 | if (dlm_is_member(ls, node->nodeid)) | ||
| 241 | continue; | 572 | continue; |
| 242 | dlm_add_member(ls, rv->nodeids[i]); | 573 | dlm_add_member(ls, node); |
| 243 | pos++; | 574 | log_debug(ls, "add member %d", node->nodeid); |
| 244 | log_debug(ls, "add member %d", rv->nodeids[i]); | ||
| 245 | } | 575 | } |
| 246 | 576 | ||
| 247 | list_for_each_entry(memb, &ls->ls_nodes, list) { | 577 | list_for_each_entry(memb, &ls->ls_nodes, list) { |
| @@ -251,7 +581,6 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) | |||
| 251 | ls->ls_low_nodeid = low; | 581 | ls->ls_low_nodeid = low; |
| 252 | 582 | ||
| 253 | make_member_array(ls); | 583 | make_member_array(ls); |
| 254 | dlm_set_recover_status(ls, DLM_RS_NODES); | ||
| 255 | *neg_out = neg; | 584 | *neg_out = neg; |
| 256 | 585 | ||
| 257 | error = ping_members(ls); | 586 | error = ping_members(ls); |
| @@ -261,12 +590,8 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) | |||
| 261 | ls->ls_members_result = error; | 590 | ls->ls_members_result = error; |
| 262 | complete(&ls->ls_members_done); | 591 | complete(&ls->ls_members_done); |
| 263 | } | 592 | } |
| 264 | if (error) | ||
| 265 | goto out; | ||
| 266 | 593 | ||
| 267 | error = dlm_recover_members_wait(ls); | 594 | log_debug(ls, "dlm_recover_members %d nodes", ls->ls_num_nodes); |
| 268 | out: | ||
| 269 | log_debug(ls, "total members %d error %d", ls->ls_num_nodes, error); | ||
| 270 | return error; | 595 | return error; |
| 271 | } | 596 | } |
| 272 | 597 | ||
| @@ -327,26 +652,35 @@ int dlm_ls_stop(struct dlm_ls *ls) | |||
| 327 | */ | 652 | */ |
| 328 | 653 | ||
| 329 | dlm_recoverd_suspend(ls); | 654 | dlm_recoverd_suspend(ls); |
| 655 | |||
| 656 | spin_lock(&ls->ls_recover_lock); | ||
| 657 | kfree(ls->ls_slots); | ||
| 658 | ls->ls_slots = NULL; | ||
| 659 | ls->ls_num_slots = 0; | ||
| 660 | ls->ls_slots_size = 0; | ||
| 330 | ls->ls_recover_status = 0; | 661 | ls->ls_recover_status = 0; |
| 662 | spin_unlock(&ls->ls_recover_lock); | ||
| 663 | |||
| 331 | dlm_recoverd_resume(ls); | 664 | dlm_recoverd_resume(ls); |
| 332 | 665 | ||
| 333 | if (!ls->ls_recover_begin) | 666 | if (!ls->ls_recover_begin) |
| 334 | ls->ls_recover_begin = jiffies; | 667 | ls->ls_recover_begin = jiffies; |
| 668 | |||
| 669 | dlm_lsop_recover_prep(ls); | ||
| 335 | return 0; | 670 | return 0; |
| 336 | } | 671 | } |
| 337 | 672 | ||
| 338 | int dlm_ls_start(struct dlm_ls *ls) | 673 | int dlm_ls_start(struct dlm_ls *ls) |
| 339 | { | 674 | { |
| 340 | struct dlm_recover *rv = NULL, *rv_old; | 675 | struct dlm_recover *rv = NULL, *rv_old; |
| 341 | int *ids = NULL, *new = NULL; | 676 | struct dlm_config_node *nodes; |
| 342 | int error, ids_count = 0, new_count = 0; | 677 | int error, count; |
| 343 | 678 | ||
| 344 | rv = kzalloc(sizeof(struct dlm_recover), GFP_NOFS); | 679 | rv = kzalloc(sizeof(struct dlm_recover), GFP_NOFS); |
| 345 | if (!rv) | 680 | if (!rv) |
| 346 | return -ENOMEM; | 681 | return -ENOMEM; |
| 347 | 682 | ||
| 348 | error = dlm_nodeid_list(ls->ls_name, &ids, &ids_count, | 683 | error = dlm_config_nodes(ls->ls_name, &nodes, &count); |
| 349 | &new, &new_count); | ||
| 350 | if (error < 0) | 684 | if (error < 0) |
| 351 | goto fail; | 685 | goto fail; |
| 352 | 686 | ||
| @@ -361,10 +695,8 @@ int dlm_ls_start(struct dlm_ls *ls) | |||
| 361 | goto fail; | 695 | goto fail; |
| 362 | } | 696 | } |
| 363 | 697 | ||
| 364 | rv->nodeids = ids; | 698 | rv->nodes = nodes; |
| 365 | rv->node_count = ids_count; | 699 | rv->nodes_count = count; |
| 366 | rv->new = new; | ||
| 367 | rv->new_count = new_count; | ||
| 368 | rv->seq = ++ls->ls_recover_seq; | 700 | rv->seq = ++ls->ls_recover_seq; |
| 369 | rv_old = ls->ls_recover_args; | 701 | rv_old = ls->ls_recover_args; |
| 370 | ls->ls_recover_args = rv; | 702 | ls->ls_recover_args = rv; |
| @@ -372,9 +704,8 @@ int dlm_ls_start(struct dlm_ls *ls) | |||
| 372 | 704 | ||
| 373 | if (rv_old) { | 705 | if (rv_old) { |
| 374 | log_error(ls, "unused recovery %llx %d", | 706 | log_error(ls, "unused recovery %llx %d", |
| 375 | (unsigned long long)rv_old->seq, rv_old->node_count); | 707 | (unsigned long long)rv_old->seq, rv_old->nodes_count); |
| 376 | kfree(rv_old->nodeids); | 708 | kfree(rv_old->nodes); |
| 377 | kfree(rv_old->new); | ||
| 378 | kfree(rv_old); | 709 | kfree(rv_old); |
| 379 | } | 710 | } |
| 380 | 711 | ||
| @@ -383,8 +714,7 @@ int dlm_ls_start(struct dlm_ls *ls) | |||
| 383 | 714 | ||
| 384 | fail: | 715 | fail: |
| 385 | kfree(rv); | 716 | kfree(rv); |
| 386 | kfree(ids); | 717 | kfree(nodes); |
| 387 | kfree(new); | ||
| 388 | return error; | 718 | return error; |
| 389 | } | 719 | } |
| 390 | 720 | ||
diff --git a/fs/dlm/member.h b/fs/dlm/member.h index 7a26fca1e0b5..3deb70661c69 100644 --- a/fs/dlm/member.h +++ b/fs/dlm/member.h | |||
| @@ -1,7 +1,7 @@ | |||
| 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 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
| 7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
| @@ -20,6 +20,14 @@ void dlm_clear_members_gone(struct dlm_ls *ls); | |||
| 20 | int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv,int *neg_out); | 20 | int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv,int *neg_out); |
| 21 | int dlm_is_removed(struct dlm_ls *ls, int nodeid); | 21 | int dlm_is_removed(struct dlm_ls *ls, int nodeid); |
| 22 | int dlm_is_member(struct dlm_ls *ls, int nodeid); | 22 | int dlm_is_member(struct dlm_ls *ls, int nodeid); |
| 23 | int dlm_slots_version(struct dlm_header *h); | ||
| 24 | void dlm_slot_save(struct dlm_ls *ls, struct dlm_rcom *rc, | ||
| 25 | struct dlm_member *memb); | ||
| 26 | void dlm_slots_copy_out(struct dlm_ls *ls, struct dlm_rcom *rc); | ||
| 27 | int dlm_slots_copy_in(struct dlm_ls *ls); | ||
| 28 | int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size, | ||
| 29 | struct dlm_slot **slots_out, uint32_t *gen_out); | ||
| 30 | void dlm_lsop_recover_done(struct dlm_ls *ls); | ||
| 23 | 31 | ||
| 24 | #endif /* __MEMBER_DOT_H__ */ | 32 | #endif /* __MEMBER_DOT_H__ */ |
| 25 | 33 | ||
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index f10a50f24e8f..ac5c616c9696 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include "memory.h" | 23 | #include "memory.h" |
| 24 | #include "lock.h" | 24 | #include "lock.h" |
| 25 | #include "util.h" | 25 | #include "util.h" |
| 26 | #include "member.h" | ||
| 26 | 27 | ||
| 27 | 28 | ||
| 28 | static int rcom_response(struct dlm_ls *ls) | 29 | static int rcom_response(struct dlm_ls *ls) |
| @@ -72,20 +73,30 @@ static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh, | |||
| 72 | dlm_lowcomms_commit_buffer(mh); | 73 | dlm_lowcomms_commit_buffer(mh); |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 76 | static void set_rcom_status(struct dlm_ls *ls, struct rcom_status *rs, | ||
| 77 | uint32_t flags) | ||
| 78 | { | ||
| 79 | rs->rs_flags = cpu_to_le32(flags); | ||
| 80 | } | ||
| 81 | |||
| 75 | /* When replying to a status request, a node also sends back its | 82 | /* When replying to a status request, a node also sends back its |
| 76 | configuration values. The requesting node then checks that the remote | 83 | configuration values. The requesting node then checks that the remote |
| 77 | node is configured the same way as itself. */ | 84 | node is configured the same way as itself. */ |
| 78 | 85 | ||
| 79 | static void make_config(struct dlm_ls *ls, struct rcom_config *rf) | 86 | static void set_rcom_config(struct dlm_ls *ls, struct rcom_config *rf, |
| 87 | uint32_t num_slots) | ||
| 80 | { | 88 | { |
| 81 | rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen); | 89 | rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen); |
| 82 | rf->rf_lsflags = cpu_to_le32(ls->ls_exflags); | 90 | rf->rf_lsflags = cpu_to_le32(ls->ls_exflags); |
| 91 | |||
| 92 | rf->rf_our_slot = cpu_to_le16(ls->ls_slot); | ||
| 93 | rf->rf_num_slots = cpu_to_le16(num_slots); | ||
| 94 | rf->rf_generation = cpu_to_le32(ls->ls_generation); | ||
| 83 | } | 95 | } |
| 84 | 96 | ||
| 85 | static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) | 97 | static int check_rcom_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) |
| 86 | { | 98 | { |
| 87 | struct rcom_config *rf = (struct rcom_config *) rc->rc_buf; | 99 | struct rcom_config *rf = (struct rcom_config *) rc->rc_buf; |
| 88 | size_t conf_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); | ||
| 89 | 100 | ||
| 90 | if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) { | 101 | if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) { |
| 91 | log_error(ls, "version mismatch: %x nodeid %d: %x", | 102 | log_error(ls, "version mismatch: %x nodeid %d: %x", |
| @@ -94,12 +105,6 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) | |||
| 94 | return -EPROTO; | 105 | return -EPROTO; |
| 95 | } | 106 | } |
| 96 | 107 | ||
| 97 | if (rc->rc_header.h_length < conf_size) { | ||
| 98 | log_error(ls, "config too short: %d nodeid %d", | ||
| 99 | rc->rc_header.h_length, nodeid); | ||
| 100 | return -EPROTO; | ||
| 101 | } | ||
| 102 | |||
| 103 | if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen || | 108 | if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen || |
| 104 | le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) { | 109 | le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) { |
| 105 | log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", | 110 | log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", |
| @@ -127,7 +132,18 @@ static void disallow_sync_reply(struct dlm_ls *ls) | |||
| 127 | spin_unlock(&ls->ls_rcom_spin); | 132 | spin_unlock(&ls->ls_rcom_spin); |
| 128 | } | 133 | } |
| 129 | 134 | ||
| 130 | int dlm_rcom_status(struct dlm_ls *ls, int nodeid) | 135 | /* |
| 136 | * low nodeid gathers one slot value at a time from each node. | ||
| 137 | * it sets need_slots=0, and saves rf_our_slot returned from each | ||
| 138 | * rcom_config. | ||
| 139 | * | ||
| 140 | * other nodes gather all slot values at once from the low nodeid. | ||
| 141 | * they set need_slots=1, and ignore the rf_our_slot returned from each | ||
| 142 | * rcom_config. they use the rf_num_slots returned from the low | ||
| 143 | * node's rcom_config. | ||
| 144 | */ | ||
| 145 | |||
| 146 | int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags) | ||
| 131 | { | 147 | { |
| 132 | struct dlm_rcom *rc; | 148 | struct dlm_rcom *rc; |
| 133 | struct dlm_mhandle *mh; | 149 | struct dlm_mhandle *mh; |
| @@ -141,10 +157,13 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) | |||
| 141 | goto out; | 157 | goto out; |
| 142 | } | 158 | } |
| 143 | 159 | ||
| 144 | error = create_rcom(ls, nodeid, DLM_RCOM_STATUS, 0, &rc, &mh); | 160 | error = create_rcom(ls, nodeid, DLM_RCOM_STATUS, |
| 161 | sizeof(struct rcom_status), &rc, &mh); | ||
| 145 | if (error) | 162 | if (error) |
| 146 | goto out; | 163 | goto out; |
| 147 | 164 | ||
| 165 | set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags); | ||
| 166 | |||
| 148 | allow_sync_reply(ls, &rc->rc_id); | 167 | allow_sync_reply(ls, &rc->rc_id); |
| 149 | memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size); | 168 | memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size); |
| 150 | 169 | ||
| @@ -161,8 +180,11 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) | |||
| 161 | /* we pretend the remote lockspace exists with 0 status */ | 180 | /* we pretend the remote lockspace exists with 0 status */ |
| 162 | log_debug(ls, "remote node %d not ready", nodeid); | 181 | log_debug(ls, "remote node %d not ready", nodeid); |
| 163 | rc->rc_result = 0; | 182 | rc->rc_result = 0; |
| 164 | } else | 183 | error = 0; |
| 165 | error = check_config(ls, rc, nodeid); | 184 | } else { |
| 185 | error = check_rcom_config(ls, rc, nodeid); | ||
| 186 | } | ||
| 187 | |||
| 166 | /* the caller looks at rc_result for the remote recovery status */ | 188 | /* the caller looks at rc_result for the remote recovery status */ |
| 167 | out: | 189 | out: |
| 168 | return error; | 190 | return error; |
| @@ -172,17 +194,60 @@ static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in) | |||
| 172 | { | 194 | { |
| 173 | struct dlm_rcom *rc; | 195 | struct dlm_rcom *rc; |
| 174 | struct dlm_mhandle *mh; | 196 | struct dlm_mhandle *mh; |
| 175 | int error, nodeid = rc_in->rc_header.h_nodeid; | 197 | struct rcom_status *rs; |
| 198 | uint32_t status; | ||
| 199 | int nodeid = rc_in->rc_header.h_nodeid; | ||
| 200 | int len = sizeof(struct rcom_config); | ||
| 201 | int num_slots = 0; | ||
| 202 | int error; | ||
| 203 | |||
| 204 | if (!dlm_slots_version(&rc_in->rc_header)) { | ||
| 205 | status = dlm_recover_status(ls); | ||
| 206 | goto do_create; | ||
| 207 | } | ||
| 208 | |||
| 209 | rs = (struct rcom_status *)rc_in->rc_buf; | ||
| 176 | 210 | ||
| 211 | if (!(rs->rs_flags & DLM_RSF_NEED_SLOTS)) { | ||
| 212 | status = dlm_recover_status(ls); | ||
| 213 | goto do_create; | ||
| 214 | } | ||
| 215 | |||
| 216 | spin_lock(&ls->ls_recover_lock); | ||
| 217 | status = ls->ls_recover_status; | ||
| 218 | num_slots = ls->ls_num_slots; | ||
| 219 | spin_unlock(&ls->ls_recover_lock); | ||
| 220 | len += num_slots * sizeof(struct rcom_slot); | ||
| 221 | |||
| 222 | do_create: | ||
| 177 | error = create_rcom(ls, nodeid, DLM_RCOM_STATUS_REPLY, | 223 | error = create_rcom(ls, nodeid, DLM_RCOM_STATUS_REPLY, |
| 178 | sizeof(struct rcom_config), &rc, &mh); | 224 | len, &rc, &mh); |
| 179 | if (error) | 225 | if (error) |
| 180 | return; | 226 | return; |
| 227 | |||
| 181 | rc->rc_id = rc_in->rc_id; | 228 | rc->rc_id = rc_in->rc_id; |
| 182 | rc->rc_seq_reply = rc_in->rc_seq; | 229 | rc->rc_seq_reply = rc_in->rc_seq; |
| 183 | rc->rc_result = dlm_recover_status(ls); | 230 | rc->rc_result = status; |
| 184 | make_config(ls, (struct rcom_config *) rc->rc_buf); | 231 | |
| 232 | set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, num_slots); | ||
| 233 | |||
| 234 | if (!num_slots) | ||
| 235 | goto do_send; | ||
| 236 | |||
| 237 | spin_lock(&ls->ls_recover_lock); | ||
| 238 | if (ls->ls_num_slots != num_slots) { | ||
| 239 | spin_unlock(&ls->ls_recover_lock); | ||
| 240 | log_debug(ls, "receive_rcom_status num_slots %d to %d", | ||
| 241 | num_slots, ls->ls_num_slots); | ||
| 242 | rc->rc_result = 0; | ||
| 243 | set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, 0); | ||
| 244 | goto do_send; | ||
| 245 | } | ||
| 246 | |||
| 247 | dlm_slots_copy_out(ls, rc); | ||
| 248 | spin_unlock(&ls->ls_recover_lock); | ||
| 185 | 249 | ||
| 250 | do_send: | ||
| 186 | send_rcom(ls, mh, rc); | 251 | send_rcom(ls, mh, rc); |
| 187 | } | 252 | } |
| 188 | 253 | ||
diff --git a/fs/dlm/rcom.h b/fs/dlm/rcom.h index b09abd29ba38..206723ab744d 100644 --- a/fs/dlm/rcom.h +++ b/fs/dlm/rcom.h | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | #ifndef __RCOM_DOT_H__ | 14 | #ifndef __RCOM_DOT_H__ |
| 15 | #define __RCOM_DOT_H__ | 15 | #define __RCOM_DOT_H__ |
| 16 | 16 | ||
| 17 | int dlm_rcom_status(struct dlm_ls *ls, int nodeid); | 17 | int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags); |
| 18 | int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,int last_len); | 18 | int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,int last_len); |
| 19 | int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid); | 19 | int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid); |
| 20 | int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); | 20 | int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); |
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index 14638235f7b2..34d5adf1fce7 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c | |||
| @@ -85,14 +85,20 @@ uint32_t dlm_recover_status(struct dlm_ls *ls) | |||
| 85 | return status; | 85 | return status; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static void _set_recover_status(struct dlm_ls *ls, uint32_t status) | ||
| 89 | { | ||
| 90 | ls->ls_recover_status |= status; | ||
| 91 | } | ||
| 92 | |||
| 88 | void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status) | 93 | void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status) |
| 89 | { | 94 | { |
| 90 | spin_lock(&ls->ls_recover_lock); | 95 | spin_lock(&ls->ls_recover_lock); |
| 91 | ls->ls_recover_status |= status; | 96 | _set_recover_status(ls, status); |
| 92 | spin_unlock(&ls->ls_recover_lock); | 97 | spin_unlock(&ls->ls_recover_lock); |
| 93 | } | 98 | } |
| 94 | 99 | ||
| 95 | static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status) | 100 | static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status, |
| 101 | int save_slots) | ||
| 96 | { | 102 | { |
| 97 | struct dlm_rcom *rc = ls->ls_recover_buf; | 103 | struct dlm_rcom *rc = ls->ls_recover_buf; |
| 98 | struct dlm_member *memb; | 104 | struct dlm_member *memb; |
| @@ -106,10 +112,13 @@ static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status) | |||
| 106 | goto out; | 112 | goto out; |
| 107 | } | 113 | } |
| 108 | 114 | ||
| 109 | error = dlm_rcom_status(ls, memb->nodeid); | 115 | error = dlm_rcom_status(ls, memb->nodeid, 0); |
| 110 | if (error) | 116 | if (error) |
| 111 | goto out; | 117 | goto out; |
| 112 | 118 | ||
| 119 | if (save_slots) | ||
| 120 | dlm_slot_save(ls, rc, memb); | ||
| 121 | |||
| 113 | if (rc->rc_result & wait_status) | 122 | if (rc->rc_result & wait_status) |
| 114 | break; | 123 | break; |
| 115 | if (delay < 1000) | 124 | if (delay < 1000) |
| @@ -121,7 +130,8 @@ static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status) | |||
| 121 | return error; | 130 | return error; |
| 122 | } | 131 | } |
| 123 | 132 | ||
| 124 | static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status) | 133 | static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status, |
| 134 | uint32_t status_flags) | ||
| 125 | { | 135 | { |
| 126 | struct dlm_rcom *rc = ls->ls_recover_buf; | 136 | struct dlm_rcom *rc = ls->ls_recover_buf; |
| 127 | int error = 0, delay = 0, nodeid = ls->ls_low_nodeid; | 137 | int error = 0, delay = 0, nodeid = ls->ls_low_nodeid; |
| @@ -132,7 +142,7 @@ static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status) | |||
| 132 | goto out; | 142 | goto out; |
| 133 | } | 143 | } |
| 134 | 144 | ||
| 135 | error = dlm_rcom_status(ls, nodeid); | 145 | error = dlm_rcom_status(ls, nodeid, status_flags); |
| 136 | if (error) | 146 | if (error) |
| 137 | break; | 147 | break; |
| 138 | 148 | ||
| @@ -152,18 +162,56 @@ static int wait_status(struct dlm_ls *ls, uint32_t status) | |||
| 152 | int error; | 162 | int error; |
| 153 | 163 | ||
| 154 | if (ls->ls_low_nodeid == dlm_our_nodeid()) { | 164 | if (ls->ls_low_nodeid == dlm_our_nodeid()) { |
| 155 | error = wait_status_all(ls, status); | 165 | error = wait_status_all(ls, status, 0); |
| 156 | if (!error) | 166 | if (!error) |
| 157 | dlm_set_recover_status(ls, status_all); | 167 | dlm_set_recover_status(ls, status_all); |
| 158 | } else | 168 | } else |
| 159 | error = wait_status_low(ls, status_all); | 169 | error = wait_status_low(ls, status_all, 0); |
| 160 | 170 | ||
| 161 | return error; | 171 | return error; |
| 162 | } | 172 | } |
| 163 | 173 | ||
| 164 | int dlm_recover_members_wait(struct dlm_ls *ls) | 174 | int dlm_recover_members_wait(struct dlm_ls *ls) |
| 165 | { | 175 | { |
| 166 | return wait_status(ls, DLM_RS_NODES); | 176 | struct dlm_member *memb; |
| 177 | struct dlm_slot *slots; | ||
| 178 | int num_slots, slots_size; | ||
| 179 | int error, rv; | ||
| 180 | uint32_t gen; | ||
| 181 | |||
| 182 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
| 183 | memb->slot = -1; | ||
| 184 | memb->generation = 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | if (ls->ls_low_nodeid == dlm_our_nodeid()) { | ||
| 188 | error = wait_status_all(ls, DLM_RS_NODES, 1); | ||
| 189 | if (error) | ||
| 190 | goto out; | ||
| 191 | |||
| 192 | /* slots array is sparse, slots_size may be > num_slots */ | ||
| 193 | |||
| 194 | rv = dlm_slots_assign(ls, &num_slots, &slots_size, &slots, &gen); | ||
| 195 | if (!rv) { | ||
| 196 | spin_lock(&ls->ls_recover_lock); | ||
| 197 | _set_recover_status(ls, DLM_RS_NODES_ALL); | ||
| 198 | ls->ls_num_slots = num_slots; | ||
| 199 | ls->ls_slots_size = slots_size; | ||
| 200 | ls->ls_slots = slots; | ||
| 201 | ls->ls_generation = gen; | ||
| 202 | spin_unlock(&ls->ls_recover_lock); | ||
| 203 | } else { | ||
| 204 | dlm_set_recover_status(ls, DLM_RS_NODES_ALL); | ||
| 205 | } | ||
| 206 | } else { | ||
| 207 | error = wait_status_low(ls, DLM_RS_NODES_ALL, DLM_RSF_NEED_SLOTS); | ||
| 208 | if (error) | ||
| 209 | goto out; | ||
| 210 | |||
| 211 | dlm_slots_copy_in(ls); | ||
| 212 | } | ||
| 213 | out: | ||
| 214 | return error; | ||
| 167 | } | 215 | } |
| 168 | 216 | ||
| 169 | int dlm_recover_directory_wait(struct dlm_ls *ls) | 217 | int dlm_recover_directory_wait(struct dlm_ls *ls) |
| @@ -542,8 +590,6 @@ int dlm_recover_locks(struct dlm_ls *ls) | |||
| 542 | out: | 590 | out: |
| 543 | if (error) | 591 | if (error) |
| 544 | recover_list_clear(ls); | 592 | recover_list_clear(ls); |
| 545 | else | ||
| 546 | dlm_set_recover_status(ls, DLM_RS_LOCKS); | ||
| 547 | return error; | 593 | return error; |
| 548 | } | 594 | } |
| 549 | 595 | ||
| @@ -715,6 +761,7 @@ void dlm_recover_rsbs(struct dlm_ls *ls) | |||
| 715 | 761 | ||
| 716 | int dlm_create_root_list(struct dlm_ls *ls) | 762 | int dlm_create_root_list(struct dlm_ls *ls) |
| 717 | { | 763 | { |
| 764 | struct rb_node *n; | ||
| 718 | struct dlm_rsb *r; | 765 | struct dlm_rsb *r; |
| 719 | int i, error = 0; | 766 | int i, error = 0; |
| 720 | 767 | ||
| @@ -727,7 +774,8 @@ int dlm_create_root_list(struct dlm_ls *ls) | |||
| 727 | 774 | ||
| 728 | for (i = 0; i < ls->ls_rsbtbl_size; i++) { | 775 | for (i = 0; i < ls->ls_rsbtbl_size; i++) { |
| 729 | spin_lock(&ls->ls_rsbtbl[i].lock); | 776 | spin_lock(&ls->ls_rsbtbl[i].lock); |
| 730 | list_for_each_entry(r, &ls->ls_rsbtbl[i].list, res_hashchain) { | 777 | for (n = rb_first(&ls->ls_rsbtbl[i].keep); n; n = rb_next(n)) { |
| 778 | r = rb_entry(n, struct dlm_rsb, res_hashnode); | ||
| 731 | list_add(&r->res_root_list, &ls->ls_root_list); | 779 | list_add(&r->res_root_list, &ls->ls_root_list); |
| 732 | dlm_hold_rsb(r); | 780 | dlm_hold_rsb(r); |
| 733 | } | 781 | } |
| @@ -741,7 +789,8 @@ int dlm_create_root_list(struct dlm_ls *ls) | |||
| 741 | continue; | 789 | continue; |
| 742 | } | 790 | } |
| 743 | 791 | ||
| 744 | list_for_each_entry(r, &ls->ls_rsbtbl[i].toss, res_hashchain) { | 792 | for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = rb_next(n)) { |
| 793 | r = rb_entry(n, struct dlm_rsb, res_hashnode); | ||
| 745 | list_add(&r->res_root_list, &ls->ls_root_list); | 794 | list_add(&r->res_root_list, &ls->ls_root_list); |
| 746 | dlm_hold_rsb(r); | 795 | dlm_hold_rsb(r); |
| 747 | } | 796 | } |
| @@ -771,16 +820,18 @@ void dlm_release_root_list(struct dlm_ls *ls) | |||
| 771 | 820 | ||
| 772 | void dlm_clear_toss_list(struct dlm_ls *ls) | 821 | void dlm_clear_toss_list(struct dlm_ls *ls) |
| 773 | { | 822 | { |
| 774 | struct dlm_rsb *r, *safe; | 823 | struct rb_node *n, *next; |
| 824 | struct dlm_rsb *rsb; | ||
| 775 | int i; | 825 | int i; |
| 776 | 826 | ||
| 777 | for (i = 0; i < ls->ls_rsbtbl_size; i++) { | 827 | for (i = 0; i < ls->ls_rsbtbl_size; i++) { |
| 778 | spin_lock(&ls->ls_rsbtbl[i].lock); | 828 | spin_lock(&ls->ls_rsbtbl[i].lock); |
| 779 | list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss, | 829 | for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = next) { |
| 780 | res_hashchain) { | 830 | next = rb_next(n);; |
| 781 | if (dlm_no_directory(ls) || !is_master(r)) { | 831 | rsb = rb_entry(n, struct dlm_rsb, res_hashnode); |
| 782 | list_del(&r->res_hashchain); | 832 | if (dlm_no_directory(ls) || !is_master(rsb)) { |
| 783 | dlm_free_rsb(r); | 833 | rb_erase(n, &ls->ls_rsbtbl[i].toss); |
| 834 | dlm_free_rsb(rsb); | ||
| 784 | } | 835 | } |
| 785 | } | 836 | } |
| 786 | spin_unlock(&ls->ls_rsbtbl[i].lock); | 837 | spin_unlock(&ls->ls_rsbtbl[i].lock); |
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 774da3cf92c6..3780caf7ae0c 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.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-2011 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 |
| @@ -54,7 +54,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
| 54 | unsigned long start; | 54 | unsigned long start; |
| 55 | int error, neg = 0; | 55 | int error, neg = 0; |
| 56 | 56 | ||
| 57 | log_debug(ls, "recover %llx", (unsigned long long)rv->seq); | 57 | log_debug(ls, "dlm_recover %llx", (unsigned long long)rv->seq); |
| 58 | 58 | ||
| 59 | mutex_lock(&ls->ls_recoverd_active); | 59 | mutex_lock(&ls->ls_recoverd_active); |
| 60 | 60 | ||
| @@ -76,14 +76,22 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
| 76 | 76 | ||
| 77 | /* | 77 | /* |
| 78 | * Add or remove nodes from the lockspace's ls_nodes list. | 78 | * Add or remove nodes from the lockspace's ls_nodes list. |
| 79 | * Also waits for all nodes to complete dlm_recover_members. | ||
| 80 | */ | 79 | */ |
| 81 | 80 | ||
| 82 | error = dlm_recover_members(ls, rv, &neg); | 81 | error = dlm_recover_members(ls, rv, &neg); |
| 83 | if (error) { | 82 | if (error) { |
| 84 | log_debug(ls, "recover_members failed %d", error); | 83 | log_debug(ls, "dlm_recover_members error %d", error); |
| 85 | goto fail; | 84 | goto fail; |
| 86 | } | 85 | } |
| 86 | |||
| 87 | dlm_set_recover_status(ls, DLM_RS_NODES); | ||
| 88 | |||
| 89 | error = dlm_recover_members_wait(ls); | ||
| 90 | if (error) { | ||
| 91 | log_debug(ls, "dlm_recover_members_wait error %d", error); | ||
| 92 | goto fail; | ||
| 93 | } | ||
| 94 | |||
| 87 | start = jiffies; | 95 | start = jiffies; |
| 88 | 96 | ||
| 89 | /* | 97 | /* |
| @@ -93,17 +101,15 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
| 93 | 101 | ||
| 94 | error = dlm_recover_directory(ls); | 102 | error = dlm_recover_directory(ls); |
| 95 | if (error) { | 103 | if (error) { |
| 96 | log_debug(ls, "recover_directory failed %d", error); | 104 | log_debug(ls, "dlm_recover_directory error %d", error); |
| 97 | goto fail; | 105 | goto fail; |
| 98 | } | 106 | } |
| 99 | 107 | ||
| 100 | /* | 108 | dlm_set_recover_status(ls, DLM_RS_DIR); |
| 101 | * Wait for all nodes to complete directory rebuild. | ||
| 102 | */ | ||
| 103 | 109 | ||
| 104 | error = dlm_recover_directory_wait(ls); | 110 | error = dlm_recover_directory_wait(ls); |
| 105 | if (error) { | 111 | if (error) { |
| 106 | log_debug(ls, "recover_directory_wait failed %d", error); | 112 | log_debug(ls, "dlm_recover_directory_wait error %d", error); |
| 107 | goto fail; | 113 | goto fail; |
| 108 | } | 114 | } |
| 109 | 115 | ||
| @@ -133,7 +139,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
| 133 | 139 | ||
| 134 | error = dlm_recover_masters(ls); | 140 | error = dlm_recover_masters(ls); |
| 135 | if (error) { | 141 | if (error) { |
| 136 | log_debug(ls, "recover_masters failed %d", error); | 142 | log_debug(ls, "dlm_recover_masters error %d", error); |
| 137 | goto fail; | 143 | goto fail; |
| 138 | } | 144 | } |
| 139 | 145 | ||
| @@ -143,13 +149,15 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
| 143 | 149 | ||
| 144 | error = dlm_recover_locks(ls); | 150 | error = dlm_recover_locks(ls); |
| 145 | if (error) { | 151 | if (error) { |
| 146 | log_debug(ls, "recover_locks failed %d", error); | 152 | log_debug(ls, "dlm_recover_locks error %d", error); |
| 147 | goto fail; | 153 | goto fail; |
| 148 | } | 154 | } |
| 149 | 155 | ||
| 156 | dlm_set_recover_status(ls, DLM_RS_LOCKS); | ||
| 157 | |||
| 150 | error = dlm_recover_locks_wait(ls); | 158 | error = dlm_recover_locks_wait(ls); |
| 151 | if (error) { | 159 | if (error) { |
| 152 | log_debug(ls, "recover_locks_wait failed %d", error); | 160 | log_debug(ls, "dlm_recover_locks_wait error %d", error); |
| 153 | goto fail; | 161 | goto fail; |
| 154 | } | 162 | } |
| 155 | 163 | ||
| @@ -170,7 +178,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
| 170 | 178 | ||
| 171 | error = dlm_recover_locks_wait(ls); | 179 | error = dlm_recover_locks_wait(ls); |
| 172 | if (error) { | 180 | if (error) { |
| 173 | log_debug(ls, "recover_locks_wait failed %d", error); | 181 | log_debug(ls, "dlm_recover_locks_wait error %d", error); |
| 174 | goto fail; | 182 | goto fail; |
| 175 | } | 183 | } |
| 176 | } | 184 | } |
| @@ -186,9 +194,10 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
| 186 | dlm_purge_requestqueue(ls); | 194 | dlm_purge_requestqueue(ls); |
| 187 | 195 | ||
| 188 | dlm_set_recover_status(ls, DLM_RS_DONE); | 196 | dlm_set_recover_status(ls, DLM_RS_DONE); |
| 197 | |||
| 189 | error = dlm_recover_done_wait(ls); | 198 | error = dlm_recover_done_wait(ls); |
| 190 | if (error) { | 199 | if (error) { |
| 191 | log_debug(ls, "recover_done_wait failed %d", error); | 200 | log_debug(ls, "dlm_recover_done_wait error %d", error); |
| 192 | goto fail; | 201 | goto fail; |
| 193 | } | 202 | } |
| 194 | 203 | ||
| @@ -200,34 +209,35 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
| 200 | 209 | ||
| 201 | error = enable_locking(ls, rv->seq); | 210 | error = enable_locking(ls, rv->seq); |
| 202 | if (error) { | 211 | if (error) { |
| 203 | log_debug(ls, "enable_locking failed %d", error); | 212 | log_debug(ls, "enable_locking error %d", error); |
| 204 | goto fail; | 213 | goto fail; |
| 205 | } | 214 | } |
| 206 | 215 | ||
| 207 | error = dlm_process_requestqueue(ls); | 216 | error = dlm_process_requestqueue(ls); |
| 208 | if (error) { | 217 | if (error) { |
| 209 | log_debug(ls, "process_requestqueue failed %d", error); | 218 | log_debug(ls, "dlm_process_requestqueue error %d", error); |
| 210 | goto fail; | 219 | goto fail; |
| 211 | } | 220 | } |
| 212 | 221 | ||
| 213 | error = dlm_recover_waiters_post(ls); | 222 | error = dlm_recover_waiters_post(ls); |
| 214 | if (error) { | 223 | if (error) { |
| 215 | log_debug(ls, "recover_waiters_post failed %d", error); | 224 | log_debug(ls, "dlm_recover_waiters_post error %d", error); |
| 216 | goto fail; | 225 | goto fail; |
| 217 | } | 226 | } |
| 218 | 227 | ||
| 219 | dlm_grant_after_purge(ls); | 228 | dlm_grant_after_purge(ls); |
| 220 | 229 | ||
| 221 | log_debug(ls, "recover %llx done: %u ms", | 230 | log_debug(ls, "dlm_recover %llx generation %u done: %u ms", |
| 222 | (unsigned long long)rv->seq, | 231 | (unsigned long long)rv->seq, ls->ls_generation, |
| 223 | jiffies_to_msecs(jiffies - start)); | 232 | jiffies_to_msecs(jiffies - start)); |
| 224 | mutex_unlock(&ls->ls_recoverd_active); | 233 | mutex_unlock(&ls->ls_recoverd_active); |
| 225 | 234 | ||
| 235 | dlm_lsop_recover_done(ls); | ||
| 226 | return 0; | 236 | return 0; |
| 227 | 237 | ||
| 228 | fail: | 238 | fail: |
| 229 | dlm_release_root_list(ls); | 239 | dlm_release_root_list(ls); |
| 230 | log_debug(ls, "recover %llx error %d", | 240 | log_debug(ls, "dlm_recover %llx error %d", |
| 231 | (unsigned long long)rv->seq, error); | 241 | (unsigned long long)rv->seq, error); |
| 232 | mutex_unlock(&ls->ls_recoverd_active); | 242 | mutex_unlock(&ls->ls_recoverd_active); |
| 233 | return error; | 243 | return error; |
| @@ -250,8 +260,7 @@ static void do_ls_recovery(struct dlm_ls *ls) | |||
| 250 | 260 | ||
| 251 | if (rv) { | 261 | if (rv) { |
| 252 | ls_recover(ls, rv); | 262 | ls_recover(ls, rv); |
| 253 | kfree(rv->nodeids); | 263 | kfree(rv->nodes); |
| 254 | kfree(rv->new); | ||
| 255 | kfree(rv); | 264 | kfree(rv); |
| 256 | } | 265 | } |
| 257 | } | 266 | } |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index d8ea60756403..eb4ed9ba3098 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
| @@ -392,8 +392,9 @@ static int device_create_lockspace(struct dlm_lspace_params *params) | |||
| 392 | if (!capable(CAP_SYS_ADMIN)) | 392 | if (!capable(CAP_SYS_ADMIN)) |
| 393 | return -EPERM; | 393 | return -EPERM; |
| 394 | 394 | ||
| 395 | error = dlm_new_lockspace(params->name, strlen(params->name), | 395 | error = dlm_new_lockspace(params->name, NULL, params->flags, |
| 396 | &lockspace, params->flags, DLM_USER_LVB_LEN); | 396 | DLM_USER_LVB_LEN, NULL, NULL, NULL, |
| 397 | &lockspace); | ||
| 397 | if (error) | 398 | if (error) |
| 398 | return error; | 399 | return error; |
| 399 | 400 | ||
