diff options
Diffstat (limited to 'fs/dlm/config.c')
-rw-r--r-- | fs/dlm/config.c | 789 |
1 files changed, 789 insertions, 0 deletions
diff --git a/fs/dlm/config.c b/fs/dlm/config.c new file mode 100644 index 000000000000..88553054bbfa --- /dev/null +++ b/fs/dlm/config.c | |||
@@ -0,0 +1,789 @@ | |||
1 | /****************************************************************************** | ||
2 | ******************************************************************************* | ||
3 | ** | ||
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | ||
6 | ** | ||
7 | ** This copyrighted material is made available to anyone wishing to use, | ||
8 | ** modify, copy, or redistribute it subject to the terms and conditions | ||
9 | ** of the GNU General Public License v.2. | ||
10 | ** | ||
11 | ******************************************************************************* | ||
12 | ******************************************************************************/ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/configfs.h> | ||
17 | #include <net/sock.h> | ||
18 | |||
19 | #include "config.h" | ||
20 | #include "lowcomms.h" | ||
21 | |||
22 | /* | ||
23 | * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid | ||
24 | * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight | ||
25 | * /config/dlm/<cluster>/comms/<comm>/nodeid | ||
26 | * /config/dlm/<cluster>/comms/<comm>/local | ||
27 | * /config/dlm/<cluster>/comms/<comm>/addr | ||
28 | * The <cluster> level is useless, but I haven't figured out how to avoid it. | ||
29 | */ | ||
30 | |||
31 | static struct config_group *space_list; | ||
32 | static struct config_group *comm_list; | ||
33 | static struct comm *local_comm; | ||
34 | |||
35 | struct clusters; | ||
36 | struct cluster; | ||
37 | struct spaces; | ||
38 | struct space; | ||
39 | struct comms; | ||
40 | struct comm; | ||
41 | struct nodes; | ||
42 | struct node; | ||
43 | |||
44 | static struct config_group *make_cluster(struct config_group *, const char *); | ||
45 | static void drop_cluster(struct config_group *, struct config_item *); | ||
46 | static void release_cluster(struct config_item *); | ||
47 | static struct config_group *make_space(struct config_group *, const char *); | ||
48 | static void drop_space(struct config_group *, struct config_item *); | ||
49 | static void release_space(struct config_item *); | ||
50 | static struct config_item *make_comm(struct config_group *, const char *); | ||
51 | static void drop_comm(struct config_group *, struct config_item *); | ||
52 | static void release_comm(struct config_item *); | ||
53 | static struct config_item *make_node(struct config_group *, const char *); | ||
54 | static void drop_node(struct config_group *, struct config_item *); | ||
55 | static void release_node(struct config_item *); | ||
56 | |||
57 | static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, | ||
58 | char *buf); | ||
59 | static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, | ||
60 | const char *buf, size_t len); | ||
61 | static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, | ||
62 | char *buf); | ||
63 | static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, | ||
64 | const char *buf, size_t len); | ||
65 | |||
66 | static ssize_t comm_nodeid_read(struct comm *cm, char *buf); | ||
67 | static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len); | ||
68 | static ssize_t comm_local_read(struct comm *cm, char *buf); | ||
69 | static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len); | ||
70 | static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len); | ||
71 | static ssize_t node_nodeid_read(struct node *nd, char *buf); | ||
72 | static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len); | ||
73 | static ssize_t node_weight_read(struct node *nd, char *buf); | ||
74 | static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len); | ||
75 | |||
76 | enum { | ||
77 | COMM_ATTR_NODEID = 0, | ||
78 | COMM_ATTR_LOCAL, | ||
79 | COMM_ATTR_ADDR, | ||
80 | }; | ||
81 | |||
82 | struct comm_attribute { | ||
83 | struct configfs_attribute attr; | ||
84 | ssize_t (*show)(struct comm *, char *); | ||
85 | ssize_t (*store)(struct comm *, const char *, size_t); | ||
86 | }; | ||
87 | |||
88 | static struct comm_attribute comm_attr_nodeid = { | ||
89 | .attr = { .ca_owner = THIS_MODULE, | ||
90 | .ca_name = "nodeid", | ||
91 | .ca_mode = S_IRUGO | S_IWUSR }, | ||
92 | .show = comm_nodeid_read, | ||
93 | .store = comm_nodeid_write, | ||
94 | }; | ||
95 | |||
96 | static struct comm_attribute comm_attr_local = { | ||
97 | .attr = { .ca_owner = THIS_MODULE, | ||
98 | .ca_name = "local", | ||
99 | .ca_mode = S_IRUGO | S_IWUSR }, | ||
100 | .show = comm_local_read, | ||
101 | .store = comm_local_write, | ||
102 | }; | ||
103 | |||
104 | static struct comm_attribute comm_attr_addr = { | ||
105 | .attr = { .ca_owner = THIS_MODULE, | ||
106 | .ca_name = "addr", | ||
107 | .ca_mode = S_IRUGO | S_IWUSR }, | ||
108 | .store = comm_addr_write, | ||
109 | }; | ||
110 | |||
111 | static struct configfs_attribute *comm_attrs[] = { | ||
112 | [COMM_ATTR_NODEID] = &comm_attr_nodeid.attr, | ||
113 | [COMM_ATTR_LOCAL] = &comm_attr_local.attr, | ||
114 | [COMM_ATTR_ADDR] = &comm_attr_addr.attr, | ||
115 | NULL, | ||
116 | }; | ||
117 | |||
118 | enum { | ||
119 | NODE_ATTR_NODEID = 0, | ||
120 | NODE_ATTR_WEIGHT, | ||
121 | }; | ||
122 | |||
123 | struct node_attribute { | ||
124 | struct configfs_attribute attr; | ||
125 | ssize_t (*show)(struct node *, char *); | ||
126 | ssize_t (*store)(struct node *, const char *, size_t); | ||
127 | }; | ||
128 | |||
129 | static struct node_attribute node_attr_nodeid = { | ||
130 | .attr = { .ca_owner = THIS_MODULE, | ||
131 | .ca_name = "nodeid", | ||
132 | .ca_mode = S_IRUGO | S_IWUSR }, | ||
133 | .show = node_nodeid_read, | ||
134 | .store = node_nodeid_write, | ||
135 | }; | ||
136 | |||
137 | static struct node_attribute node_attr_weight = { | ||
138 | .attr = { .ca_owner = THIS_MODULE, | ||
139 | .ca_name = "weight", | ||
140 | .ca_mode = S_IRUGO | S_IWUSR }, | ||
141 | .show = node_weight_read, | ||
142 | .store = node_weight_write, | ||
143 | }; | ||
144 | |||
145 | static struct configfs_attribute *node_attrs[] = { | ||
146 | [NODE_ATTR_NODEID] = &node_attr_nodeid.attr, | ||
147 | [NODE_ATTR_WEIGHT] = &node_attr_weight.attr, | ||
148 | NULL, | ||
149 | }; | ||
150 | |||
151 | struct clusters { | ||
152 | struct configfs_subsystem subsys; | ||
153 | }; | ||
154 | |||
155 | struct cluster { | ||
156 | struct config_group group; | ||
157 | }; | ||
158 | |||
159 | struct spaces { | ||
160 | struct config_group ss_group; | ||
161 | }; | ||
162 | |||
163 | struct space { | ||
164 | struct config_group group; | ||
165 | struct list_head members; | ||
166 | struct mutex members_lock; | ||
167 | int members_count; | ||
168 | }; | ||
169 | |||
170 | struct comms { | ||
171 | struct config_group cs_group; | ||
172 | }; | ||
173 | |||
174 | struct comm { | ||
175 | struct config_item item; | ||
176 | int nodeid; | ||
177 | int local; | ||
178 | int addr_count; | ||
179 | struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; | ||
180 | }; | ||
181 | |||
182 | struct nodes { | ||
183 | struct config_group ns_group; | ||
184 | }; | ||
185 | |||
186 | struct node { | ||
187 | struct config_item item; | ||
188 | struct list_head list; /* space->members */ | ||
189 | int nodeid; | ||
190 | int weight; | ||
191 | }; | ||
192 | |||
193 | static struct configfs_group_operations clusters_ops = { | ||
194 | .make_group = make_cluster, | ||
195 | .drop_item = drop_cluster, | ||
196 | }; | ||
197 | |||
198 | static struct configfs_item_operations cluster_ops = { | ||
199 | .release = release_cluster, | ||
200 | }; | ||
201 | |||
202 | static struct configfs_group_operations spaces_ops = { | ||
203 | .make_group = make_space, | ||
204 | .drop_item = drop_space, | ||
205 | }; | ||
206 | |||
207 | static struct configfs_item_operations space_ops = { | ||
208 | .release = release_space, | ||
209 | }; | ||
210 | |||
211 | static struct configfs_group_operations comms_ops = { | ||
212 | .make_item = make_comm, | ||
213 | .drop_item = drop_comm, | ||
214 | }; | ||
215 | |||
216 | static struct configfs_item_operations comm_ops = { | ||
217 | .release = release_comm, | ||
218 | .show_attribute = show_comm, | ||
219 | .store_attribute = store_comm, | ||
220 | }; | ||
221 | |||
222 | static struct configfs_group_operations nodes_ops = { | ||
223 | .make_item = make_node, | ||
224 | .drop_item = drop_node, | ||
225 | }; | ||
226 | |||
227 | static struct configfs_item_operations node_ops = { | ||
228 | .release = release_node, | ||
229 | .show_attribute = show_node, | ||
230 | .store_attribute = store_node, | ||
231 | }; | ||
232 | |||
233 | static struct config_item_type clusters_type = { | ||
234 | .ct_group_ops = &clusters_ops, | ||
235 | .ct_owner = THIS_MODULE, | ||
236 | }; | ||
237 | |||
238 | static struct config_item_type cluster_type = { | ||
239 | .ct_item_ops = &cluster_ops, | ||
240 | .ct_owner = THIS_MODULE, | ||
241 | }; | ||
242 | |||
243 | static struct config_item_type spaces_type = { | ||
244 | .ct_group_ops = &spaces_ops, | ||
245 | .ct_owner = THIS_MODULE, | ||
246 | }; | ||
247 | |||
248 | static struct config_item_type space_type = { | ||
249 | .ct_item_ops = &space_ops, | ||
250 | .ct_owner = THIS_MODULE, | ||
251 | }; | ||
252 | |||
253 | static struct config_item_type comms_type = { | ||
254 | .ct_group_ops = &comms_ops, | ||
255 | .ct_owner = THIS_MODULE, | ||
256 | }; | ||
257 | |||
258 | static struct config_item_type comm_type = { | ||
259 | .ct_item_ops = &comm_ops, | ||
260 | .ct_attrs = comm_attrs, | ||
261 | .ct_owner = THIS_MODULE, | ||
262 | }; | ||
263 | |||
264 | static struct config_item_type nodes_type = { | ||
265 | .ct_group_ops = &nodes_ops, | ||
266 | .ct_owner = THIS_MODULE, | ||
267 | }; | ||
268 | |||
269 | static struct config_item_type node_type = { | ||
270 | .ct_item_ops = &node_ops, | ||
271 | .ct_attrs = node_attrs, | ||
272 | .ct_owner = THIS_MODULE, | ||
273 | }; | ||
274 | |||
275 | static struct cluster *to_cluster(struct config_item *i) | ||
276 | { | ||
277 | return i ? container_of(to_config_group(i), struct cluster, group):NULL; | ||
278 | } | ||
279 | |||
280 | static struct space *to_space(struct config_item *i) | ||
281 | { | ||
282 | return i ? container_of(to_config_group(i), struct space, group) : NULL; | ||
283 | } | ||
284 | |||
285 | static struct comm *to_comm(struct config_item *i) | ||
286 | { | ||
287 | return i ? container_of(i, struct comm, item) : NULL; | ||
288 | } | ||
289 | |||
290 | static struct node *to_node(struct config_item *i) | ||
291 | { | ||
292 | return i ? container_of(i, struct node, item) : NULL; | ||
293 | } | ||
294 | |||
295 | static struct config_group *make_cluster(struct config_group *g, | ||
296 | const char *name) | ||
297 | { | ||
298 | struct cluster *cl = NULL; | ||
299 | struct spaces *sps = NULL; | ||
300 | struct comms *cms = NULL; | ||
301 | void *gps = NULL; | ||
302 | |||
303 | cl = kzalloc(sizeof(struct cluster), GFP_KERNEL); | ||
304 | gps = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); | ||
305 | sps = kzalloc(sizeof(struct spaces), GFP_KERNEL); | ||
306 | cms = kzalloc(sizeof(struct comms), GFP_KERNEL); | ||
307 | |||
308 | if (!cl || !gps || !sps || !cms) | ||
309 | goto fail; | ||
310 | |||
311 | config_group_init_type_name(&cl->group, name, &cluster_type); | ||
312 | config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type); | ||
313 | config_group_init_type_name(&cms->cs_group, "comms", &comms_type); | ||
314 | |||
315 | cl->group.default_groups = gps; | ||
316 | cl->group.default_groups[0] = &sps->ss_group; | ||
317 | cl->group.default_groups[1] = &cms->cs_group; | ||
318 | cl->group.default_groups[2] = NULL; | ||
319 | |||
320 | space_list = &sps->ss_group; | ||
321 | comm_list = &cms->cs_group; | ||
322 | return &cl->group; | ||
323 | |||
324 | fail: | ||
325 | kfree(cl); | ||
326 | kfree(gps); | ||
327 | kfree(sps); | ||
328 | kfree(cms); | ||
329 | return NULL; | ||
330 | } | ||
331 | |||
332 | static void drop_cluster(struct config_group *g, struct config_item *i) | ||
333 | { | ||
334 | struct cluster *cl = to_cluster(i); | ||
335 | struct config_item *tmp; | ||
336 | int j; | ||
337 | |||
338 | for (j = 0; cl->group.default_groups[j]; j++) { | ||
339 | tmp = &cl->group.default_groups[j]->cg_item; | ||
340 | cl->group.default_groups[j] = NULL; | ||
341 | config_item_put(tmp); | ||
342 | } | ||
343 | |||
344 | space_list = NULL; | ||
345 | comm_list = NULL; | ||
346 | |||
347 | config_item_put(i); | ||
348 | } | ||
349 | |||
350 | static void release_cluster(struct config_item *i) | ||
351 | { | ||
352 | struct cluster *cl = to_cluster(i); | ||
353 | kfree(cl->group.default_groups); | ||
354 | kfree(cl); | ||
355 | } | ||
356 | |||
357 | static struct config_group *make_space(struct config_group *g, const char *name) | ||
358 | { | ||
359 | struct space *sp = NULL; | ||
360 | struct nodes *nds = NULL; | ||
361 | void *gps = NULL; | ||
362 | |||
363 | sp = kzalloc(sizeof(struct space), GFP_KERNEL); | ||
364 | gps = kcalloc(2, sizeof(struct config_group *), GFP_KERNEL); | ||
365 | nds = kzalloc(sizeof(struct nodes), GFP_KERNEL); | ||
366 | |||
367 | if (!sp || !gps || !nds) | ||
368 | goto fail; | ||
369 | |||
370 | config_group_init_type_name(&sp->group, name, &space_type); | ||
371 | config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type); | ||
372 | |||
373 | sp->group.default_groups = gps; | ||
374 | sp->group.default_groups[0] = &nds->ns_group; | ||
375 | sp->group.default_groups[1] = NULL; | ||
376 | |||
377 | INIT_LIST_HEAD(&sp->members); | ||
378 | mutex_init(&sp->members_lock); | ||
379 | sp->members_count = 0; | ||
380 | return &sp->group; | ||
381 | |||
382 | fail: | ||
383 | kfree(sp); | ||
384 | kfree(gps); | ||
385 | kfree(nds); | ||
386 | return NULL; | ||
387 | } | ||
388 | |||
389 | static void drop_space(struct config_group *g, struct config_item *i) | ||
390 | { | ||
391 | struct space *sp = to_space(i); | ||
392 | struct config_item *tmp; | ||
393 | int j; | ||
394 | |||
395 | /* assert list_empty(&sp->members) */ | ||
396 | |||
397 | for (j = 0; sp->group.default_groups[j]; j++) { | ||
398 | tmp = &sp->group.default_groups[j]->cg_item; | ||
399 | sp->group.default_groups[j] = NULL; | ||
400 | config_item_put(tmp); | ||
401 | } | ||
402 | |||
403 | config_item_put(i); | ||
404 | } | ||
405 | |||
406 | static void release_space(struct config_item *i) | ||
407 | { | ||
408 | struct space *sp = to_space(i); | ||
409 | kfree(sp->group.default_groups); | ||
410 | kfree(sp); | ||
411 | } | ||
412 | |||
413 | static struct config_item *make_comm(struct config_group *g, const char *name) | ||
414 | { | ||
415 | struct comm *cm; | ||
416 | |||
417 | cm = kzalloc(sizeof(struct comm), GFP_KERNEL); | ||
418 | if (!cm) | ||
419 | return NULL; | ||
420 | |||
421 | config_item_init_type_name(&cm->item, name, &comm_type); | ||
422 | cm->nodeid = -1; | ||
423 | cm->local = 0; | ||
424 | cm->addr_count = 0; | ||
425 | return &cm->item; | ||
426 | } | ||
427 | |||
428 | static void drop_comm(struct config_group *g, struct config_item *i) | ||
429 | { | ||
430 | struct comm *cm = to_comm(i); | ||
431 | if (local_comm == cm) | ||
432 | local_comm = NULL; | ||
433 | dlm_lowcomms_close(cm->nodeid); | ||
434 | while (cm->addr_count--) | ||
435 | kfree(cm->addr[cm->addr_count]); | ||
436 | config_item_put(i); | ||
437 | } | ||
438 | |||
439 | static void release_comm(struct config_item *i) | ||
440 | { | ||
441 | struct comm *cm = to_comm(i); | ||
442 | kfree(cm); | ||
443 | } | ||
444 | |||
445 | static struct config_item *make_node(struct config_group *g, const char *name) | ||
446 | { | ||
447 | struct space *sp = to_space(g->cg_item.ci_parent); | ||
448 | struct node *nd; | ||
449 | |||
450 | nd = kzalloc(sizeof(struct node), GFP_KERNEL); | ||
451 | if (!nd) | ||
452 | return NULL; | ||
453 | |||
454 | config_item_init_type_name(&nd->item, name, &node_type); | ||
455 | nd->nodeid = -1; | ||
456 | nd->weight = 1; /* default weight of 1 if none is set */ | ||
457 | |||
458 | mutex_lock(&sp->members_lock); | ||
459 | list_add(&nd->list, &sp->members); | ||
460 | sp->members_count++; | ||
461 | mutex_unlock(&sp->members_lock); | ||
462 | |||
463 | return &nd->item; | ||
464 | } | ||
465 | |||
466 | static void drop_node(struct config_group *g, struct config_item *i) | ||
467 | { | ||
468 | struct space *sp = to_space(g->cg_item.ci_parent); | ||
469 | struct node *nd = to_node(i); | ||
470 | |||
471 | mutex_lock(&sp->members_lock); | ||
472 | list_del(&nd->list); | ||
473 | sp->members_count--; | ||
474 | mutex_unlock(&sp->members_lock); | ||
475 | |||
476 | config_item_put(i); | ||
477 | } | ||
478 | |||
479 | static void release_node(struct config_item *i) | ||
480 | { | ||
481 | struct node *nd = to_node(i); | ||
482 | kfree(nd); | ||
483 | } | ||
484 | |||
485 | static struct clusters clusters_root = { | ||
486 | .subsys = { | ||
487 | .su_group = { | ||
488 | .cg_item = { | ||
489 | .ci_namebuf = "dlm", | ||
490 | .ci_type = &clusters_type, | ||
491 | }, | ||
492 | }, | ||
493 | }, | ||
494 | }; | ||
495 | |||
496 | int dlm_config_init(void) | ||
497 | { | ||
498 | config_group_init(&clusters_root.subsys.su_group); | ||
499 | init_MUTEX(&clusters_root.subsys.su_sem); | ||
500 | return configfs_register_subsystem(&clusters_root.subsys); | ||
501 | } | ||
502 | |||
503 | void dlm_config_exit(void) | ||
504 | { | ||
505 | configfs_unregister_subsystem(&clusters_root.subsys); | ||
506 | } | ||
507 | |||
508 | /* | ||
509 | * Functions for user space to read/write attributes | ||
510 | */ | ||
511 | |||
512 | static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, | ||
513 | char *buf) | ||
514 | { | ||
515 | struct comm *cm = to_comm(i); | ||
516 | struct comm_attribute *cma = | ||
517 | container_of(a, struct comm_attribute, attr); | ||
518 | return cma->show ? cma->show(cm, buf) : 0; | ||
519 | } | ||
520 | |||
521 | static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, | ||
522 | const char *buf, size_t len) | ||
523 | { | ||
524 | struct comm *cm = to_comm(i); | ||
525 | struct comm_attribute *cma = | ||
526 | container_of(a, struct comm_attribute, attr); | ||
527 | return cma->store ? cma->store(cm, buf, len) : -EINVAL; | ||
528 | } | ||
529 | |||
530 | static ssize_t comm_nodeid_read(struct comm *cm, char *buf) | ||
531 | { | ||
532 | return sprintf(buf, "%d\n", cm->nodeid); | ||
533 | } | ||
534 | |||
535 | static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len) | ||
536 | { | ||
537 | cm->nodeid = simple_strtol(buf, NULL, 0); | ||
538 | return len; | ||
539 | } | ||
540 | |||
541 | static ssize_t comm_local_read(struct comm *cm, char *buf) | ||
542 | { | ||
543 | return sprintf(buf, "%d\n", cm->local); | ||
544 | } | ||
545 | |||
546 | static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len) | ||
547 | { | ||
548 | cm->local= simple_strtol(buf, NULL, 0); | ||
549 | if (cm->local && !local_comm) | ||
550 | local_comm = cm; | ||
551 | return len; | ||
552 | } | ||
553 | |||
554 | static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len) | ||
555 | { | ||
556 | struct sockaddr_storage *addr; | ||
557 | |||
558 | if (len != sizeof(struct sockaddr_storage)) | ||
559 | return -EINVAL; | ||
560 | |||
561 | if (cm->addr_count >= DLM_MAX_ADDR_COUNT) | ||
562 | return -ENOSPC; | ||
563 | |||
564 | addr = kzalloc(sizeof(*addr), GFP_KERNEL); | ||
565 | if (!addr) | ||
566 | return -ENOMEM; | ||
567 | |||
568 | memcpy(addr, buf, len); | ||
569 | cm->addr[cm->addr_count++] = addr; | ||
570 | return len; | ||
571 | } | ||
572 | |||
573 | static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, | ||
574 | char *buf) | ||
575 | { | ||
576 | struct node *nd = to_node(i); | ||
577 | struct node_attribute *nda = | ||
578 | container_of(a, struct node_attribute, attr); | ||
579 | return nda->show ? nda->show(nd, buf) : 0; | ||
580 | } | ||
581 | |||
582 | static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, | ||
583 | const char *buf, size_t len) | ||
584 | { | ||
585 | struct node *nd = to_node(i); | ||
586 | struct node_attribute *nda = | ||
587 | container_of(a, struct node_attribute, attr); | ||
588 | return nda->store ? nda->store(nd, buf, len) : -EINVAL; | ||
589 | } | ||
590 | |||
591 | static ssize_t node_nodeid_read(struct node *nd, char *buf) | ||
592 | { | ||
593 | return sprintf(buf, "%d\n", nd->nodeid); | ||
594 | } | ||
595 | |||
596 | static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len) | ||
597 | { | ||
598 | nd->nodeid = simple_strtol(buf, NULL, 0); | ||
599 | return len; | ||
600 | } | ||
601 | |||
602 | static ssize_t node_weight_read(struct node *nd, char *buf) | ||
603 | { | ||
604 | return sprintf(buf, "%d\n", nd->weight); | ||
605 | } | ||
606 | |||
607 | static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len) | ||
608 | { | ||
609 | nd->weight = simple_strtol(buf, NULL, 0); | ||
610 | return len; | ||
611 | } | ||
612 | |||
613 | /* | ||
614 | * Functions for the dlm to get the info that's been configured | ||
615 | */ | ||
616 | |||
617 | static struct space *get_space(char *name) | ||
618 | { | ||
619 | if (!space_list) | ||
620 | return NULL; | ||
621 | return to_space(config_group_find_obj(space_list, name)); | ||
622 | } | ||
623 | |||
624 | static void put_space(struct space *sp) | ||
625 | { | ||
626 | config_item_put(&sp->group.cg_item); | ||
627 | } | ||
628 | |||
629 | static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr) | ||
630 | { | ||
631 | struct config_item *i; | ||
632 | struct comm *cm = NULL; | ||
633 | int found = 0; | ||
634 | |||
635 | if (!comm_list) | ||
636 | return NULL; | ||
637 | |||
638 | down(&clusters_root.subsys.su_sem); | ||
639 | |||
640 | list_for_each_entry(i, &comm_list->cg_children, ci_entry) { | ||
641 | cm = to_comm(i); | ||
642 | |||
643 | if (nodeid) { | ||
644 | if (cm->nodeid != nodeid) | ||
645 | continue; | ||
646 | found = 1; | ||
647 | break; | ||
648 | } else { | ||
649 | if (!cm->addr_count || | ||
650 | memcmp(cm->addr[0], addr, sizeof(*addr))) | ||
651 | continue; | ||
652 | found = 1; | ||
653 | break; | ||
654 | } | ||
655 | } | ||
656 | up(&clusters_root.subsys.su_sem); | ||
657 | |||
658 | if (found) | ||
659 | config_item_get(i); | ||
660 | else | ||
661 | cm = NULL; | ||
662 | return cm; | ||
663 | } | ||
664 | |||
665 | static void put_comm(struct comm *cm) | ||
666 | { | ||
667 | config_item_put(&cm->item); | ||
668 | } | ||
669 | |||
670 | /* caller must free mem */ | ||
671 | int dlm_nodeid_list(char *lsname, int **ids_out) | ||
672 | { | ||
673 | struct space *sp; | ||
674 | struct node *nd; | ||
675 | int i = 0, rv = 0; | ||
676 | int *ids; | ||
677 | |||
678 | sp = get_space(lsname); | ||
679 | if (!sp) | ||
680 | return -EEXIST; | ||
681 | |||
682 | mutex_lock(&sp->members_lock); | ||
683 | if (!sp->members_count) { | ||
684 | rv = 0; | ||
685 | goto out; | ||
686 | } | ||
687 | |||
688 | ids = kcalloc(sp->members_count, sizeof(int), GFP_KERNEL); | ||
689 | if (!ids) { | ||
690 | rv = -ENOMEM; | ||
691 | goto out; | ||
692 | } | ||
693 | |||
694 | rv = sp->members_count; | ||
695 | list_for_each_entry(nd, &sp->members, list) | ||
696 | ids[i++] = nd->nodeid; | ||
697 | |||
698 | if (rv != i) | ||
699 | printk("bad nodeid count %d %d\n", rv, i); | ||
700 | |||
701 | *ids_out = ids; | ||
702 | out: | ||
703 | mutex_unlock(&sp->members_lock); | ||
704 | put_space(sp); | ||
705 | return rv; | ||
706 | } | ||
707 | |||
708 | int dlm_node_weight(char *lsname, int nodeid) | ||
709 | { | ||
710 | struct space *sp; | ||
711 | struct node *nd; | ||
712 | int w = -EEXIST; | ||
713 | |||
714 | sp = get_space(lsname); | ||
715 | if (!sp) | ||
716 | goto out; | ||
717 | |||
718 | mutex_lock(&sp->members_lock); | ||
719 | list_for_each_entry(nd, &sp->members, list) { | ||
720 | if (nd->nodeid != nodeid) | ||
721 | continue; | ||
722 | w = nd->weight; | ||
723 | break; | ||
724 | } | ||
725 | mutex_unlock(&sp->members_lock); | ||
726 | put_space(sp); | ||
727 | out: | ||
728 | return w; | ||
729 | } | ||
730 | |||
731 | int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) | ||
732 | { | ||
733 | struct comm *cm = get_comm(nodeid, NULL); | ||
734 | if (!cm) | ||
735 | return -EEXIST; | ||
736 | if (!cm->addr_count) | ||
737 | return -ENOENT; | ||
738 | memcpy(addr, cm->addr[0], sizeof(*addr)); | ||
739 | put_comm(cm); | ||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) | ||
744 | { | ||
745 | struct comm *cm = get_comm(0, addr); | ||
746 | if (!cm) | ||
747 | return -EEXIST; | ||
748 | *nodeid = cm->nodeid; | ||
749 | put_comm(cm); | ||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | int dlm_our_nodeid(void) | ||
754 | { | ||
755 | return local_comm ? local_comm->nodeid : 0; | ||
756 | } | ||
757 | |||
758 | /* num 0 is first addr, num 1 is second addr */ | ||
759 | int dlm_our_addr(struct sockaddr_storage *addr, int num) | ||
760 | { | ||
761 | if (!local_comm) | ||
762 | return -1; | ||
763 | if (num + 1 > local_comm->addr_count) | ||
764 | return -1; | ||
765 | memcpy(addr, local_comm->addr[num], sizeof(*addr)); | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | /* Config file defaults */ | ||
770 | #define DEFAULT_TCP_PORT 21064 | ||
771 | #define DEFAULT_BUFFER_SIZE 4096 | ||
772 | #define DEFAULT_RSBTBL_SIZE 256 | ||
773 | #define DEFAULT_LKBTBL_SIZE 1024 | ||
774 | #define DEFAULT_DIRTBL_SIZE 512 | ||
775 | #define DEFAULT_RECOVER_TIMER 5 | ||
776 | #define DEFAULT_TOSS_SECS 10 | ||
777 | #define DEFAULT_SCAN_SECS 5 | ||
778 | |||
779 | struct dlm_config_info dlm_config = { | ||
780 | .tcp_port = DEFAULT_TCP_PORT, | ||
781 | .buffer_size = DEFAULT_BUFFER_SIZE, | ||
782 | .rsbtbl_size = DEFAULT_RSBTBL_SIZE, | ||
783 | .lkbtbl_size = DEFAULT_LKBTBL_SIZE, | ||
784 | .dirtbl_size = DEFAULT_DIRTBL_SIZE, | ||
785 | .recover_timer = DEFAULT_RECOVER_TIMER, | ||
786 | .toss_secs = DEFAULT_TOSS_SECS, | ||
787 | .scan_secs = DEFAULT_SCAN_SECS | ||
788 | }; | ||
789 | |||