diff options
| -rw-r--r-- | fs/ocfs2/dlm/dlmcommon.h | 17 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 182 |
2 files changed, 198 insertions, 1 deletions
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index aa506d3e2ae6..b36d0bf77a5a 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h | |||
| @@ -447,6 +447,7 @@ enum { | |||
| 447 | DLM_BEGIN_RECO_MSG, /* 517 */ | 447 | DLM_BEGIN_RECO_MSG, /* 517 */ |
| 448 | DLM_FINALIZE_RECO_MSG, /* 518 */ | 448 | DLM_FINALIZE_RECO_MSG, /* 518 */ |
| 449 | DLM_QUERY_REGION, /* 519 */ | 449 | DLM_QUERY_REGION, /* 519 */ |
| 450 | DLM_QUERY_NODEINFO, /* 520 */ | ||
| 450 | }; | 451 | }; |
| 451 | 452 | ||
| 452 | struct dlm_reco_node_data | 453 | struct dlm_reco_node_data |
| @@ -737,6 +738,22 @@ struct dlm_query_region { | |||
| 737 | u8 qr_regions[O2HB_MAX_REGION_NAME_LEN * O2NM_MAX_REGIONS]; | 738 | u8 qr_regions[O2HB_MAX_REGION_NAME_LEN * O2NM_MAX_REGIONS]; |
| 738 | }; | 739 | }; |
| 739 | 740 | ||
| 741 | struct dlm_node_info { | ||
| 742 | u8 ni_nodenum; | ||
| 743 | u8 pad1; | ||
| 744 | u16 ni_ipv4_port; | ||
| 745 | u32 ni_ipv4_address; | ||
| 746 | }; | ||
| 747 | |||
| 748 | struct dlm_query_nodeinfo { | ||
| 749 | u8 qn_nodenum; | ||
| 750 | u8 qn_numnodes; | ||
| 751 | u8 qn_namelen; | ||
| 752 | u8 pad1; | ||
| 753 | u8 qn_domain[O2NM_MAX_NAME_LEN]; | ||
| 754 | struct dlm_node_info qn_nodes[O2NM_MAX_NODES]; | ||
| 755 | }; | ||
| 756 | |||
| 740 | struct dlm_exit_domain | 757 | struct dlm_exit_domain |
| 741 | { | 758 | { |
| 742 | u8 node_idx; | 759 | u8 node_idx; |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 49650756dfef..78d428f5e10e 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
| @@ -131,6 +131,7 @@ static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events); | |||
| 131 | * | 131 | * |
| 132 | * New in version 1.1: | 132 | * New in version 1.1: |
| 133 | * - Message DLM_QUERY_REGION added to support global heartbeat | 133 | * - Message DLM_QUERY_REGION added to support global heartbeat |
| 134 | * - Message DLM_QUERY_NODEINFO added to allow online node removes | ||
| 134 | */ | 135 | */ |
| 135 | static const struct dlm_protocol_version dlm_protocol = { | 136 | static const struct dlm_protocol_version dlm_protocol = { |
| 136 | .pv_major = 1, | 137 | .pv_major = 1, |
| @@ -1123,6 +1124,173 @@ bail: | |||
| 1123 | return status; | 1124 | return status; |
| 1124 | } | 1125 | } |
| 1125 | 1126 | ||
| 1127 | static int dlm_match_nodes(struct dlm_ctxt *dlm, struct dlm_query_nodeinfo *qn) | ||
| 1128 | { | ||
| 1129 | struct o2nm_node *local; | ||
| 1130 | struct dlm_node_info *remote; | ||
| 1131 | int i, j; | ||
| 1132 | int status = 0; | ||
| 1133 | |||
| 1134 | for (j = 0; j < qn->qn_numnodes; ++j) | ||
| 1135 | mlog(0, "Node %3d, %pI4:%u\n", qn->qn_nodes[j].ni_nodenum, | ||
| 1136 | &(qn->qn_nodes[j].ni_ipv4_address), | ||
| 1137 | ntohs(qn->qn_nodes[j].ni_ipv4_port)); | ||
| 1138 | |||
| 1139 | for (i = 0; i < O2NM_MAX_NODES && !status; ++i) { | ||
| 1140 | local = o2nm_get_node_by_num(i); | ||
| 1141 | remote = NULL; | ||
| 1142 | for (j = 0; j < qn->qn_numnodes; ++j) { | ||
| 1143 | if (qn->qn_nodes[j].ni_nodenum == i) { | ||
| 1144 | remote = &(qn->qn_nodes[j]); | ||
| 1145 | break; | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | if (!local && !remote) | ||
| 1150 | continue; | ||
| 1151 | |||
| 1152 | if ((local && !remote) || (!local && remote)) | ||
| 1153 | status = -EINVAL; | ||
| 1154 | |||
| 1155 | if (!status && | ||
| 1156 | ((remote->ni_nodenum != local->nd_num) || | ||
| 1157 | (remote->ni_ipv4_port != local->nd_ipv4_port) || | ||
| 1158 | (remote->ni_ipv4_address != local->nd_ipv4_address))) | ||
| 1159 | status = -EINVAL; | ||
| 1160 | |||
| 1161 | if (status) { | ||
| 1162 | if (remote && !local) | ||
| 1163 | mlog(ML_ERROR, "Domain %s: Node %d (%pI4:%u) " | ||
| 1164 | "registered in joining node %d but not in " | ||
| 1165 | "local node %d\n", qn->qn_domain, | ||
| 1166 | remote->ni_nodenum, | ||
| 1167 | &(remote->ni_ipv4_address), | ||
| 1168 | ntohs(remote->ni_ipv4_port), | ||
| 1169 | qn->qn_nodenum, dlm->node_num); | ||
| 1170 | if (local && !remote) | ||
| 1171 | mlog(ML_ERROR, "Domain %s: Node %d (%pI4:%u) " | ||
| 1172 | "registered in local node %d but not in " | ||
| 1173 | "joining node %d\n", qn->qn_domain, | ||
| 1174 | local->nd_num, &(local->nd_ipv4_address), | ||
| 1175 | ntohs(local->nd_ipv4_port), | ||
| 1176 | dlm->node_num, qn->qn_nodenum); | ||
| 1177 | BUG_ON((!local && !remote)); | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | if (local) | ||
| 1181 | o2nm_node_put(local); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | return status; | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | static int dlm_send_nodeinfo(struct dlm_ctxt *dlm, unsigned long *node_map) | ||
| 1188 | { | ||
| 1189 | struct dlm_query_nodeinfo *qn = NULL; | ||
| 1190 | struct o2nm_node *node; | ||
| 1191 | int ret = 0, status, count, i; | ||
| 1192 | |||
| 1193 | if (find_next_bit(node_map, O2NM_MAX_NODES, 0) >= O2NM_MAX_NODES) | ||
| 1194 | goto bail; | ||
| 1195 | |||
| 1196 | qn = kzalloc(sizeof(struct dlm_query_nodeinfo), GFP_KERNEL); | ||
| 1197 | if (!qn) { | ||
| 1198 | ret = -ENOMEM; | ||
| 1199 | mlog_errno(ret); | ||
| 1200 | goto bail; | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | for (i = 0, count = 0; i < O2NM_MAX_NODES; ++i) { | ||
| 1204 | node = o2nm_get_node_by_num(i); | ||
| 1205 | if (!node) | ||
| 1206 | continue; | ||
| 1207 | qn->qn_nodes[count].ni_nodenum = node->nd_num; | ||
| 1208 | qn->qn_nodes[count].ni_ipv4_port = node->nd_ipv4_port; | ||
| 1209 | qn->qn_nodes[count].ni_ipv4_address = node->nd_ipv4_address; | ||
| 1210 | mlog(0, "Node %3d, %pI4:%u\n", node->nd_num, | ||
| 1211 | &(node->nd_ipv4_address), ntohs(node->nd_ipv4_port)); | ||
| 1212 | ++count; | ||
| 1213 | o2nm_node_put(node); | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | qn->qn_nodenum = dlm->node_num; | ||
| 1217 | qn->qn_numnodes = count; | ||
| 1218 | qn->qn_namelen = strlen(dlm->name); | ||
| 1219 | memcpy(qn->qn_domain, dlm->name, qn->qn_namelen); | ||
| 1220 | |||
| 1221 | i = -1; | ||
| 1222 | while ((i = find_next_bit(node_map, O2NM_MAX_NODES, | ||
| 1223 | i + 1)) < O2NM_MAX_NODES) { | ||
| 1224 | if (i == dlm->node_num) | ||
| 1225 | continue; | ||
| 1226 | |||
| 1227 | mlog(0, "Sending nodeinfo to node %d\n", i); | ||
| 1228 | |||
| 1229 | ret = o2net_send_message(DLM_QUERY_NODEINFO, DLM_MOD_KEY, | ||
| 1230 | qn, sizeof(struct dlm_query_nodeinfo), | ||
| 1231 | i, &status); | ||
| 1232 | if (ret >= 0) | ||
| 1233 | ret = status; | ||
| 1234 | if (ret) { | ||
| 1235 | mlog(ML_ERROR, "node mismatch %d, node %d\n", ret, i); | ||
| 1236 | break; | ||
| 1237 | } | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | bail: | ||
| 1241 | kfree(qn); | ||
| 1242 | return ret; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | static int dlm_query_nodeinfo_handler(struct o2net_msg *msg, u32 len, | ||
| 1246 | void *data, void **ret_data) | ||
| 1247 | { | ||
| 1248 | struct dlm_query_nodeinfo *qn; | ||
| 1249 | struct dlm_ctxt *dlm = NULL; | ||
| 1250 | int locked = 0, status = -EINVAL; | ||
| 1251 | |||
| 1252 | qn = (struct dlm_query_nodeinfo *) msg->buf; | ||
| 1253 | |||
| 1254 | mlog(0, "Node %u queries nodes on domain %s\n", qn->qn_nodenum, | ||
| 1255 | qn->qn_domain); | ||
| 1256 | |||
| 1257 | spin_lock(&dlm_domain_lock); | ||
| 1258 | dlm = __dlm_lookup_domain_full(qn->qn_domain, qn->qn_namelen); | ||
| 1259 | if (!dlm) { | ||
| 1260 | mlog(ML_ERROR, "Node %d queried nodes on domain %s before " | ||
| 1261 | "join domain\n", qn->qn_nodenum, qn->qn_domain); | ||
| 1262 | goto bail; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | spin_lock(&dlm->spinlock); | ||
| 1266 | locked = 1; | ||
| 1267 | if (dlm->joining_node != qn->qn_nodenum) { | ||
| 1268 | mlog(ML_ERROR, "Node %d queried nodes on domain %s but " | ||
| 1269 | "joining node is %d\n", qn->qn_nodenum, qn->qn_domain, | ||
| 1270 | dlm->joining_node); | ||
| 1271 | goto bail; | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | /* Support for node query was added in 1.1 */ | ||
| 1275 | if (dlm->dlm_locking_proto.pv_major == 1 && | ||
| 1276 | dlm->dlm_locking_proto.pv_minor == 0) { | ||
| 1277 | mlog(ML_ERROR, "Node %d queried nodes on domain %s " | ||
| 1278 | "but active dlm protocol is %d.%d\n", qn->qn_nodenum, | ||
| 1279 | qn->qn_domain, dlm->dlm_locking_proto.pv_major, | ||
| 1280 | dlm->dlm_locking_proto.pv_minor); | ||
| 1281 | goto bail; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | status = dlm_match_nodes(dlm, qn); | ||
| 1285 | |||
| 1286 | bail: | ||
| 1287 | if (locked) | ||
| 1288 | spin_unlock(&dlm->spinlock); | ||
| 1289 | spin_unlock(&dlm_domain_lock); | ||
| 1290 | |||
| 1291 | return status; | ||
| 1292 | } | ||
| 1293 | |||
| 1126 | static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data, | 1294 | static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data, |
| 1127 | void **ret_data) | 1295 | void **ret_data) |
| 1128 | { | 1296 | { |
| @@ -1443,8 +1611,13 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm) | |||
| 1443 | set_bit(dlm->node_num, dlm->domain_map); | 1611 | set_bit(dlm->node_num, dlm->domain_map); |
| 1444 | spin_unlock(&dlm->spinlock); | 1612 | spin_unlock(&dlm->spinlock); |
| 1445 | 1613 | ||
| 1446 | /* Support for global heartbeat was added in 1.1 */ | 1614 | /* Support for global heartbeat and node info was added in 1.1 */ |
| 1447 | if (dlm_protocol.pv_major > 1 || dlm_protocol.pv_minor > 0) { | 1615 | if (dlm_protocol.pv_major > 1 || dlm_protocol.pv_minor > 0) { |
| 1616 | status = dlm_send_nodeinfo(dlm, ctxt->yes_resp_map); | ||
| 1617 | if (status) { | ||
| 1618 | mlog_errno(status); | ||
| 1619 | goto bail; | ||
| 1620 | } | ||
| 1448 | status = dlm_send_regions(dlm, ctxt->yes_resp_map); | 1621 | status = dlm_send_regions(dlm, ctxt->yes_resp_map); |
| 1449 | if (status) { | 1622 | if (status) { |
| 1450 | mlog_errno(status); | 1623 | mlog_errno(status); |
| @@ -2026,6 +2199,13 @@ static int dlm_register_net_handlers(void) | |||
| 2026 | dlm_query_region_handler, | 2199 | dlm_query_region_handler, |
| 2027 | NULL, NULL, &dlm_join_handlers); | 2200 | NULL, NULL, &dlm_join_handlers); |
| 2028 | 2201 | ||
| 2202 | if (status) | ||
| 2203 | goto bail; | ||
| 2204 | |||
| 2205 | status = o2net_register_handler(DLM_QUERY_NODEINFO, DLM_MOD_KEY, | ||
| 2206 | sizeof(struct dlm_query_nodeinfo), | ||
| 2207 | dlm_query_nodeinfo_handler, | ||
| 2208 | NULL, NULL, &dlm_join_handlers); | ||
| 2029 | bail: | 2209 | bail: |
| 2030 | if (status < 0) | 2210 | if (status < 0) |
| 2031 | dlm_unregister_net_handlers(); | 2211 | dlm_unregister_net_handlers(); |
