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