Blame view
fs/dlm/config.c
22.7 KB
2522fe45a
|
1 |
// SPDX-License-Identifier: GPL-2.0-only |
e7fd41792
|
2 3 4 5 |
/****************************************************************************** ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
60f98d183
|
6 |
** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. |
e7fd41792
|
7 |
** |
e7fd41792
|
8 9 10 11 12 |
** ******************************************************************************* ******************************************************************************/ #include <linux/kernel.h> |
7963b8a59
|
13 |
#include <linux/init.h> |
e7fd41792
|
14 |
#include <linux/configfs.h> |
5a0e3ad6a
|
15 |
#include <linux/slab.h> |
44be6fdf1
|
16 17 |
#include <linux/in.h> #include <linux/in6.h> |
60f98d183
|
18 |
#include <linux/dlmconstants.h> |
44be6fdf1
|
19 |
#include <net/ipv6.h> |
e7fd41792
|
20 21 22 |
#include <net/sock.h> #include "config.h" |
1c032c031
|
23 |
#include "lowcomms.h" |
e7fd41792
|
24 25 26 27 28 29 |
/* * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight * /config/dlm/<cluster>/comms/<comm>/nodeid * /config/dlm/<cluster>/comms/<comm>/local |
55b3286d3
|
30 31 |
* /config/dlm/<cluster>/comms/<comm>/addr (write only) * /config/dlm/<cluster>/comms/<comm>/addr_list (read only) |
e7fd41792
|
32 33 34 35 36 |
* The <cluster> level is useless, but I haven't figured out how to avoid it. */ static struct config_group *space_list; static struct config_group *comm_list; |
51409340d
|
37 |
static struct dlm_comm *local_comm; |
60f98d183
|
38 |
static uint32_t dlm_comm_count; |
e7fd41792
|
39 |
|
51409340d
|
40 41 42 43 44 45 46 47 |
struct dlm_clusters; struct dlm_cluster; struct dlm_spaces; struct dlm_space; struct dlm_comms; struct dlm_comm; struct dlm_nodes; struct dlm_node; |
e7fd41792
|
48 |
|
f89ab8619
|
49 |
static struct config_group *make_cluster(struct config_group *, const char *); |
e7fd41792
|
50 51 |
static void drop_cluster(struct config_group *, struct config_item *); static void release_cluster(struct config_item *); |
f89ab8619
|
52 |
static struct config_group *make_space(struct config_group *, const char *); |
e7fd41792
|
53 54 |
static void drop_space(struct config_group *, struct config_item *); static void release_space(struct config_item *); |
f89ab8619
|
55 |
static struct config_item *make_comm(struct config_group *, const char *); |
e7fd41792
|
56 57 |
static void drop_comm(struct config_group *, struct config_item *); static void release_comm(struct config_item *); |
f89ab8619
|
58 |
static struct config_item *make_node(struct config_group *, const char *); |
e7fd41792
|
59 60 |
static void drop_node(struct config_group *, struct config_item *); static void release_node(struct config_item *); |
9ae0f367d
|
61 62 |
static struct configfs_attribute *comm_attrs[]; static struct configfs_attribute *node_attrs[]; |
51409340d
|
63 64 |
struct dlm_cluster { |
d200778e1
|
65 66 67 68 |
struct config_group group; unsigned int cl_tcp_port; unsigned int cl_buffer_size; unsigned int cl_rsbtbl_size; |
d200778e1
|
69 70 71 72 |
unsigned int cl_recover_timer; unsigned int cl_toss_secs; unsigned int cl_scan_secs; unsigned int cl_log_debug; |
505ee5283
|
73 |
unsigned int cl_log_info; |
6ed7257b4
|
74 |
unsigned int cl_protocol; |
a5b7ab635
|
75 |
unsigned int cl_mark; |
3ae1acf93
|
76 |
unsigned int cl_timewarn_cs; |
c6ff669ba
|
77 |
unsigned int cl_waitwarn_us; |
3881ac04e
|
78 |
unsigned int cl_new_rsb_count; |
60f98d183
|
79 80 |
unsigned int cl_recover_callbacks; char cl_cluster_name[DLM_LOCKSPACE_LEN]; |
d200778e1
|
81 |
}; |
9ae0f367d
|
82 83 84 85 86 |
static struct dlm_cluster *config_item_to_cluster(struct config_item *i) { return i ? container_of(to_config_group(i), struct dlm_cluster, group) : NULL; } |
d200778e1
|
87 88 89 90 |
enum { CLUSTER_ATTR_TCP_PORT = 0, CLUSTER_ATTR_BUFFER_SIZE, CLUSTER_ATTR_RSBTBL_SIZE, |
d200778e1
|
91 92 93 94 |
CLUSTER_ATTR_RECOVER_TIMER, CLUSTER_ATTR_TOSS_SECS, CLUSTER_ATTR_SCAN_SECS, CLUSTER_ATTR_LOG_DEBUG, |
505ee5283
|
95 |
CLUSTER_ATTR_LOG_INFO, |
6ed7257b4
|
96 |
CLUSTER_ATTR_PROTOCOL, |
a5b7ab635
|
97 |
CLUSTER_ATTR_MARK, |
3ae1acf93
|
98 |
CLUSTER_ATTR_TIMEWARN_CS, |
c6ff669ba
|
99 |
CLUSTER_ATTR_WAITWARN_US, |
3881ac04e
|
100 |
CLUSTER_ATTR_NEW_RSB_COUNT, |
60f98d183
|
101 102 |
CLUSTER_ATTR_RECOVER_CALLBACKS, CLUSTER_ATTR_CLUSTER_NAME, |
d200778e1
|
103 |
}; |
9ae0f367d
|
104 |
static ssize_t cluster_cluster_name_show(struct config_item *item, char *buf) |
60f98d183
|
105 |
{ |
9ae0f367d
|
106 |
struct dlm_cluster *cl = config_item_to_cluster(item); |
60f98d183
|
107 108 109 |
return sprintf(buf, "%s ", cl->cl_cluster_name); } |
9ae0f367d
|
110 |
static ssize_t cluster_cluster_name_store(struct config_item *item, |
60f98d183
|
111 112 |
const char *buf, size_t len) { |
9ae0f367d
|
113 |
struct dlm_cluster *cl = config_item_to_cluster(item); |
ad917e7f8
|
114 115 116 |
strlcpy(dlm_config.ci_cluster_name, buf, sizeof(dlm_config.ci_cluster_name)); strlcpy(cl->cl_cluster_name, buf, sizeof(cl->cl_cluster_name)); |
60f98d183
|
117 118 |
return len; } |
9ae0f367d
|
119 |
CONFIGFS_ATTR(cluster_, cluster_name); |
60f98d183
|
120 |
|
51409340d
|
121 |
static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, |
e1a0ec30a
|
122 |
int *info_field, bool (*check_cb)(unsigned int x), |
d200778e1
|
123 124 125 |
const char *buf, size_t len) { unsigned int x; |
4f4c337fb
|
126 |
int rc; |
d200778e1
|
127 128 |
if (!capable(CAP_SYS_ADMIN)) |
417358187
|
129 |
return -EPERM; |
4f4c337fb
|
130 131 132 |
rc = kstrtouint(buf, 0, &x); if (rc) return rc; |
d200778e1
|
133 |
|
e1a0ec30a
|
134 |
if (check_cb && check_cb(x)) |
d200778e1
|
135 136 137 138 139 140 141 |
return -EINVAL; *cl_field = x; *info_field = x; return len; } |
e1a0ec30a
|
142 |
#define CLUSTER_ATTR(name, check_cb) \ |
9ae0f367d
|
143 144 |
static ssize_t cluster_##name##_store(struct config_item *item, \ const char *buf, size_t len) \ |
d200778e1
|
145 |
{ \ |
9ae0f367d
|
146 |
struct dlm_cluster *cl = config_item_to_cluster(item); \ |
d200778e1
|
147 |
return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name, \ |
e1a0ec30a
|
148 |
check_cb, buf, len); \ |
d200778e1
|
149 |
} \ |
9ae0f367d
|
150 |
static ssize_t cluster_##name##_show(struct config_item *item, char *buf) \ |
d200778e1
|
151 |
{ \ |
9ae0f367d
|
152 |
struct dlm_cluster *cl = config_item_to_cluster(item); \ |
d200778e1
|
153 154 155 |
return snprintf(buf, PAGE_SIZE, "%u ", cl->cl_##name); \ } \ |
9ae0f367d
|
156 |
CONFIGFS_ATTR(cluster_, name); |
d200778e1
|
157 |
|
e1a0ec30a
|
158 159 160 161 |
static bool dlm_check_zero(unsigned int x) { return !x; } |
4e192ee68
|
162 163 164 165 |
static bool dlm_check_buffer_size(unsigned int x) { return (x < DEFAULT_BUFFER_SIZE); } |
e1a0ec30a
|
166 |
CLUSTER_ATTR(tcp_port, dlm_check_zero); |
4e192ee68
|
167 |
CLUSTER_ATTR(buffer_size, dlm_check_buffer_size); |
e1a0ec30a
|
168 169 170 171 172 173 174 175 176 177 178 179 |
CLUSTER_ATTR(rsbtbl_size, dlm_check_zero); CLUSTER_ATTR(recover_timer, dlm_check_zero); CLUSTER_ATTR(toss_secs, dlm_check_zero); CLUSTER_ATTR(scan_secs, dlm_check_zero); CLUSTER_ATTR(log_debug, NULL); CLUSTER_ATTR(log_info, NULL); CLUSTER_ATTR(protocol, NULL); CLUSTER_ATTR(mark, NULL); CLUSTER_ATTR(timewarn_cs, dlm_check_zero); CLUSTER_ATTR(waitwarn_us, NULL); CLUSTER_ATTR(new_rsb_count, NULL); CLUSTER_ATTR(recover_callbacks, NULL); |
d200778e1
|
180 181 |
static struct configfs_attribute *cluster_attrs[] = { |
9ae0f367d
|
182 183 184 185 186 187 188 |
[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port, [CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size, [CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size, [CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer, [CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs, [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs, [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug, |
505ee5283
|
189 |
[CLUSTER_ATTR_LOG_INFO] = &cluster_attr_log_info, |
9ae0f367d
|
190 |
[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol, |
a5b7ab635
|
191 |
[CLUSTER_ATTR_MARK] = &cluster_attr_mark, |
9ae0f367d
|
192 193 194 195 196 |
[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs, [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us, [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count, [CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks, [CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name, |
d200778e1
|
197 198 |
NULL, }; |
e7fd41792
|
199 200 201 202 |
enum { COMM_ATTR_NODEID = 0, COMM_ATTR_LOCAL, COMM_ATTR_ADDR, |
55b3286d3
|
203 |
COMM_ATTR_ADDR_LIST, |
9c9f168f5
|
204 |
COMM_ATTR_MARK, |
e7fd41792
|
205 |
}; |
e7fd41792
|
206 207 208 209 |
enum { NODE_ATTR_NODEID = 0, NODE_ATTR_WEIGHT, }; |
51409340d
|
210 |
struct dlm_clusters { |
e7fd41792
|
211 212 |
struct configfs_subsystem subsys; }; |
51409340d
|
213 |
struct dlm_spaces { |
e7fd41792
|
214 215 |
struct config_group ss_group; }; |
51409340d
|
216 |
struct dlm_space { |
e7fd41792
|
217 218 |
struct config_group group; struct list_head members; |
901359256
|
219 |
struct mutex members_lock; |
e7fd41792
|
220 |
int members_count; |
3d2825c8c
|
221 |
struct dlm_nodes *nds; |
e7fd41792
|
222 |
}; |
51409340d
|
223 |
struct dlm_comms { |
e7fd41792
|
224 225 |
struct config_group cs_group; }; |
51409340d
|
226 |
struct dlm_comm { |
e7fd41792
|
227 |
struct config_item item; |
60f98d183
|
228 |
int seq; |
e7fd41792
|
229 230 231 |
int nodeid; int local; int addr_count; |
9c9f168f5
|
232 |
unsigned int mark; |
e7fd41792
|
233 234 |
struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; }; |
51409340d
|
235 |
struct dlm_nodes { |
e7fd41792
|
236 237 |
struct config_group ns_group; }; |
51409340d
|
238 |
struct dlm_node { |
e7fd41792
|
239 240 241 242 |
struct config_item item; struct list_head list; /* space->members */ int nodeid; int weight; |
d44e0fc70
|
243 |
int new; |
60f98d183
|
244 |
int comm_seq; /* copy of cm->seq when nd->nodeid is set */ |
e7fd41792
|
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
}; static struct configfs_group_operations clusters_ops = { .make_group = make_cluster, .drop_item = drop_cluster, }; static struct configfs_item_operations cluster_ops = { .release = release_cluster, }; static struct configfs_group_operations spaces_ops = { .make_group = make_space, .drop_item = drop_space, }; static struct configfs_item_operations space_ops = { .release = release_space, }; static struct configfs_group_operations comms_ops = { .make_item = make_comm, .drop_item = drop_comm, }; static struct configfs_item_operations comm_ops = { .release = release_comm, |
e7fd41792
|
272 273 274 275 276 277 278 279 280 |
}; static struct configfs_group_operations nodes_ops = { .make_item = make_node, .drop_item = drop_node, }; static struct configfs_item_operations node_ops = { .release = release_node, |
e7fd41792
|
281 |
}; |
761594b74
|
282 |
static const struct config_item_type clusters_type = { |
e7fd41792
|
283 284 285 |
.ct_group_ops = &clusters_ops, .ct_owner = THIS_MODULE, }; |
761594b74
|
286 |
static const struct config_item_type cluster_type = { |
e7fd41792
|
287 |
.ct_item_ops = &cluster_ops, |
d200778e1
|
288 |
.ct_attrs = cluster_attrs, |
e7fd41792
|
289 290 |
.ct_owner = THIS_MODULE, }; |
761594b74
|
291 |
static const struct config_item_type spaces_type = { |
e7fd41792
|
292 293 294 |
.ct_group_ops = &spaces_ops, .ct_owner = THIS_MODULE, }; |
761594b74
|
295 |
static const struct config_item_type space_type = { |
e7fd41792
|
296 297 298 |
.ct_item_ops = &space_ops, .ct_owner = THIS_MODULE, }; |
761594b74
|
299 |
static const struct config_item_type comms_type = { |
e7fd41792
|
300 301 302 |
.ct_group_ops = &comms_ops, .ct_owner = THIS_MODULE, }; |
761594b74
|
303 |
static const struct config_item_type comm_type = { |
e7fd41792
|
304 305 306 307 |
.ct_item_ops = &comm_ops, .ct_attrs = comm_attrs, .ct_owner = THIS_MODULE, }; |
761594b74
|
308 |
static const struct config_item_type nodes_type = { |
e7fd41792
|
309 310 311 |
.ct_group_ops = &nodes_ops, .ct_owner = THIS_MODULE, }; |
761594b74
|
312 |
static const struct config_item_type node_type = { |
e7fd41792
|
313 314 315 316 |
.ct_item_ops = &node_ops, .ct_attrs = node_attrs, .ct_owner = THIS_MODULE, }; |
27eccf464
|
317 |
static struct dlm_space *config_item_to_space(struct config_item *i) |
e7fd41792
|
318 |
{ |
51409340d
|
319 320 |
return i ? container_of(to_config_group(i), struct dlm_space, group) : NULL; |
e7fd41792
|
321 |
} |
27eccf464
|
322 |
static struct dlm_comm *config_item_to_comm(struct config_item *i) |
e7fd41792
|
323 |
{ |
51409340d
|
324 |
return i ? container_of(i, struct dlm_comm, item) : NULL; |
e7fd41792
|
325 |
} |
27eccf464
|
326 |
static struct dlm_node *config_item_to_node(struct config_item *i) |
e7fd41792
|
327 |
{ |
51409340d
|
328 |
return i ? container_of(i, struct dlm_node, item) : NULL; |
e7fd41792
|
329 |
} |
f89ab8619
|
330 331 |
static struct config_group *make_cluster(struct config_group *g, const char *name) |
e7fd41792
|
332 |
{ |
51409340d
|
333 334 335 |
struct dlm_cluster *cl = NULL; struct dlm_spaces *sps = NULL; struct dlm_comms *cms = NULL; |
e7fd41792
|
336 |
|
573c24c4a
|
337 |
cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS); |
573c24c4a
|
338 339 |
sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS); cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS); |
e7fd41792
|
340 |
|
82c7d823c
|
341 |
if (!cl || !sps || !cms) |
e7fd41792
|
342 343 344 345 346 |
goto fail; config_group_init_type_name(&cl->group, name, &cluster_type); config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type); config_group_init_type_name(&cms->cs_group, "comms", &comms_type); |
1ae1602de
|
347 348 |
configfs_add_default_group(&sps->ss_group, &cl->group); configfs_add_default_group(&cms->cs_group, &cl->group); |
e7fd41792
|
349 |
|
d200778e1
|
350 351 352 |
cl->cl_tcp_port = dlm_config.ci_tcp_port; cl->cl_buffer_size = dlm_config.ci_buffer_size; cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size; |
d200778e1
|
353 354 355 356 |
cl->cl_recover_timer = dlm_config.ci_recover_timer; cl->cl_toss_secs = dlm_config.ci_toss_secs; cl->cl_scan_secs = dlm_config.ci_scan_secs; cl->cl_log_debug = dlm_config.ci_log_debug; |
505ee5283
|
357 |
cl->cl_log_info = dlm_config.ci_log_info; |
0b7cac0fb
|
358 |
cl->cl_protocol = dlm_config.ci_protocol; |
84d8cd69a
|
359 |
cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs; |
c6ff669ba
|
360 |
cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us; |
3881ac04e
|
361 |
cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count; |
60f98d183
|
362 363 364 |
cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks; memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name, DLM_LOCKSPACE_LEN); |
d200778e1
|
365 |
|
e7fd41792
|
366 367 |
space_list = &sps->ss_group; comm_list = &cms->cs_group; |
f89ab8619
|
368 |
return &cl->group; |
e7fd41792
|
369 370 371 |
fail: kfree(cl); |
e7fd41792
|
372 373 |
kfree(sps); kfree(cms); |
a6795e9eb
|
374 |
return ERR_PTR(-ENOMEM); |
e7fd41792
|
375 376 377 378 |
} static void drop_cluster(struct config_group *g, struct config_item *i) { |
27eccf464
|
379 |
struct dlm_cluster *cl = config_item_to_cluster(i); |
e7fd41792
|
380 |
|
1ae1602de
|
381 |
configfs_remove_default_groups(&cl->group); |
e7fd41792
|
382 383 384 385 386 387 388 389 390 |
space_list = NULL; comm_list = NULL; config_item_put(i); } static void release_cluster(struct config_item *i) { |
27eccf464
|
391 |
struct dlm_cluster *cl = config_item_to_cluster(i); |
e7fd41792
|
392 393 |
kfree(cl); } |
f89ab8619
|
394 |
static struct config_group *make_space(struct config_group *g, const char *name) |
e7fd41792
|
395 |
{ |
51409340d
|
396 397 |
struct dlm_space *sp = NULL; struct dlm_nodes *nds = NULL; |
e7fd41792
|
398 |
|
573c24c4a
|
399 |
sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS); |
573c24c4a
|
400 |
nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS); |
e7fd41792
|
401 |
|
1ae1602de
|
402 |
if (!sp || !nds) |
e7fd41792
|
403 404 405 |
goto fail; config_group_init_type_name(&sp->group, name, &space_type); |
e7fd41792
|
406 |
|
1ae1602de
|
407 408 |
config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type); configfs_add_default_group(&nds->ns_group, &sp->group); |
e7fd41792
|
409 410 |
INIT_LIST_HEAD(&sp->members); |
901359256
|
411 |
mutex_init(&sp->members_lock); |
e7fd41792
|
412 |
sp->members_count = 0; |
3d2825c8c
|
413 |
sp->nds = nds; |
f89ab8619
|
414 |
return &sp->group; |
e7fd41792
|
415 416 417 |
fail: kfree(sp); |
e7fd41792
|
418 |
kfree(nds); |
a6795e9eb
|
419 |
return ERR_PTR(-ENOMEM); |
e7fd41792
|
420 421 422 423 |
} static void drop_space(struct config_group *g, struct config_item *i) { |
27eccf464
|
424 |
struct dlm_space *sp = config_item_to_space(i); |
e7fd41792
|
425 426 |
/* assert list_empty(&sp->members) */ |
1ae1602de
|
427 |
configfs_remove_default_groups(&sp->group); |
e7fd41792
|
428 429 430 431 432 |
config_item_put(i); } static void release_space(struct config_item *i) { |
27eccf464
|
433 |
struct dlm_space *sp = config_item_to_space(i); |
3d2825c8c
|
434 |
kfree(sp->nds); |
e7fd41792
|
435 436 |
kfree(sp); } |
f89ab8619
|
437 |
static struct config_item *make_comm(struct config_group *g, const char *name) |
e7fd41792
|
438 |
{ |
51409340d
|
439 |
struct dlm_comm *cm; |
e7fd41792
|
440 |
|
573c24c4a
|
441 |
cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS); |
e7fd41792
|
442 |
if (!cm) |
a6795e9eb
|
443 |
return ERR_PTR(-ENOMEM); |
e7fd41792
|
444 445 |
config_item_init_type_name(&cm->item, name, &comm_type); |
60f98d183
|
446 447 448 449 |
cm->seq = dlm_comm_count++; if (!cm->seq) cm->seq = dlm_comm_count++; |
e7fd41792
|
450 451 452 |
cm->nodeid = -1; cm->local = 0; cm->addr_count = 0; |
9c9f168f5
|
453 |
cm->mark = 0; |
f89ab8619
|
454 |
return &cm->item; |
e7fd41792
|
455 456 457 458 |
} static void drop_comm(struct config_group *g, struct config_item *i) { |
27eccf464
|
459 |
struct dlm_comm *cm = config_item_to_comm(i); |
e7fd41792
|
460 461 |
if (local_comm == cm) local_comm = NULL; |
1c032c031
|
462 |
dlm_lowcomms_close(cm->nodeid); |
e7fd41792
|
463 464 465 466 467 468 469 |
while (cm->addr_count--) kfree(cm->addr[cm->addr_count]); config_item_put(i); } static void release_comm(struct config_item *i) { |
27eccf464
|
470 |
struct dlm_comm *cm = config_item_to_comm(i); |
e7fd41792
|
471 472 |
kfree(cm); } |
f89ab8619
|
473 |
static struct config_item *make_node(struct config_group *g, const char *name) |
e7fd41792
|
474 |
{ |
27eccf464
|
475 |
struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent); |
51409340d
|
476 |
struct dlm_node *nd; |
e7fd41792
|
477 |
|
573c24c4a
|
478 |
nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS); |
e7fd41792
|
479 |
if (!nd) |
a6795e9eb
|
480 |
return ERR_PTR(-ENOMEM); |
e7fd41792
|
481 482 483 484 |
config_item_init_type_name(&nd->item, name, &node_type); nd->nodeid = -1; nd->weight = 1; /* default weight of 1 if none is set */ |
d44e0fc70
|
485 |
nd->new = 1; /* set to 0 once it's been read by dlm_nodeid_list() */ |
e7fd41792
|
486 |
|
901359256
|
487 |
mutex_lock(&sp->members_lock); |
e7fd41792
|
488 489 |
list_add(&nd->list, &sp->members); sp->members_count++; |
901359256
|
490 |
mutex_unlock(&sp->members_lock); |
e7fd41792
|
491 |
|
f89ab8619
|
492 |
return &nd->item; |
e7fd41792
|
493 494 495 496 |
} static void drop_node(struct config_group *g, struct config_item *i) { |
27eccf464
|
497 498 |
struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent); struct dlm_node *nd = config_item_to_node(i); |
e7fd41792
|
499 |
|
901359256
|
500 |
mutex_lock(&sp->members_lock); |
e7fd41792
|
501 502 |
list_del(&nd->list); sp->members_count--; |
901359256
|
503 |
mutex_unlock(&sp->members_lock); |
e7fd41792
|
504 505 506 507 508 509 |
config_item_put(i); } static void release_node(struct config_item *i) { |
27eccf464
|
510 |
struct dlm_node *nd = config_item_to_node(i); |
e7fd41792
|
511 512 |
kfree(nd); } |
51409340d
|
513 |
static struct dlm_clusters clusters_root = { |
e7fd41792
|
514 515 516 517 518 519 520 521 522 |
.subsys = { .su_group = { .cg_item = { .ci_namebuf = "dlm", .ci_type = &clusters_type, }, }, }, }; |
30727174b
|
523 |
int __init dlm_config_init(void) |
e7fd41792
|
524 525 |
{ config_group_init(&clusters_root.subsys.su_group); |
e6bd07aee
|
526 |
mutex_init(&clusters_root.subsys.su_mutex); |
e7fd41792
|
527 528 529 530 531 532 533 534 535 536 537 |
return configfs_register_subsystem(&clusters_root.subsys); } void dlm_config_exit(void) { configfs_unregister_subsystem(&clusters_root.subsys); } /* * Functions for user space to read/write attributes */ |
9ae0f367d
|
538 |
static ssize_t comm_nodeid_show(struct config_item *item, char *buf) |
d200778e1
|
539 |
{ |
9ae0f367d
|
540 541 |
return sprintf(buf, "%d ", config_item_to_comm(item)->nodeid); |
e7fd41792
|
542 |
} |
9ae0f367d
|
543 |
static ssize_t comm_nodeid_store(struct config_item *item, const char *buf, |
51409340d
|
544 |
size_t len) |
e7fd41792
|
545 |
{ |
9ae0f367d
|
546 |
int rc = kstrtoint(buf, 0, &config_item_to_comm(item)->nodeid); |
4f4c337fb
|
547 548 549 |
if (rc) return rc; |
e7fd41792
|
550 551 |
return len; } |
9ae0f367d
|
552 |
static ssize_t comm_local_show(struct config_item *item, char *buf) |
e7fd41792
|
553 |
{ |
9ae0f367d
|
554 555 |
return sprintf(buf, "%d ", config_item_to_comm(item)->local); |
e7fd41792
|
556 |
} |
9ae0f367d
|
557 |
static ssize_t comm_local_store(struct config_item *item, const char *buf, |
51409340d
|
558 |
size_t len) |
e7fd41792
|
559 |
{ |
9ae0f367d
|
560 |
struct dlm_comm *cm = config_item_to_comm(item); |
4f4c337fb
|
561 562 563 564 |
int rc = kstrtoint(buf, 0, &cm->local); if (rc) return rc; |
e7fd41792
|
565 566 567 568 |
if (cm->local && !local_comm) local_comm = cm; return len; } |
9ae0f367d
|
569 570 |
static ssize_t comm_addr_store(struct config_item *item, const char *buf, size_t len) |
e7fd41792
|
571 |
{ |
9ae0f367d
|
572 |
struct dlm_comm *cm = config_item_to_comm(item); |
e7fd41792
|
573 |
struct sockaddr_storage *addr; |
36b71a8bf
|
574 |
int rv; |
e7fd41792
|
575 576 577 578 579 580 |
if (len != sizeof(struct sockaddr_storage)) return -EINVAL; if (cm->addr_count >= DLM_MAX_ADDR_COUNT) return -ENOSPC; |
573c24c4a
|
581 |
addr = kzalloc(sizeof(*addr), GFP_NOFS); |
e7fd41792
|
582 583 584 585 |
if (!addr) return -ENOMEM; memcpy(addr, buf, len); |
36b71a8bf
|
586 587 588 589 590 591 |
rv = dlm_lowcomms_addr(cm->nodeid, addr, len); if (rv) { kfree(addr); return rv; } |
e7fd41792
|
592 593 594 |
cm->addr[cm->addr_count++] = addr; return len; } |
9ae0f367d
|
595 |
static ssize_t comm_addr_list_show(struct config_item *item, char *buf) |
55b3286d3
|
596 |
{ |
9ae0f367d
|
597 |
struct dlm_comm *cm = config_item_to_comm(item); |
55b3286d3
|
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
ssize_t s; ssize_t allowance; int i; struct sockaddr_storage *addr; struct sockaddr_in *addr_in; struct sockaddr_in6 *addr_in6; /* Taken from ip6_addr_string() defined in lib/vsprintf.c */ char buf0[sizeof("AF_INET6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255 ")]; /* Derived from SIMPLE_ATTR_SIZE of fs/configfs/file.c */ allowance = 4096; buf[0] = '\0'; for (i = 0; i < cm->addr_count; i++) { addr = cm->addr[i]; switch(addr->ss_family) { case AF_INET: addr_in = (struct sockaddr_in *)addr; s = sprintf(buf0, "AF_INET %pI4 ", &addr_in->sin_addr.s_addr); break; case AF_INET6: addr_in6 = (struct sockaddr_in6 *)addr; s = sprintf(buf0, "AF_INET6 %pI6 ", &addr_in6->sin6_addr); break; default: s = sprintf(buf0, "%s ", "<UNKNOWN>"); break; } allowance -= s; if (allowance >= 0) strcat(buf, buf0); else { allowance += s; break; } } return 4096 - allowance; } |
9c9f168f5
|
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 |
static ssize_t comm_mark_show(struct config_item *item, char *buf) { return sprintf(buf, "%u ", config_item_to_comm(item)->mark); } static ssize_t comm_mark_store(struct config_item *item, const char *buf, size_t len) { unsigned int mark; int rc; rc = kstrtouint(buf, 0, &mark); if (rc) return rc; config_item_to_comm(item)->mark = mark; return len; } |
9ae0f367d
|
662 663 |
CONFIGFS_ATTR(comm_, nodeid); CONFIGFS_ATTR(comm_, local); |
9c9f168f5
|
664 |
CONFIGFS_ATTR(comm_, mark); |
9ae0f367d
|
665 666 |
CONFIGFS_ATTR_WO(comm_, addr); CONFIGFS_ATTR_RO(comm_, addr_list); |
e7fd41792
|
667 |
|
9ae0f367d
|
668 669 670 671 672 |
static struct configfs_attribute *comm_attrs[] = { [COMM_ATTR_NODEID] = &comm_attr_nodeid, [COMM_ATTR_LOCAL] = &comm_attr_local, [COMM_ATTR_ADDR] = &comm_attr_addr, [COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list, |
9c9f168f5
|
673 |
[COMM_ATTR_MARK] = &comm_attr_mark, |
9ae0f367d
|
674 675 |
NULL, }; |
e7fd41792
|
676 |
|
9ae0f367d
|
677 |
static ssize_t node_nodeid_show(struct config_item *item, char *buf) |
e7fd41792
|
678 |
{ |
9ae0f367d
|
679 680 |
return sprintf(buf, "%d ", config_item_to_node(item)->nodeid); |
e7fd41792
|
681 |
} |
9ae0f367d
|
682 |
static ssize_t node_nodeid_store(struct config_item *item, const char *buf, |
51409340d
|
683 |
size_t len) |
e7fd41792
|
684 |
{ |
9ae0f367d
|
685 |
struct dlm_node *nd = config_item_to_node(item); |
60f98d183
|
686 |
uint32_t seq = 0; |
4f4c337fb
|
687 688 689 690 |
int rc = kstrtoint(buf, 0, &nd->nodeid); if (rc) return rc; |
60f98d183
|
691 692 |
dlm_comm_seq(nd->nodeid, &seq); nd->comm_seq = seq; |
e7fd41792
|
693 694 |
return len; } |
9ae0f367d
|
695 |
static ssize_t node_weight_show(struct config_item *item, char *buf) |
e7fd41792
|
696 |
{ |
9ae0f367d
|
697 698 |
return sprintf(buf, "%d ", config_item_to_node(item)->weight); |
e7fd41792
|
699 |
} |
9ae0f367d
|
700 |
static ssize_t node_weight_store(struct config_item *item, const char *buf, |
51409340d
|
701 |
size_t len) |
e7fd41792
|
702 |
{ |
9ae0f367d
|
703 |
int rc = kstrtoint(buf, 0, &config_item_to_node(item)->weight); |
4f4c337fb
|
704 705 706 |
if (rc) return rc; |
e7fd41792
|
707 708 |
return len; } |
9ae0f367d
|
709 710 711 712 713 714 715 716 |
CONFIGFS_ATTR(node_, nodeid); CONFIGFS_ATTR(node_, weight); static struct configfs_attribute *node_attrs[] = { [NODE_ATTR_NODEID] = &node_attr_nodeid, [NODE_ATTR_WEIGHT] = &node_attr_weight, NULL, }; |
e7fd41792
|
717 718 719 |
/* * Functions for the dlm to get the info that's been configured */ |
51409340d
|
720 |
static struct dlm_space *get_space(char *name) |
e7fd41792
|
721 |
{ |
3168b0780
|
722 |
struct config_item *i; |
e7fd41792
|
723 724 |
if (!space_list) return NULL; |
3168b0780
|
725 |
|
e6bd07aee
|
726 |
mutex_lock(&space_list->cg_subsys->su_mutex); |
3fe6c5ce1
|
727 |
i = config_group_find_item(space_list, name); |
e6bd07aee
|
728 |
mutex_unlock(&space_list->cg_subsys->su_mutex); |
3168b0780
|
729 |
|
27eccf464
|
730 |
return config_item_to_space(i); |
e7fd41792
|
731 |
} |
51409340d
|
732 |
static void put_space(struct dlm_space *sp) |
e7fd41792
|
733 734 735 |
{ config_item_put(&sp->group.cg_item); } |
36b71a8bf
|
736 |
static struct dlm_comm *get_comm(int nodeid) |
e7fd41792
|
737 738 |
{ struct config_item *i; |
51409340d
|
739 |
struct dlm_comm *cm = NULL; |
e7fd41792
|
740 741 742 743 |
int found = 0; if (!comm_list) return NULL; |
e6bd07aee
|
744 |
mutex_lock(&clusters_root.subsys.su_mutex); |
e7fd41792
|
745 746 |
list_for_each_entry(i, &comm_list->cg_children, ci_entry) { |
27eccf464
|
747 |
cm = config_item_to_comm(i); |
e7fd41792
|
748 |
|
36b71a8bf
|
749 750 751 752 753 |
if (cm->nodeid != nodeid) continue; found = 1; config_item_get(i); break; |
e7fd41792
|
754 |
} |
e6bd07aee
|
755 |
mutex_unlock(&clusters_root.subsys.su_mutex); |
e7fd41792
|
756 |
|
3168b0780
|
757 |
if (!found) |
e7fd41792
|
758 759 760 |
cm = NULL; return cm; } |
51409340d
|
761 |
static void put_comm(struct dlm_comm *cm) |
e7fd41792
|
762 763 764 765 766 |
{ config_item_put(&cm->item); } /* caller must free mem */ |
60f98d183
|
767 768 |
int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, int *count_out) |
e7fd41792
|
769 |
{ |
51409340d
|
770 771 |
struct dlm_space *sp; struct dlm_node *nd; |
60f98d183
|
772 773 |
struct dlm_config_node *nodes, *node; int rv, count; |
e7fd41792
|
774 775 776 777 |
sp = get_space(lsname); if (!sp) return -EEXIST; |
901359256
|
778 |
mutex_lock(&sp->members_lock); |
e7fd41792
|
779 |
if (!sp->members_count) { |
d44e0fc70
|
780 781 782 |
rv = -EINVAL; printk(KERN_ERR "dlm: zero members_count "); |
e7fd41792
|
783 784 |
goto out; } |
60f98d183
|
785 |
count = sp->members_count; |
d44e0fc70
|
786 |
|
60f98d183
|
787 788 |
nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS); if (!nodes) { |
e7fd41792
|
789 790 791 |
rv = -ENOMEM; goto out; } |
60f98d183
|
792 |
node = nodes; |
d44e0fc70
|
793 |
list_for_each_entry(nd, &sp->members, list) { |
60f98d183
|
794 795 796 797 798 |
node->nodeid = nd->nodeid; node->weight = nd->weight; node->new = nd->new; node->comm_seq = nd->comm_seq; node++; |
d44e0fc70
|
799 |
|
60f98d183
|
800 |
nd->new = 0; |
d44e0fc70
|
801 |
} |
e7fd41792
|
802 |
|
60f98d183
|
803 804 805 |
*count_out = count; *nodes_out = nodes; rv = 0; |
e7fd41792
|
806 |
out: |
901359256
|
807 |
mutex_unlock(&sp->members_lock); |
e7fd41792
|
808 809 810 |
put_space(sp); return rv; } |
60f98d183
|
811 |
int dlm_comm_seq(int nodeid, uint32_t *seq) |
e7fd41792
|
812 |
{ |
36b71a8bf
|
813 |
struct dlm_comm *cm = get_comm(nodeid); |
60f98d183
|
814 815 816 817 818 |
if (!cm) return -EEXIST; *seq = cm->seq; put_comm(cm); return 0; |
e7fd41792
|
819 |
} |
3f78cd7d2
|
820 |
void dlm_comm_mark(int nodeid, unsigned int *mark) |
9c9f168f5
|
821 822 823 824 |
{ struct dlm_comm *cm; cm = get_comm(nodeid); |
3f78cd7d2
|
825 826 827 828 |
if (!cm) { *mark = dlm_config.ci_mark; return; } |
9c9f168f5
|
829 |
|
3f78cd7d2
|
830 831 832 833 |
if (cm->mark) *mark = cm->mark; else *mark = dlm_config.ci_mark; |
9c9f168f5
|
834 |
|
3f78cd7d2
|
835 |
put_comm(cm); |
9c9f168f5
|
836 |
} |
e7fd41792
|
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 |
int dlm_our_nodeid(void) { return local_comm ? local_comm->nodeid : 0; } /* num 0 is first addr, num 1 is second addr */ int dlm_our_addr(struct sockaddr_storage *addr, int num) { if (!local_comm) return -1; if (num + 1 > local_comm->addr_count) return -1; memcpy(addr, local_comm->addr[num], sizeof(*addr)); return 0; } /* Config file defaults */ #define DEFAULT_TCP_PORT 21064 |
e3853a90e
|
855 |
#define DEFAULT_RSBTBL_SIZE 1024 |
e7fd41792
|
856 857 858 |
#define DEFAULT_RECOVER_TIMER 5 #define DEFAULT_TOSS_SECS 10 #define DEFAULT_SCAN_SECS 5 |
99fc64874
|
859 |
#define DEFAULT_LOG_DEBUG 0 |
505ee5283
|
860 |
#define DEFAULT_LOG_INFO 1 |
6ed7257b4
|
861 |
#define DEFAULT_PROTOCOL 0 |
a5b7ab635
|
862 |
#define DEFAULT_MARK 0 |
3ae1acf93
|
863 |
#define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */ |
c6ff669ba
|
864 |
#define DEFAULT_WAITWARN_US 0 |
3881ac04e
|
865 |
#define DEFAULT_NEW_RSB_COUNT 128 |
60f98d183
|
866 867 |
#define DEFAULT_RECOVER_CALLBACKS 0 #define DEFAULT_CLUSTER_NAME "" |
e7fd41792
|
868 869 |
struct dlm_config_info dlm_config = { |
68c817a1c
|
870 871 872 |
.ci_tcp_port = DEFAULT_TCP_PORT, .ci_buffer_size = DEFAULT_BUFFER_SIZE, .ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE, |
68c817a1c
|
873 874 |
.ci_recover_timer = DEFAULT_RECOVER_TIMER, .ci_toss_secs = DEFAULT_TOSS_SECS, |
99fc64874
|
875 |
.ci_scan_secs = DEFAULT_SCAN_SECS, |
6ed7257b4
|
876 |
.ci_log_debug = DEFAULT_LOG_DEBUG, |
505ee5283
|
877 |
.ci_log_info = DEFAULT_LOG_INFO, |
3ae1acf93
|
878 |
.ci_protocol = DEFAULT_PROTOCOL, |
a5b7ab635
|
879 |
.ci_mark = DEFAULT_MARK, |
c6ff669ba
|
880 |
.ci_timewarn_cs = DEFAULT_TIMEWARN_CS, |
3881ac04e
|
881 |
.ci_waitwarn_us = DEFAULT_WAITWARN_US, |
60f98d183
|
882 883 884 |
.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT, .ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS, .ci_cluster_name = DEFAULT_CLUSTER_NAME |
e7fd41792
|
885 |
}; |