Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/dlm/config.c
29265 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/******************************************************************************
3
*******************************************************************************
4
**
5
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
6
** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
7
**
8
**
9
*******************************************************************************
10
******************************************************************************/
11
12
#include <linux/kernel.h>
13
#include <linux/init.h>
14
#include <linux/configfs.h>
15
#include <linux/slab.h>
16
#include <linux/in.h>
17
#include <linux/in6.h>
18
#include <linux/dlmconstants.h>
19
#include <net/ipv6.h>
20
#include <net/sock.h>
21
22
#include "config.h"
23
#include "midcomms.h"
24
#include "lowcomms.h"
25
26
/*
27
* /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid (refers to <node>)
28
* /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight
29
* /config/dlm/<cluster>/spaces/<space>/nodes/<node>/release_recover
30
* /config/dlm/<cluster>/comms/<comm>/nodeid (refers to <comm>)
31
* /config/dlm/<cluster>/comms/<comm>/local
32
* /config/dlm/<cluster>/comms/<comm>/addr (write only)
33
* /config/dlm/<cluster>/comms/<comm>/addr_list (read only)
34
* The <cluster> level is useless, but I haven't figured out how to avoid it.
35
*/
36
37
static struct config_group *space_list;
38
static struct config_group *comm_list;
39
static struct dlm_comm *local_comm;
40
static uint32_t dlm_comm_count;
41
42
struct dlm_clusters;
43
struct dlm_cluster;
44
struct dlm_spaces;
45
struct dlm_space;
46
struct dlm_comms;
47
struct dlm_comm;
48
struct dlm_nodes;
49
struct dlm_node;
50
51
static struct config_group *make_cluster(struct config_group *, const char *);
52
static void drop_cluster(struct config_group *, struct config_item *);
53
static void release_cluster(struct config_item *);
54
static struct config_group *make_space(struct config_group *, const char *);
55
static void drop_space(struct config_group *, struct config_item *);
56
static void release_space(struct config_item *);
57
static struct config_item *make_comm(struct config_group *, const char *);
58
static void drop_comm(struct config_group *, struct config_item *);
59
static void release_comm(struct config_item *);
60
static struct config_item *make_node(struct config_group *, const char *);
61
static void drop_node(struct config_group *, struct config_item *);
62
static void release_node(struct config_item *);
63
64
static struct configfs_attribute *comm_attrs[];
65
static struct configfs_attribute *node_attrs[];
66
67
const struct rhashtable_params dlm_rhash_rsb_params = {
68
.nelem_hint = 3, /* start small */
69
.key_len = DLM_RESNAME_MAXLEN,
70
.key_offset = offsetof(struct dlm_rsb, res_name),
71
.head_offset = offsetof(struct dlm_rsb, res_node),
72
.automatic_shrinking = true,
73
};
74
75
struct dlm_cluster {
76
struct config_group group;
77
struct dlm_spaces *sps;
78
struct dlm_comms *cms;
79
};
80
81
static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
82
{
83
return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
84
NULL;
85
}
86
87
enum {
88
CLUSTER_ATTR_TCP_PORT = 0,
89
CLUSTER_ATTR_BUFFER_SIZE,
90
CLUSTER_ATTR_RSBTBL_SIZE,
91
CLUSTER_ATTR_RECOVER_TIMER,
92
CLUSTER_ATTR_TOSS_SECS,
93
CLUSTER_ATTR_SCAN_SECS,
94
CLUSTER_ATTR_LOG_DEBUG,
95
CLUSTER_ATTR_LOG_INFO,
96
CLUSTER_ATTR_PROTOCOL,
97
CLUSTER_ATTR_MARK,
98
CLUSTER_ATTR_NEW_RSB_COUNT,
99
CLUSTER_ATTR_RECOVER_CALLBACKS,
100
CLUSTER_ATTR_CLUSTER_NAME,
101
};
102
103
static ssize_t cluster_cluster_name_show(struct config_item *item, char *buf)
104
{
105
return sprintf(buf, "%s\n", dlm_config.ci_cluster_name);
106
}
107
108
static ssize_t cluster_cluster_name_store(struct config_item *item,
109
const char *buf, size_t len)
110
{
111
strscpy(dlm_config.ci_cluster_name, buf,
112
sizeof(dlm_config.ci_cluster_name));
113
return len;
114
}
115
116
CONFIGFS_ATTR(cluster_, cluster_name);
117
118
static ssize_t cluster_tcp_port_show(struct config_item *item, char *buf)
119
{
120
return sprintf(buf, "%u\n", be16_to_cpu(dlm_config.ci_tcp_port));
121
}
122
123
static int dlm_check_zero_and_dlm_running(unsigned int x)
124
{
125
if (!x)
126
return -EINVAL;
127
128
if (dlm_lowcomms_is_running())
129
return -EBUSY;
130
131
return 0;
132
}
133
134
static ssize_t cluster_tcp_port_store(struct config_item *item,
135
const char *buf, size_t len)
136
{
137
int rc;
138
u16 x;
139
140
if (!capable(CAP_SYS_ADMIN))
141
return -EPERM;
142
143
rc = kstrtou16(buf, 0, &x);
144
if (rc)
145
return rc;
146
147
rc = dlm_check_zero_and_dlm_running(x);
148
if (rc)
149
return rc;
150
151
dlm_config.ci_tcp_port = cpu_to_be16(x);
152
return len;
153
}
154
155
CONFIGFS_ATTR(cluster_, tcp_port);
156
157
static ssize_t cluster_set(unsigned int *info_field,
158
int (*check_cb)(unsigned int x),
159
const char *buf, size_t len)
160
{
161
unsigned int x;
162
int rc;
163
164
if (!capable(CAP_SYS_ADMIN))
165
return -EPERM;
166
rc = kstrtouint(buf, 0, &x);
167
if (rc)
168
return rc;
169
170
if (check_cb) {
171
rc = check_cb(x);
172
if (rc)
173
return rc;
174
}
175
176
*info_field = x;
177
178
return len;
179
}
180
181
#define CLUSTER_ATTR(name, check_cb) \
182
static ssize_t cluster_##name##_store(struct config_item *item, \
183
const char *buf, size_t len) \
184
{ \
185
return cluster_set(&dlm_config.ci_##name, check_cb, buf, len); \
186
} \
187
static ssize_t cluster_##name##_show(struct config_item *item, char *buf) \
188
{ \
189
return snprintf(buf, PAGE_SIZE, "%u\n", dlm_config.ci_##name); \
190
} \
191
CONFIGFS_ATTR(cluster_, name);
192
193
static int dlm_check_protocol_and_dlm_running(unsigned int x)
194
{
195
switch (x) {
196
case 0:
197
/* TCP */
198
break;
199
case 1:
200
/* SCTP */
201
if (!IS_ENABLED(CONFIG_IP_SCTP))
202
return -EOPNOTSUPP;
203
204
break;
205
default:
206
return -EINVAL;
207
}
208
209
if (dlm_lowcomms_is_running())
210
return -EBUSY;
211
212
return 0;
213
}
214
215
static int dlm_check_zero(unsigned int x)
216
{
217
if (!x)
218
return -EINVAL;
219
220
return 0;
221
}
222
223
static int dlm_check_buffer_size(unsigned int x)
224
{
225
if (x < DLM_MAX_SOCKET_BUFSIZE)
226
return -EINVAL;
227
228
return 0;
229
}
230
231
CLUSTER_ATTR(buffer_size, dlm_check_buffer_size);
232
CLUSTER_ATTR(rsbtbl_size, dlm_check_zero);
233
CLUSTER_ATTR(recover_timer, dlm_check_zero);
234
CLUSTER_ATTR(toss_secs, dlm_check_zero);
235
CLUSTER_ATTR(scan_secs, dlm_check_zero);
236
CLUSTER_ATTR(log_debug, NULL);
237
CLUSTER_ATTR(log_info, NULL);
238
CLUSTER_ATTR(protocol, dlm_check_protocol_and_dlm_running);
239
CLUSTER_ATTR(mark, NULL);
240
CLUSTER_ATTR(new_rsb_count, NULL);
241
CLUSTER_ATTR(recover_callbacks, NULL);
242
243
static struct configfs_attribute *cluster_attrs[] = {
244
[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port,
245
[CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size,
246
[CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size,
247
[CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer,
248
[CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs,
249
[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs,
250
[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug,
251
[CLUSTER_ATTR_LOG_INFO] = &cluster_attr_log_info,
252
[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol,
253
[CLUSTER_ATTR_MARK] = &cluster_attr_mark,
254
[CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count,
255
[CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks,
256
[CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name,
257
NULL,
258
};
259
260
enum {
261
COMM_ATTR_NODEID = 0,
262
COMM_ATTR_LOCAL,
263
COMM_ATTR_ADDR,
264
COMM_ATTR_ADDR_LIST,
265
COMM_ATTR_MARK,
266
};
267
268
enum {
269
NODE_ATTR_NODEID = 0,
270
NODE_ATTR_WEIGHT,
271
NODE_ATTR_RELEASE_RECOVER,
272
};
273
274
struct dlm_clusters {
275
struct configfs_subsystem subsys;
276
};
277
278
struct dlm_spaces {
279
struct config_group ss_group;
280
};
281
282
struct dlm_space {
283
struct config_group group;
284
struct list_head members;
285
struct list_head members_gone;
286
int members_gone_count;
287
struct mutex members_lock;
288
int members_count;
289
struct dlm_nodes *nds;
290
};
291
292
struct dlm_comms {
293
struct config_group cs_group;
294
};
295
296
struct dlm_comm {
297
struct config_item item;
298
int seq;
299
int nodeid;
300
int local;
301
int addr_count;
302
unsigned int mark;
303
struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
304
};
305
306
struct dlm_nodes {
307
struct config_group ns_group;
308
};
309
310
struct dlm_node {
311
struct config_item item;
312
struct list_head list; /* space->members */
313
int nodeid;
314
int weight;
315
int new;
316
int comm_seq; /* copy of cm->seq when nd->nodeid is set */
317
unsigned int release_recover;
318
};
319
320
struct dlm_member_gone {
321
int nodeid;
322
unsigned int release_recover;
323
324
struct list_head list; /* space->members_gone */
325
};
326
327
static struct configfs_group_operations clusters_ops = {
328
.make_group = make_cluster,
329
.drop_item = drop_cluster,
330
};
331
332
static struct configfs_item_operations cluster_ops = {
333
.release = release_cluster,
334
};
335
336
static struct configfs_group_operations spaces_ops = {
337
.make_group = make_space,
338
.drop_item = drop_space,
339
};
340
341
static struct configfs_item_operations space_ops = {
342
.release = release_space,
343
};
344
345
static struct configfs_group_operations comms_ops = {
346
.make_item = make_comm,
347
.drop_item = drop_comm,
348
};
349
350
static struct configfs_item_operations comm_ops = {
351
.release = release_comm,
352
};
353
354
static struct configfs_group_operations nodes_ops = {
355
.make_item = make_node,
356
.drop_item = drop_node,
357
};
358
359
static struct configfs_item_operations node_ops = {
360
.release = release_node,
361
};
362
363
static const struct config_item_type clusters_type = {
364
.ct_group_ops = &clusters_ops,
365
.ct_owner = THIS_MODULE,
366
};
367
368
static const struct config_item_type cluster_type = {
369
.ct_item_ops = &cluster_ops,
370
.ct_attrs = cluster_attrs,
371
.ct_owner = THIS_MODULE,
372
};
373
374
static const struct config_item_type spaces_type = {
375
.ct_group_ops = &spaces_ops,
376
.ct_owner = THIS_MODULE,
377
};
378
379
static const struct config_item_type space_type = {
380
.ct_item_ops = &space_ops,
381
.ct_owner = THIS_MODULE,
382
};
383
384
static const struct config_item_type comms_type = {
385
.ct_group_ops = &comms_ops,
386
.ct_owner = THIS_MODULE,
387
};
388
389
static const struct config_item_type comm_type = {
390
.ct_item_ops = &comm_ops,
391
.ct_attrs = comm_attrs,
392
.ct_owner = THIS_MODULE,
393
};
394
395
static const struct config_item_type nodes_type = {
396
.ct_group_ops = &nodes_ops,
397
.ct_owner = THIS_MODULE,
398
};
399
400
static const struct config_item_type node_type = {
401
.ct_item_ops = &node_ops,
402
.ct_attrs = node_attrs,
403
.ct_owner = THIS_MODULE,
404
};
405
406
static struct dlm_space *config_item_to_space(struct config_item *i)
407
{
408
return i ? container_of(to_config_group(i), struct dlm_space, group) :
409
NULL;
410
}
411
412
static struct dlm_comm *config_item_to_comm(struct config_item *i)
413
{
414
return i ? container_of(i, struct dlm_comm, item) : NULL;
415
}
416
417
static struct dlm_node *config_item_to_node(struct config_item *i)
418
{
419
return i ? container_of(i, struct dlm_node, item) : NULL;
420
}
421
422
static struct config_group *make_cluster(struct config_group *g,
423
const char *name)
424
{
425
struct dlm_cluster *cl = NULL;
426
struct dlm_spaces *sps = NULL;
427
struct dlm_comms *cms = NULL;
428
429
cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS);
430
sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS);
431
cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS);
432
433
if (!cl || !sps || !cms)
434
goto fail;
435
436
cl->sps = sps;
437
cl->cms = cms;
438
439
config_group_init_type_name(&cl->group, name, &cluster_type);
440
config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type);
441
config_group_init_type_name(&cms->cs_group, "comms", &comms_type);
442
443
configfs_add_default_group(&sps->ss_group, &cl->group);
444
configfs_add_default_group(&cms->cs_group, &cl->group);
445
446
space_list = &sps->ss_group;
447
comm_list = &cms->cs_group;
448
return &cl->group;
449
450
fail:
451
kfree(cl);
452
kfree(sps);
453
kfree(cms);
454
return ERR_PTR(-ENOMEM);
455
}
456
457
static void drop_cluster(struct config_group *g, struct config_item *i)
458
{
459
struct dlm_cluster *cl = config_item_to_cluster(i);
460
461
configfs_remove_default_groups(&cl->group);
462
463
space_list = NULL;
464
comm_list = NULL;
465
466
config_item_put(i);
467
}
468
469
static void release_cluster(struct config_item *i)
470
{
471
struct dlm_cluster *cl = config_item_to_cluster(i);
472
473
kfree(cl->sps);
474
kfree(cl->cms);
475
kfree(cl);
476
}
477
478
static struct config_group *make_space(struct config_group *g, const char *name)
479
{
480
struct dlm_space *sp = NULL;
481
struct dlm_nodes *nds = NULL;
482
483
sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS);
484
nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS);
485
486
if (!sp || !nds)
487
goto fail;
488
489
config_group_init_type_name(&sp->group, name, &space_type);
490
491
config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type);
492
configfs_add_default_group(&nds->ns_group, &sp->group);
493
494
INIT_LIST_HEAD(&sp->members);
495
INIT_LIST_HEAD(&sp->members_gone);
496
mutex_init(&sp->members_lock);
497
sp->members_count = 0;
498
sp->nds = nds;
499
return &sp->group;
500
501
fail:
502
kfree(sp);
503
kfree(nds);
504
return ERR_PTR(-ENOMEM);
505
}
506
507
static void drop_space(struct config_group *g, struct config_item *i)
508
{
509
struct dlm_space *sp = config_item_to_space(i);
510
511
/* assert list_empty(&sp->members) */
512
513
configfs_remove_default_groups(&sp->group);
514
config_item_put(i);
515
}
516
517
static void release_space(struct config_item *i)
518
{
519
struct dlm_space *sp = config_item_to_space(i);
520
kfree(sp->nds);
521
kfree(sp);
522
}
523
524
static struct config_item *make_comm(struct config_group *g, const char *name)
525
{
526
struct dlm_comm *cm;
527
unsigned int nodeid;
528
int rv;
529
530
rv = kstrtouint(name, 0, &nodeid);
531
if (rv)
532
return ERR_PTR(rv);
533
534
cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS);
535
if (!cm)
536
return ERR_PTR(-ENOMEM);
537
538
config_item_init_type_name(&cm->item, name, &comm_type);
539
540
cm->seq = dlm_comm_count++;
541
if (!cm->seq)
542
cm->seq = dlm_comm_count++;
543
544
cm->nodeid = nodeid;
545
cm->local = 0;
546
cm->addr_count = 0;
547
cm->mark = 0;
548
return &cm->item;
549
}
550
551
static void drop_comm(struct config_group *g, struct config_item *i)
552
{
553
struct dlm_comm *cm = config_item_to_comm(i);
554
if (local_comm == cm)
555
local_comm = NULL;
556
dlm_midcomms_close(cm->nodeid);
557
while (cm->addr_count--)
558
kfree(cm->addr[cm->addr_count]);
559
config_item_put(i);
560
}
561
562
static void release_comm(struct config_item *i)
563
{
564
struct dlm_comm *cm = config_item_to_comm(i);
565
kfree(cm);
566
}
567
568
static struct config_item *make_node(struct config_group *g, const char *name)
569
{
570
struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
571
unsigned int nodeid;
572
struct dlm_node *nd;
573
uint32_t seq = 0;
574
int rv;
575
576
rv = kstrtouint(name, 0, &nodeid);
577
if (rv)
578
return ERR_PTR(rv);
579
580
nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS);
581
if (!nd)
582
return ERR_PTR(-ENOMEM);
583
584
config_item_init_type_name(&nd->item, name, &node_type);
585
nd->nodeid = nodeid;
586
nd->weight = 1; /* default weight of 1 if none is set */
587
nd->new = 1; /* set to 0 once it's been read by dlm_nodeid_list() */
588
dlm_comm_seq(nodeid, &seq, true);
589
nd->comm_seq = seq;
590
591
mutex_lock(&sp->members_lock);
592
list_add(&nd->list, &sp->members);
593
sp->members_count++;
594
mutex_unlock(&sp->members_lock);
595
596
return &nd->item;
597
}
598
599
static void drop_node(struct config_group *g, struct config_item *i)
600
{
601
struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
602
struct dlm_node *nd = config_item_to_node(i);
603
struct dlm_member_gone *mb_gone;
604
605
mb_gone = kzalloc(sizeof(*mb_gone), GFP_KERNEL);
606
if (!mb_gone)
607
return;
608
609
mutex_lock(&sp->members_lock);
610
list_del(&nd->list);
611
sp->members_count--;
612
613
mb_gone->nodeid = nd->nodeid;
614
mb_gone->release_recover = nd->release_recover;
615
list_add(&mb_gone->list, &sp->members_gone);
616
sp->members_gone_count++;
617
mutex_unlock(&sp->members_lock);
618
619
config_item_put(i);
620
}
621
622
static void release_node(struct config_item *i)
623
{
624
struct dlm_node *nd = config_item_to_node(i);
625
kfree(nd);
626
}
627
628
static struct dlm_clusters clusters_root = {
629
.subsys = {
630
.su_group = {
631
.cg_item = {
632
.ci_namebuf = "dlm",
633
.ci_type = &clusters_type,
634
},
635
},
636
},
637
};
638
639
int __init dlm_config_init(void)
640
{
641
config_group_init(&clusters_root.subsys.su_group);
642
mutex_init(&clusters_root.subsys.su_mutex);
643
return configfs_register_subsystem(&clusters_root.subsys);
644
}
645
646
void dlm_config_exit(void)
647
{
648
configfs_unregister_subsystem(&clusters_root.subsys);
649
}
650
651
/*
652
* Functions for user space to read/write attributes
653
*/
654
655
static ssize_t comm_nodeid_show(struct config_item *item, char *buf)
656
{
657
unsigned int nodeid;
658
int rv;
659
660
rv = kstrtouint(config_item_name(item), 0, &nodeid);
661
if (WARN_ON(rv))
662
return rv;
663
664
return sprintf(buf, "%u\n", nodeid);
665
}
666
667
static ssize_t comm_nodeid_store(struct config_item *item, const char *buf,
668
size_t len)
669
{
670
return len;
671
}
672
673
static ssize_t comm_local_show(struct config_item *item, char *buf)
674
{
675
return sprintf(buf, "%d\n", config_item_to_comm(item)->local);
676
}
677
678
static ssize_t comm_local_store(struct config_item *item, const char *buf,
679
size_t len)
680
{
681
struct dlm_comm *cm = config_item_to_comm(item);
682
int rc = kstrtoint(buf, 0, &cm->local);
683
684
if (rc)
685
return rc;
686
if (cm->local && !local_comm)
687
local_comm = cm;
688
return len;
689
}
690
691
static ssize_t comm_addr_store(struct config_item *item, const char *buf,
692
size_t len)
693
{
694
struct dlm_comm *cm = config_item_to_comm(item);
695
struct sockaddr_storage *addr;
696
int rv;
697
698
if (len != sizeof(struct sockaddr_storage))
699
return -EINVAL;
700
701
if (cm->addr_count >= DLM_MAX_ADDR_COUNT)
702
return -ENOSPC;
703
704
addr = kzalloc(sizeof(*addr), GFP_NOFS);
705
if (!addr)
706
return -ENOMEM;
707
708
memcpy(addr, buf, len);
709
710
rv = dlm_midcomms_addr(cm->nodeid, addr);
711
if (rv) {
712
kfree(addr);
713
return rv;
714
}
715
716
cm->addr[cm->addr_count++] = addr;
717
return len;
718
}
719
720
static ssize_t comm_addr_list_show(struct config_item *item, char *buf)
721
{
722
struct dlm_comm *cm = config_item_to_comm(item);
723
ssize_t s;
724
ssize_t allowance;
725
int i;
726
struct sockaddr_storage *addr;
727
struct sockaddr_in *addr_in;
728
struct sockaddr_in6 *addr_in6;
729
730
/* Taken from ip6_addr_string() defined in lib/vsprintf.c */
731
char buf0[sizeof("AF_INET6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255\n")];
732
733
734
/* Derived from SIMPLE_ATTR_SIZE of fs/configfs/file.c */
735
allowance = 4096;
736
buf[0] = '\0';
737
738
for (i = 0; i < cm->addr_count; i++) {
739
addr = cm->addr[i];
740
741
switch(addr->ss_family) {
742
case AF_INET:
743
addr_in = (struct sockaddr_in *)addr;
744
s = sprintf(buf0, "AF_INET %pI4\n", &addr_in->sin_addr.s_addr);
745
break;
746
case AF_INET6:
747
addr_in6 = (struct sockaddr_in6 *)addr;
748
s = sprintf(buf0, "AF_INET6 %pI6\n", &addr_in6->sin6_addr);
749
break;
750
default:
751
s = sprintf(buf0, "%s\n", "<UNKNOWN>");
752
break;
753
}
754
allowance -= s;
755
if (allowance >= 0)
756
strcat(buf, buf0);
757
else {
758
allowance += s;
759
break;
760
}
761
}
762
return 4096 - allowance;
763
}
764
765
static ssize_t comm_mark_show(struct config_item *item, char *buf)
766
{
767
return sprintf(buf, "%u\n", config_item_to_comm(item)->mark);
768
}
769
770
static ssize_t comm_mark_store(struct config_item *item, const char *buf,
771
size_t len)
772
{
773
struct dlm_comm *comm;
774
unsigned int mark;
775
int rc;
776
777
rc = kstrtouint(buf, 0, &mark);
778
if (rc)
779
return rc;
780
781
if (mark == 0)
782
mark = dlm_config.ci_mark;
783
784
comm = config_item_to_comm(item);
785
rc = dlm_lowcomms_nodes_set_mark(comm->nodeid, mark);
786
if (rc)
787
return rc;
788
789
comm->mark = mark;
790
return len;
791
}
792
793
CONFIGFS_ATTR(comm_, nodeid);
794
CONFIGFS_ATTR(comm_, local);
795
CONFIGFS_ATTR(comm_, mark);
796
CONFIGFS_ATTR_WO(comm_, addr);
797
CONFIGFS_ATTR_RO(comm_, addr_list);
798
799
static struct configfs_attribute *comm_attrs[] = {
800
[COMM_ATTR_NODEID] = &comm_attr_nodeid,
801
[COMM_ATTR_LOCAL] = &comm_attr_local,
802
[COMM_ATTR_ADDR] = &comm_attr_addr,
803
[COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list,
804
[COMM_ATTR_MARK] = &comm_attr_mark,
805
NULL,
806
};
807
808
static ssize_t node_nodeid_show(struct config_item *item, char *buf)
809
{
810
unsigned int nodeid;
811
int rv;
812
813
rv = kstrtouint(config_item_name(item), 0, &nodeid);
814
if (WARN_ON(rv))
815
return rv;
816
817
return sprintf(buf, "%u\n", nodeid);
818
}
819
820
static ssize_t node_nodeid_store(struct config_item *item, const char *buf,
821
size_t len)
822
{
823
return len;
824
}
825
826
static ssize_t node_weight_show(struct config_item *item, char *buf)
827
{
828
return sprintf(buf, "%d\n", config_item_to_node(item)->weight);
829
}
830
831
static ssize_t node_weight_store(struct config_item *item, const char *buf,
832
size_t len)
833
{
834
int rc = kstrtoint(buf, 0, &config_item_to_node(item)->weight);
835
836
if (rc)
837
return rc;
838
return len;
839
}
840
841
static ssize_t node_release_recover_show(struct config_item *item, char *buf)
842
{
843
struct dlm_node *n = config_item_to_node(item);
844
845
return sprintf(buf, "%u\n", n->release_recover);
846
}
847
848
static ssize_t node_release_recover_store(struct config_item *item,
849
const char *buf, size_t len)
850
{
851
struct dlm_node *n = config_item_to_node(item);
852
int rc;
853
854
rc = kstrtouint(buf, 0, &n->release_recover);
855
if (rc)
856
return rc;
857
858
return len;
859
}
860
861
CONFIGFS_ATTR(node_, nodeid);
862
CONFIGFS_ATTR(node_, weight);
863
CONFIGFS_ATTR(node_, release_recover);
864
865
static struct configfs_attribute *node_attrs[] = {
866
[NODE_ATTR_NODEID] = &node_attr_nodeid,
867
[NODE_ATTR_WEIGHT] = &node_attr_weight,
868
[NODE_ATTR_RELEASE_RECOVER] = &node_attr_release_recover,
869
NULL,
870
};
871
872
/*
873
* Functions for the dlm to get the info that's been configured
874
*/
875
876
static struct dlm_space *get_space(char *name)
877
{
878
struct config_item *i;
879
880
if (!space_list)
881
return NULL;
882
883
mutex_lock(&space_list->cg_subsys->su_mutex);
884
i = config_group_find_item(space_list, name);
885
mutex_unlock(&space_list->cg_subsys->su_mutex);
886
887
return config_item_to_space(i);
888
}
889
890
static void put_space(struct dlm_space *sp)
891
{
892
config_item_put(&sp->group.cg_item);
893
}
894
895
static struct dlm_comm *get_comm(int nodeid)
896
{
897
struct config_item *i;
898
struct dlm_comm *cm = NULL;
899
int found = 0;
900
901
if (!comm_list)
902
return NULL;
903
904
WARN_ON_ONCE(!mutex_is_locked(&clusters_root.subsys.su_mutex));
905
906
list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
907
cm = config_item_to_comm(i);
908
909
if (cm->nodeid != nodeid)
910
continue;
911
found = 1;
912
config_item_get(i);
913
break;
914
}
915
916
if (!found)
917
cm = NULL;
918
return cm;
919
}
920
921
static void put_comm(struct dlm_comm *cm)
922
{
923
config_item_put(&cm->item);
924
}
925
926
/* caller must free mem */
927
int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
928
int *count_out)
929
{
930
struct dlm_member_gone *mb_gone, *mb_safe;
931
struct dlm_config_node *nodes, *node;
932
struct dlm_space *sp;
933
struct dlm_node *nd;
934
int rv, count;
935
936
sp = get_space(lsname);
937
if (!sp)
938
return -EEXIST;
939
940
mutex_lock(&sp->members_lock);
941
if (!sp->members_count) {
942
rv = -EINVAL;
943
printk(KERN_ERR "dlm: zero members_count\n");
944
goto out;
945
}
946
947
count = sp->members_count + sp->members_gone_count;
948
949
nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
950
if (!nodes) {
951
rv = -ENOMEM;
952
goto out;
953
}
954
955
node = nodes;
956
list_for_each_entry(nd, &sp->members, list) {
957
node->nodeid = nd->nodeid;
958
node->weight = nd->weight;
959
node->new = nd->new;
960
node->comm_seq = nd->comm_seq;
961
node++;
962
963
nd->new = 0;
964
}
965
966
/* we delay the remove on nodes until here as configfs does
967
* not support addtional attributes for rmdir().
968
*/
969
list_for_each_entry_safe(mb_gone, mb_safe, &sp->members_gone, list) {
970
node->nodeid = mb_gone->nodeid;
971
node->release_recover = mb_gone->release_recover;
972
node->gone = true;
973
node++;
974
975
list_del(&mb_gone->list);
976
sp->members_gone_count--;
977
kfree(mb_gone);
978
}
979
980
*count_out = count;
981
*nodes_out = nodes;
982
rv = 0;
983
out:
984
mutex_unlock(&sp->members_lock);
985
put_space(sp);
986
return rv;
987
}
988
989
int dlm_comm_seq(int nodeid, uint32_t *seq, bool locked)
990
{
991
struct dlm_comm *cm;
992
993
if (locked) {
994
cm = get_comm(nodeid);
995
} else {
996
mutex_lock(&clusters_root.subsys.su_mutex);
997
cm = get_comm(nodeid);
998
mutex_unlock(&clusters_root.subsys.su_mutex);
999
}
1000
if (!cm)
1001
return -ENOENT;
1002
1003
*seq = cm->seq;
1004
put_comm(cm);
1005
return 0;
1006
}
1007
1008
int dlm_our_nodeid(void)
1009
{
1010
return local_comm->nodeid;
1011
}
1012
1013
/* num 0 is first addr, num 1 is second addr */
1014
int dlm_our_addr(struct sockaddr_storage *addr, int num)
1015
{
1016
if (!local_comm)
1017
return -1;
1018
if (num + 1 > local_comm->addr_count)
1019
return -1;
1020
memcpy(addr, local_comm->addr[num], sizeof(*addr));
1021
return 0;
1022
}
1023
1024
/* Config file defaults */
1025
#define DEFAULT_TCP_PORT 21064
1026
#define DEFAULT_RSBTBL_SIZE 1024
1027
#define DEFAULT_RECOVER_TIMER 5
1028
#define DEFAULT_TOSS_SECS 10
1029
#define DEFAULT_SCAN_SECS 5
1030
#define DEFAULT_LOG_DEBUG 0
1031
#define DEFAULT_LOG_INFO 1
1032
#define DEFAULT_PROTOCOL DLM_PROTO_TCP
1033
#define DEFAULT_MARK 0
1034
#define DEFAULT_NEW_RSB_COUNT 128
1035
#define DEFAULT_RECOVER_CALLBACKS 0
1036
#define DEFAULT_CLUSTER_NAME ""
1037
1038
struct dlm_config_info dlm_config = {
1039
.ci_tcp_port = cpu_to_be16(DEFAULT_TCP_PORT),
1040
.ci_buffer_size = DLM_MAX_SOCKET_BUFSIZE,
1041
.ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE,
1042
.ci_recover_timer = DEFAULT_RECOVER_TIMER,
1043
.ci_toss_secs = DEFAULT_TOSS_SECS,
1044
.ci_scan_secs = DEFAULT_SCAN_SECS,
1045
.ci_log_debug = DEFAULT_LOG_DEBUG,
1046
.ci_log_info = DEFAULT_LOG_INFO,
1047
.ci_protocol = DEFAULT_PROTOCOL,
1048
.ci_mark = DEFAULT_MARK,
1049
.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT,
1050
.ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS,
1051
.ci_cluster_name = DEFAULT_CLUSTER_NAME
1052
};
1053
1054
1055