~wb-munzinger/+junk/ocfs2-tools

« back to all changes in this revision

Viewing changes to libo2cb/o2cb_abi.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2009-07-06 07:26:30 UTC
  • mfrom: (1.1.7 upstream) (0.1.5 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090706072630-59335sl51k3rvu74
Tags: 1.4.2-1
* New upstream release (Closes: #535471).
* Drop patch for limits.h, included upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *
6
6
 * Kernel<->User ABI for modifying cluster configuration.
7
7
 *
8
 
 * Copyright (C) 2004 Oracle.  All rights reserved.
 
8
 * Copyright (C) 2004,2007 Oracle.  All rights reserved.
9
9
 *
10
10
 * This program is free software; you can redistribute it and/or
11
11
 * modify it under the terms of the GNU General Public
12
 
 * License, version 2,  as published by the Free Software Foundation.
 
12
 * License, version 2, as published by the Free Software Foundation.
13
13
 * 
14
14
 * This program is distributed in the hope that it will be useful,
15
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
17
 * General Public License for more details.
18
 
 * 
19
 
 * You should have received a copy of the GNU General Public
20
 
 * License along with this program; if not, write to the
21
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22
 
 * Boston, MA 021110-1307, USA.
23
18
 */
24
19
 
25
20
#define _XOPEN_SOURCE 600  /* Triggers XOPEN2K in features.h */
42
37
 
43
38
#include <linux/types.h>
44
39
 
45
 
#include "o2cb.h"
 
40
#include "o2cb/o2cb.h"
 
41
#include "o2cb/o2cb_client_proto.h"
46
42
#include "o2cb_abi.h"
47
43
#include "o2cb_crc32.h"
48
 
#include "ocfs2_nodemanager.h"
 
44
 
 
45
#define CLUSTER_STACK_FILE      "/sys/fs/ocfs2/cluster_stack"
 
46
#define LOCKING_PROTOCOL_FILE   "/sys/fs/ocfs2/max_locking_protocol"
 
47
#define OCFS2_STACK_LABEL_LEN   4
 
48
#define CONTROL_DEVICE          "/dev/misc/ocfs2_control"
 
49
 
 
50
 
 
51
struct o2cb_stack_ops {
 
52
        errcode_t (*list_clusters)(char ***clusters);
 
53
        errcode_t (*begin_group_join)(struct o2cb_cluster_desc *cluster,
 
54
                                      struct o2cb_region_desc *region);
 
55
        errcode_t (*complete_group_join)(struct o2cb_cluster_desc *cluster,
 
56
                                         struct o2cb_region_desc *region,
 
57
                                         int result);
 
58
        errcode_t (*group_leave)(struct o2cb_cluster_desc *cluster,
 
59
                                 struct o2cb_region_desc *region);
 
60
};
 
61
 
 
62
struct o2cb_stack {
 
63
        char s_name[OCFS2_STACK_LABEL_LEN + 1];
 
64
        struct o2cb_stack_ops *s_ops;
 
65
};
 
66
 
 
67
static errcode_t classic_list_clusters(char ***clusters);
 
68
static errcode_t classic_begin_group_join(struct o2cb_cluster_desc *cluster,
 
69
                                          struct o2cb_region_desc *region);
 
70
static errcode_t classic_complete_group_join(struct o2cb_cluster_desc *cluster,
 
71
                                             struct o2cb_region_desc *region,
 
72
                                             int result);
 
73
static errcode_t classic_group_leave(struct o2cb_cluster_desc *cluster,
 
74
                                     struct o2cb_region_desc *region);
 
75
static struct o2cb_stack_ops classic_ops = {
 
76
        .list_clusters          = classic_list_clusters,
 
77
        .begin_group_join       = classic_begin_group_join,
 
78
        .complete_group_join    = classic_complete_group_join,
 
79
        .group_leave            = classic_group_leave,
 
80
};
 
81
static struct o2cb_stack classic_stack = {
 
82
        .s_name         = "o2cb",
 
83
        .s_ops          = &classic_ops,
 
84
};
 
85
 
 
86
static errcode_t user_list_clusters(char ***clusters);
 
87
static errcode_t user_begin_group_join(struct o2cb_cluster_desc *cluster,
 
88
                                       struct o2cb_region_desc *region);
 
89
static errcode_t user_complete_group_join(struct o2cb_cluster_desc *cluster,
 
90
                                          struct o2cb_region_desc *region,
 
91
                                          int result);
 
92
static errcode_t user_group_leave(struct o2cb_cluster_desc *cluster,
 
93
                                  struct o2cb_region_desc *region);
 
94
static struct o2cb_stack_ops user_ops = {
 
95
        .list_clusters          = user_list_clusters,
 
96
        .begin_group_join       = user_begin_group_join,
 
97
        .complete_group_join    = user_complete_group_join,
 
98
        .group_leave            = user_group_leave,
 
99
};
 
100
static struct o2cb_stack user_stack = {
 
101
        .s_ops          = &user_ops,
 
102
};
 
103
 
 
104
static struct o2cb_stack *current_stack;
 
105
static int control_daemon_fd = -1;
 
106
static int control_device_fd = -1;
49
107
 
50
108
static char *configfs_path;
51
109
 
 
110
 
 
111
static ssize_t read_single_line_file(const char *file, char *line,
 
112
                                     size_t count)
 
113
{
 
114
        ssize_t ret = 0;
 
115
        FILE *f;
 
116
 
 
117
        f = fopen(file, "r");
 
118
        if (f) {
 
119
                if (fgets(line, count, f))
 
120
                        ret = strlen(line);
 
121
                fclose(f);
 
122
        } else
 
123
                ret = -errno;
 
124
 
 
125
        return ret;
 
126
}
 
127
 
 
128
static ssize_t read_stack_file(char *line, size_t count)
 
129
{
 
130
        return read_single_line_file(CLUSTER_STACK_FILE, line, count);
 
131
}
 
132
 
 
133
static errcode_t determine_stack(void)
 
134
{
 
135
        ssize_t len;
 
136
        char line[100];
 
137
        errcode_t err = O2CB_ET_SERVICE_UNAVAILABLE;
 
138
 
 
139
        len = read_stack_file(line, sizeof(line));
 
140
        if (len > 0) {
 
141
                if (line[len - 1] == '\n') {
 
142
                        line[len - 1] = '\0';
 
143
                        len--;
 
144
                }
 
145
 
 
146
                if (len != OCFS2_STACK_LABEL_LEN)
 
147
                        err = O2CB_ET_INTERNAL_FAILURE;
 
148
                else if (!strcmp(line, classic_stack.s_name)) {
 
149
                        current_stack = &classic_stack;
 
150
                        err = 0;
 
151
                } else {
 
152
                        strncpy(user_stack.s_name, line,
 
153
                                OCFS2_STACK_LABEL_LEN);
 
154
                        current_stack = &user_stack;
 
155
                        err = 0;
 
156
                }
 
157
        } else if (len == -ENOENT) {
 
158
                current_stack = &classic_stack;
 
159
                err = 0;
 
160
        }
 
161
 
 
162
        return err;
 
163
}
 
164
 
 
165
errcode_t o2cb_get_stack_name(const char **name)
 
166
{
 
167
        if (!current_stack)
 
168
                return O2CB_ET_SERVICE_UNAVAILABLE;
 
169
 
 
170
        *name = current_stack->s_name;
 
171
        return 0;
 
172
}
 
173
 
 
174
static ssize_t read_locking_proto_file(char *line, size_t count)
 
175
{
 
176
        return read_single_line_file(LOCKING_PROTOCOL_FILE, line, count);
 
177
}
 
178
 
 
179
errcode_t o2cb_get_max_locking_protocol(struct ocfs2_protocol_version *proto)
 
180
{
 
181
        ssize_t len;
 
182
        char line[100];
 
183
        errcode_t err;
 
184
        unsigned int major, minor;
 
185
 
 
186
        len = read_locking_proto_file(line, sizeof(line));
 
187
        if (len <= 0) {
 
188
                switch (-len) {
 
189
                        case EACCES:
 
190
                        case EPERM:
 
191
                                err = O2CB_ET_PERMISSION_DENIED;
 
192
                                break;
 
193
 
 
194
                        case ENOMEM:
 
195
                                err = O2CB_ET_NO_MEMORY;
 
196
                                break;
 
197
 
 
198
                        case 0:
 
199
                        case ENOENT:
 
200
                        case ENOTDIR:
 
201
                                err = O2CB_ET_SERVICE_UNAVAILABLE;
 
202
                                break;
 
203
 
 
204
                        default:
 
205
                                err = O2CB_ET_INTERNAL_FAILURE;
 
206
                                break;
 
207
                }
 
208
                goto out;
 
209
        }
 
210
 
 
211
        if (line[len - 1] == '\n') {
 
212
                line[len - 1] = '\0';
 
213
                len--;
 
214
        }
 
215
 
 
216
        err = O2CB_ET_SERVICE_UNAVAILABLE;
 
217
        if (sscanf(line, "%u.%u", &major, &minor) != 2)
 
218
                goto out;
 
219
        /* Major and minor can't be more than a u8 */
 
220
        if ((major > (uint8_t)-1) || (minor > (uint8_t)-1))
 
221
                goto out;
 
222
 
 
223
        proto->pv_major = major;
 
224
        proto->pv_minor = minor;
 
225
        err = 0;
 
226
 
 
227
out:
 
228
        return err;
 
229
}
 
230
 
 
231
 
52
232
errcode_t o2cb_create_cluster(const char *cluster_name)
53
233
{
54
234
        char path[PATH_MAX];
484
664
        return O2CB_ET_SERVICE_UNAVAILABLE;
485
665
}
486
666
 
487
 
#define O2CB_INTERFACE_REVISION_PATH_OLD        "/proc/fs/ocfs2_nodemanager/interface_revision"
488
 
#define O2CB_INTERFACE_REVISION_PATH            "/sys/o2cb/interface_revision"
 
667
#define O2CB_INTERFACE_REVISION_PATH_OLD_PROC   "/proc/fs/ocfs2_nodemanager/interface_revision"
 
668
#define O2CB_INTERFACE_REVISION_PATH_OLD_SYS    "/sys/o2cb/interface_revision"
 
669
#define O2CB_INTERFACE_REVISION_PATH            "/sys/fs/o2cb/interface_revision"
489
670
errcode_t o2cb_init(void)
490
671
{
491
672
        int ret, fd;
493
674
        errcode_t err;
494
675
        char revision_string[16];
495
676
 
 
677
        err = determine_stack();
 
678
        if (err)
 
679
                return err;
 
680
 
496
681
        err = try_file(O2CB_INTERFACE_REVISION_PATH, &fd);
497
682
        if (err == O2CB_ET_SERVICE_UNAVAILABLE)
498
 
                err = try_file(O2CB_INTERFACE_REVISION_PATH_OLD, &fd);
 
683
                err = try_file(O2CB_INTERFACE_REVISION_PATH_OLD_SYS, &fd);
 
684
        if (err == O2CB_ET_SERVICE_UNAVAILABLE)
 
685
                err = try_file(O2CB_INTERFACE_REVISION_PATH_OLD_PROC, &fd);
499
686
        if (err)
500
687
                return err;
501
688
 
996
1183
 * to drop the reference taken during startup, otherwise that
997
1184
 * reference was dropped automatically at process shutdown so there's
998
1185
 * no need to drop one here. */
999
 
static errcode_t __o2cb_stop_heartbeat_region(const char *cluster_name,
1000
 
                                              const char *region_name,
1001
 
                                              int undo)
 
1186
static errcode_t classic_group_leave(struct o2cb_cluster_desc *cluster,
 
1187
                                     struct o2cb_region_desc *region)
1002
1188
{
1003
1189
        errcode_t ret, up_ret;
1004
1190
        int hb_refs;
1005
1191
        int semid;
1006
1192
 
1007
 
        ret = o2cb_mutex_down_lookup(region_name, &semid);
 
1193
        ret = o2cb_mutex_down_lookup(region->r_name, &semid);
1008
1194
        if (ret)
1009
1195
                return ret;
1010
1196
 
1016
1202
         * references on the region. We avoid a negative error count
1017
1203
         * here and clean up the region as normal. */
1018
1204
        if (hb_refs) {
1019
 
                ret = __o2cb_drop_ref(semid, undo);
 
1205
                ret = __o2cb_drop_ref(semid, !region->r_persist);
1020
1206
                if (ret)
1021
1207
                        goto up;
1022
1208
 
1028
1214
        if (!hb_refs) {
1029
1215
                /* XXX: If this fails, shouldn't we still destroy the
1030
1216
                 * semaphore set? */
1031
 
                ret = o2cb_remove_heartbeat_region(cluster_name, region_name);
 
1217
                ret = o2cb_remove_heartbeat_region(cluster->c_cluster,
 
1218
                                                   region->r_name);
1032
1219
                if (ret)
1033
1220
                        goto up;
1034
1221
 
1047
1234
        return ret;
1048
1235
}
1049
1236
 
1050
 
static errcode_t __o2cb_start_heartbeat_region(const char *cluster_name,
1051
 
                                               struct o2cb_region_desc *desc,
1052
 
                                               int undo)
 
1237
static errcode_t classic_begin_group_join(struct o2cb_cluster_desc *cluster,
 
1238
                                          struct o2cb_region_desc *region)
1053
1239
{
1054
1240
        errcode_t ret, up_ret;
1055
1241
        int semid;
1056
1242
 
1057
 
        ret = o2cb_mutex_down_lookup(desc->r_name, &semid);
 
1243
        ret = o2cb_mutex_down_lookup(region->r_name, &semid);
1058
1244
        if (ret)
1059
1245
                return ret;
1060
1246
 
1061
 
        ret = o2cb_create_heartbeat_region(cluster_name,
1062
 
                                           desc->r_name,
1063
 
                                           desc->r_device_name,
1064
 
                                           desc->r_block_bytes,
1065
 
                                           desc->r_start_block,
1066
 
                                           desc->r_blocks);
 
1247
        ret = o2cb_create_heartbeat_region(cluster->c_cluster,
 
1248
                                           region->r_name,
 
1249
                                           region->r_device_name,
 
1250
                                           region->r_block_bytes,
 
1251
                                           region->r_start_block,
 
1252
                                           region->r_blocks);
1067
1253
        if (ret && ret != O2CB_ET_REGION_EXISTS)
1068
1254
                goto up;
1069
1255
 
1070
 
        ret = __o2cb_get_ref(semid, undo);
 
1256
        ret = __o2cb_get_ref(semid, !region->r_persist);
1071
1257
        /* XXX: Maybe stop heartbeat on error here? */
1072
1258
up:
1073
1259
        up_ret = o2cb_mutex_up(semid);
1077
1263
        return ret;
1078
1264
}
1079
1265
 
1080
 
errcode_t o2cb_start_heartbeat_region(const char *cluster_name,
1081
 
                                      struct o2cb_region_desc *desc)
1082
 
{
1083
 
        return __o2cb_start_heartbeat_region(cluster_name, desc, 1);
1084
 
}
1085
 
 
1086
 
errcode_t o2cb_stop_heartbeat_region(const char *cluster_name,
1087
 
                                     const char *region_name)
1088
 
{
1089
 
        return __o2cb_stop_heartbeat_region(cluster_name, region_name, 1);
1090
 
}
1091
 
 
1092
 
errcode_t o2cb_start_heartbeat_region_perm(const char *cluster_name,
1093
 
                                           struct o2cb_region_desc *desc)
1094
 
{
1095
 
        return __o2cb_start_heartbeat_region(cluster_name, desc, 0);
1096
 
}
1097
 
 
1098
 
errcode_t o2cb_stop_heartbeat_region_perm(const char *cluster_name,
1099
 
                                          const char *region_name)
1100
 
{
1101
 
        return __o2cb_stop_heartbeat_region(cluster_name, region_name, 0);
 
1266
static errcode_t classic_complete_group_join(struct o2cb_cluster_desc *cluster,
 
1267
                                             struct o2cb_region_desc *region,
 
1268
                                             int result)
 
1269
{
 
1270
        errcode_t ret = 0;
 
1271
 
 
1272
        if (result)
 
1273
                ret = classic_group_leave(cluster, region);
 
1274
 
 
1275
        return ret;
 
1276
}
 
1277
 
 
1278
static errcode_t user_parse_status(char **args, int *error, char **error_msg)
 
1279
{
 
1280
        errcode_t err = O2CB_ET_IO;
 
1281
        long result;
 
1282
        char *ptr = NULL;
 
1283
 
 
1284
        result = strtol(args[0], &ptr, 10);
 
1285
        if (ptr && *ptr != '\0') {
 
1286
                /* fprintf(stderr, "Invalid error code string: %s", args[0]); */
 
1287
        } else if ((result == LONG_MIN) || (result == LONG_MAX) ||
 
1288
                   (result < INT_MIN) || (result > INT_MAX)) {
 
1289
                /* fprintf(stderr, "Error code %ld out of range", err); */
 
1290
        } else {
 
1291
                *error_msg = args[1];
 
1292
                *error = result;
 
1293
                err = 0;
 
1294
        }
 
1295
 
 
1296
        return err;
 
1297
}
 
1298
 
 
1299
static errcode_t user_begin_group_join(struct o2cb_cluster_desc *cluster,
 
1300
                                       struct o2cb_region_desc *region)
 
1301
{
 
1302
        errcode_t err;
 
1303
        int rc;
 
1304
        int error;
 
1305
        char *error_msg;
 
1306
        client_message message;
 
1307
        char *argv[OCFS2_CONTROLD_MAXARGS + 1];
 
1308
        char buf[OCFS2_CONTROLD_MAXLINE];
 
1309
 
 
1310
        if (control_daemon_fd != -1) {
 
1311
                /* fprintf(stderr, "Join already in progress!\n"); */
 
1312
                err = O2CB_ET_INTERNAL_FAILURE;
 
1313
                goto out;
 
1314
        }
 
1315
 
 
1316
        rc = ocfs2_client_connect();
 
1317
        if (rc < 0) {
 
1318
                /* fprintf(stderr, "Unable to connect to ocfs2_controld: %s\n",
 
1319
                        strerror(-rc)); */
 
1320
                switch (rc) {
 
1321
                        case -EACCES:
 
1322
                        case -EPERM:
 
1323
                                err = O2CB_ET_PERMISSION_DENIED;
 
1324
                                break;
 
1325
 
 
1326
                        default:
 
1327
                                err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1328
                                break;
 
1329
                }
 
1330
                goto out;
 
1331
        }
 
1332
        control_daemon_fd = rc;
 
1333
 
 
1334
        rc = send_message(control_daemon_fd, CM_MOUNT, OCFS2_FS_NAME,
 
1335
                          region->r_name, cluster->c_cluster,
 
1336
                          region->r_device_name, region->r_service);
 
1337
        if (rc) {
 
1338
                /* fprintf(stderr, "Unable to send MOUNT message: %s\n",
 
1339
                        strerror(-rc)); */
 
1340
                err = O2CB_ET_IO;
 
1341
                goto out;
 
1342
        }
 
1343
 
 
1344
        rc = receive_message(control_daemon_fd, buf, &message, argv);
 
1345
        if (rc < 0) {
 
1346
                /* fprintf(stderr, "Error reading from daemon: %s\n",
 
1347
                        strerror(-rc)); */
 
1348
                err = O2CB_ET_IO;
 
1349
                goto out;
 
1350
        }
 
1351
 
 
1352
        switch (message) {
 
1353
                case CM_STATUS:
 
1354
                        err = user_parse_status(argv, &error, &error_msg);
 
1355
                        if (err) {
 
1356
                                /* fprintf(stderr, "Bad status message: %s\n",
 
1357
                                        strerror(-rc)); */
 
1358
                                goto out;
 
1359
                        }
 
1360
                        if (error && (error != EALREADY)) {
 
1361
                                /* fprintf(stderr,
 
1362
                                        "Error %d from daemon: %s\n",
 
1363
                                        error, error_msg); */
 
1364
                                err = O2CB_ET_CONFIGURATION_ERROR;
 
1365
                                goto out;
 
1366
                        }
 
1367
                        break;
 
1368
 
 
1369
                default:
 
1370
                        /* fprintf(stderr,
 
1371
                                "Unexpected message %s from daemon\n",
 
1372
                                message_to_string(message)); */
 
1373
                        err = O2CB_ET_INTERNAL_FAILURE;
 
1374
                        goto out;
 
1375
                        break;
 
1376
        }
 
1377
 
 
1378
        err = 0;
 
1379
 
 
1380
out:
 
1381
        if (err && (control_daemon_fd != -1)) {
 
1382
                close(control_daemon_fd);
 
1383
                control_daemon_fd = -1;
 
1384
        }
 
1385
 
 
1386
        return err;
 
1387
}
 
1388
 
 
1389
static errcode_t user_complete_group_join(struct o2cb_cluster_desc *cluster,
 
1390
                                          struct o2cb_region_desc *region,
 
1391
                                          int result)
 
1392
{
 
1393
        errcode_t err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1394
        int rc;
 
1395
        int error;
 
1396
        char *error_msg;
 
1397
        client_message message;
 
1398
        char *argv[OCFS2_CONTROLD_MAXARGS + 1];
 
1399
        char buf[OCFS2_CONTROLD_MAXLINE];
 
1400
 
 
1401
        if (control_daemon_fd == -1) {
 
1402
                /* fprintf(stderr, "Join not started!\n"); */
 
1403
                err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1404
                goto out;
 
1405
        }
 
1406
 
 
1407
        rc = send_message(control_daemon_fd, CM_MRESULT, OCFS2_FS_NAME,
 
1408
                          region->r_name, result, region->r_service);
 
1409
        if (rc) {
 
1410
                /* fprintf(stderr, "Unable to send MRESULT message: %s\n",
 
1411
                        strerror(-rc)); */
 
1412
                err = O2CB_ET_IO;
 
1413
                goto out;
 
1414
        }
 
1415
 
 
1416
        rc = receive_message(control_daemon_fd, buf, &message, argv);
 
1417
        if (rc < 0) {
 
1418
                /* fprintf(stderr, "Error reading from daemon: %s\n",
 
1419
                        strerror(-rc)); */
 
1420
                err = O2CB_ET_IO;
 
1421
                goto out;
 
1422
        }
 
1423
 
 
1424
        switch (message) {
 
1425
                case CM_STATUS:
 
1426
                        err = user_parse_status(argv, &error, &error_msg);
 
1427
                        if (err) {
 
1428
                                /* fprintf(stderr, "Bad status message: %s\n",
 
1429
                                        strerror(-rc)); */
 
1430
                                goto out;
 
1431
                        }
 
1432
                        if (error) {
 
1433
                                /* fprintf(stderr,
 
1434
                                        "Error %d from daemon: %s\n",
 
1435
                                        error, error_msg); */
 
1436
                                err = O2CB_ET_CONFIGURATION_ERROR;
 
1437
                        }
 
1438
                        break;
 
1439
 
 
1440
                default:
 
1441
                        /* fprintf(stderr,
 
1442
                                "Unexpected message %s from daemon\n",
 
1443
                                message_to_string(message)); */
 
1444
                        err = O2CB_ET_INTERNAL_FAILURE;
 
1445
                        goto out;
 
1446
                        break;
 
1447
        }
 
1448
 
 
1449
        err = 0;
 
1450
 
 
1451
out:
 
1452
        if (control_daemon_fd != -1) {
 
1453
                close(control_daemon_fd);
 
1454
                control_daemon_fd = -1;
 
1455
        }
 
1456
 
 
1457
        return err;
 
1458
}
 
1459
 
 
1460
static errcode_t user_group_leave(struct o2cb_cluster_desc *cluster,
 
1461
                                  struct o2cb_region_desc *region)
 
1462
{
 
1463
        errcode_t err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1464
        int rc;
 
1465
        int error;
 
1466
        char *error_msg;
 
1467
        client_message message;
 
1468
        char *argv[OCFS2_CONTROLD_MAXARGS + 1];
 
1469
        char buf[OCFS2_CONTROLD_MAXLINE];
 
1470
 
 
1471
        if (control_daemon_fd != -1) {
 
1472
                /* fprintf(stderr, "Join in progress!\n"); */
 
1473
                err = O2CB_ET_INTERNAL_FAILURE;
 
1474
                goto out;
 
1475
        }
 
1476
 
 
1477
        rc = ocfs2_client_connect();
 
1478
        if (rc < 0) {
 
1479
                /* fprintf(stderr, "Unable to connect to ocfs2_controld: %s\n",
 
1480
                        strerror(-rc)); */
 
1481
                switch (rc) {
 
1482
                        case -EACCES:
 
1483
                        case -EPERM:
 
1484
                                err = O2CB_ET_PERMISSION_DENIED;
 
1485
                                break;
 
1486
 
 
1487
                        default:
 
1488
                                err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1489
                                break;
 
1490
                }
 
1491
                goto out;
 
1492
        }
 
1493
        control_daemon_fd = rc;
 
1494
 
 
1495
        rc = send_message(control_daemon_fd, CM_UNMOUNT, OCFS2_FS_NAME,
 
1496
                          region->r_name, region->r_service);
 
1497
        if (rc) {
 
1498
                /* fprintf(stderr, "Unable to send UNMOUNT message: %s\n",
 
1499
                        strerror(-rc)); */
 
1500
                err = O2CB_ET_IO;
 
1501
                goto out;
 
1502
        }
 
1503
 
 
1504
        rc = receive_message(control_daemon_fd, buf, &message, argv);
 
1505
        if (rc < 0) {
 
1506
                /* fprintf(stderr, "Error reading from daemon: %s\n",
 
1507
                        strerror(-rc)); */
 
1508
                err = O2CB_ET_IO;
 
1509
                goto out;
 
1510
        }
 
1511
 
 
1512
        switch (message) {
 
1513
                case CM_STATUS:
 
1514
                        err = user_parse_status(argv, &error, &error_msg);
 
1515
                        if (err) {
 
1516
                                /* fprintf(stderr, "Bad status message: %s\n",
 
1517
                                        strerror(-rc)); */
 
1518
                                goto out;
 
1519
                        }
 
1520
                        if (error) {
 
1521
                                /* fprintf(stderr,
 
1522
                                        "Error %d from daemon: %s\n",
 
1523
                                        error, error_msg); */
 
1524
                                err = O2CB_ET_CONFIGURATION_ERROR;
 
1525
                                goto out;
 
1526
                        }
 
1527
                        break;
 
1528
 
 
1529
                default:
 
1530
                        /* fprintf(stderr,
 
1531
                                "Unexpected message %s from daemon\n",
 
1532
                                message_to_string(message)); */
 
1533
                        err = O2CB_ET_INTERNAL_FAILURE;
 
1534
                        goto out;
 
1535
                        break;
 
1536
        }
 
1537
 
 
1538
        err = 0;
 
1539
 
 
1540
out:
 
1541
        if (control_daemon_fd != -1) {
 
1542
                close(control_daemon_fd);
 
1543
                control_daemon_fd = -1;
 
1544
        }
 
1545
 
 
1546
        return err;
 
1547
}
 
1548
 
 
1549
static errcode_t o2cb_validate_cluster_desc(struct o2cb_cluster_desc *desc)
 
1550
{
 
1551
        errcode_t err;
 
1552
        const char *name;
 
1553
 
 
1554
        if (!desc)
 
1555
                return O2CB_ET_INVALID_STACK_NAME;
 
1556
 
 
1557
        if (desc->c_stack && !desc->c_cluster)
 
1558
                return O2CB_ET_INVALID_STACK_NAME;
 
1559
 
 
1560
        err = o2cb_get_stack_name(&name);
 
1561
        if (err)
 
1562
                return err;
 
1563
 
 
1564
        if (desc->c_stack) {
 
1565
                if (strcmp(desc->c_stack, name))
 
1566
                        return O2CB_ET_INVALID_STACK_NAME;
 
1567
        } else if (strcmp(name, classic_stack.s_name))
 
1568
                return O2CB_ET_INVALID_STACK_NAME;
 
1569
 
 
1570
        return 0;
 
1571
}
 
1572
 
 
1573
errcode_t o2cb_begin_group_join(struct o2cb_cluster_desc *cluster,
 
1574
                                struct o2cb_region_desc *region)
 
1575
{
 
1576
        errcode_t err;
 
1577
        struct o2cb_cluster_desc desc;
 
1578
        char _fake_cluster_name[NAME_MAX];
 
1579
 
 
1580
        if (!current_stack)
 
1581
                return O2CB_ET_SERVICE_UNAVAILABLE;
 
1582
 
 
1583
        err = o2cb_validate_cluster_desc(cluster);
 
1584
        if (err)
 
1585
                return err;
 
1586
 
 
1587
        desc = *cluster;
 
1588
        if (!desc.c_cluster) {
 
1589
                err = _fake_default_cluster(_fake_cluster_name);
 
1590
                if (err)
 
1591
                        return err;
 
1592
                desc.c_cluster = _fake_cluster_name;
 
1593
        }
 
1594
 
 
1595
        return current_stack->s_ops->begin_group_join(&desc, region);
 
1596
}
 
1597
 
 
1598
errcode_t o2cb_complete_group_join(struct o2cb_cluster_desc *cluster,
 
1599
                                   struct o2cb_region_desc *region,
 
1600
                                   int result)
 
1601
{
 
1602
        errcode_t err;
 
1603
        struct o2cb_cluster_desc desc;
 
1604
        char _fake_cluster_name[NAME_MAX];
 
1605
 
 
1606
        if (!current_stack)
 
1607
                return O2CB_ET_SERVICE_UNAVAILABLE;
 
1608
 
 
1609
        err = o2cb_validate_cluster_desc(cluster);
 
1610
        if (err)
 
1611
                return err;
 
1612
 
 
1613
        desc = *cluster;
 
1614
        if (!desc.c_cluster) {
 
1615
                err = _fake_default_cluster(_fake_cluster_name);
 
1616
                if (err)
 
1617
                        return err;
 
1618
                desc.c_cluster = _fake_cluster_name;
 
1619
        }
 
1620
 
 
1621
        return current_stack->s_ops->complete_group_join(&desc, region,
 
1622
                                                         result);
 
1623
}
 
1624
 
 
1625
errcode_t o2cb_group_leave(struct o2cb_cluster_desc *cluster,
 
1626
                           struct o2cb_region_desc *region)
 
1627
{
 
1628
        errcode_t err;
 
1629
        struct o2cb_cluster_desc desc;
 
1630
        char _fake_cluster_name[NAME_MAX];
 
1631
 
 
1632
        if (!current_stack)
 
1633
                return O2CB_ET_SERVICE_UNAVAILABLE;
 
1634
 
 
1635
        err = o2cb_validate_cluster_desc(cluster);
 
1636
        if (err)
 
1637
                return err;
 
1638
 
 
1639
        desc = *cluster;
 
1640
        if (!desc.c_cluster) {
 
1641
                err = _fake_default_cluster(_fake_cluster_name);
 
1642
                if (err)
 
1643
                        return err;
 
1644
                desc.c_cluster = _fake_cluster_name;
 
1645
        }
 
1646
 
 
1647
        return current_stack->s_ops->group_leave(&desc, region);
 
1648
}
 
1649
 
 
1650
void o2cb_free_cluster_desc(struct o2cb_cluster_desc *cluster)
 
1651
{
 
1652
        if (cluster->c_stack)
 
1653
                free(cluster->c_stack);
 
1654
        if (cluster->c_cluster)
 
1655
                free(cluster->c_cluster);
 
1656
}
 
1657
 
 
1658
errcode_t o2cb_running_cluster_desc(struct o2cb_cluster_desc *cluster)
 
1659
{
 
1660
        errcode_t err;
 
1661
        const char *stack;
 
1662
        char **clusters = NULL;
 
1663
 
 
1664
        err = o2cb_get_stack_name(&stack);
 
1665
        if (err)
 
1666
                return err;
 
1667
 
 
1668
        if (!strcmp(stack, classic_stack.s_name)) {
 
1669
                cluster->c_stack = NULL;
 
1670
                cluster->c_cluster = NULL;
 
1671
                return 0;
 
1672
        }
 
1673
 
 
1674
        cluster->c_stack = strdup(stack);
 
1675
        if (!cluster->c_stack)
 
1676
                return O2CB_ET_NO_MEMORY;
 
1677
 
 
1678
        err = o2cb_list_clusters(&clusters);
 
1679
        if (err) {
 
1680
                free(cluster->c_stack);
 
1681
                return err;
 
1682
        }
 
1683
 
 
1684
        /* The first cluster is the default cluster */
 
1685
        if (clusters[0]) {
 
1686
                cluster->c_cluster = strdup(clusters[0]);
 
1687
                if (!cluster->c_cluster) {
 
1688
                        free(cluster->c_stack);
 
1689
                        err = O2CB_ET_NO_MEMORY;
 
1690
                }
 
1691
        }
 
1692
        o2cb_free_cluster_list(clusters);
 
1693
 
 
1694
        return 0;
1102
1695
}
1103
1696
 
1104
1697
static inline int is_dots(const char *name)
1122
1715
{
1123
1716
        errcode_t ret;
1124
1717
        int count;
 
1718
        char statpath[PATH_MAX];
 
1719
        struct stat stat_buf;
1125
1720
        DIR *dir;
1126
1721
        struct dirent *dirent;
1127
1722
        struct dlist {
1160
1755
                if (is_dots(dirent->d_name))
1161
1756
                        continue;
1162
1757
 
 
1758
                snprintf(statpath, sizeof(statpath), "%s/%s", path,
 
1759
                         dirent->d_name);
 
1760
 
 
1761
                /* Silently ignore, we can't access it anyway */
 
1762
                if (lstat(statpath, &stat_buf))
 
1763
                        continue;
 
1764
 
 
1765
                /* Non-directories are attributes */
 
1766
                if (!S_ISDIR(stat_buf.st_mode))
 
1767
                        continue;
 
1768
 
1163
1769
                tmp = malloc(sizeof(struct dlist));
1164
1770
                if (!tmp)
1165
1771
                        goto out_free_list;
1179
1785
        if (!*objs)
1180
1786
                goto out_free_list;
1181
1787
 
1182
 
        tmp = list;
1183
 
        count = 0;
1184
1788
        for (tmp = list, count = 0; tmp; tmp = tmp->next, count++) {
1185
1789
                (*objs)[count] = tmp->name;
1186
1790
                tmp->name = NULL;
1215
1819
        free(objs);
1216
1820
}
1217
1821
 
1218
 
errcode_t o2cb_list_clusters(char ***clusters)
 
1822
static errcode_t classic_list_clusters(char ***clusters)
1219
1823
{
1220
1824
        char path[PATH_MAX];
1221
1825
        errcode_t ret;
1231
1835
        return o2cb_list_dir(path, clusters);
1232
1836
}
1233
1837
 
 
1838
static errcode_t user_list_clusters(char ***clusters)
 
1839
{
 
1840
        errcode_t err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1841
        int rc, fd = -1;
 
1842
        char buf[OCFS2_CONTROLD_MAXLINE];
 
1843
 
 
1844
        rc = ocfs2_client_connect();
 
1845
        if (rc < 0) {
 
1846
                /* fprintf(stderr, "Unable to connect to ocfs2_controld: %s\n",
 
1847
                        strerror(-rc)); */
 
1848
                switch (rc) {
 
1849
                        case -EACCES:
 
1850
                        case -EPERM:
 
1851
                                err = O2CB_ET_PERMISSION_DENIED;
 
1852
                                break;
 
1853
 
 
1854
                        default:
 
1855
                                err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1856
                                break;
 
1857
                }
 
1858
                goto out;
 
1859
        }
 
1860
        fd = rc;
 
1861
 
 
1862
        rc = send_message(fd, CM_LISTCLUSTERS);
 
1863
        if (rc) {
 
1864
                /* fprintf(stderr,
 
1865
                        "Unable to send LISTCLUSTERS message: %s\n",
 
1866
                        strerror(-rc)); */
 
1867
                err = O2CB_ET_IO;
 
1868
                goto out;
 
1869
        }
 
1870
 
 
1871
        rc = receive_list(fd, buf, clusters);
 
1872
        if (rc) {
 
1873
                /* fprintf(stderr, "Error reading from daemon: %s\n",
 
1874
                        strerror(-rc)); */
 
1875
                err = O2CB_ET_IO;
 
1876
                goto out;
 
1877
        }
 
1878
 
 
1879
        err = 0;
 
1880
 
 
1881
out:
 
1882
        if (fd != -1)
 
1883
                close(fd);
 
1884
 
 
1885
        return err;
 
1886
}
 
1887
 
 
1888
errcode_t o2cb_list_clusters(char ***clusters)
 
1889
{
 
1890
        if (!current_stack)
 
1891
                return O2CB_ET_SERVICE_UNAVAILABLE;
 
1892
 
 
1893
        return current_stack->s_ops->list_clusters(clusters);
 
1894
}
 
1895
 
1234
1896
void o2cb_free_cluster_list(char **clusters)
1235
1897
{
1236
1898
        o2cb_free_dir_list(clusters);
1257
1919
        o2cb_free_dir_list(nodes);
1258
1920
}
1259
1921
 
 
1922
static errcode_t dump_list_to_string(char **dump_list, char **debug)
 
1923
{
 
1924
        int i;
 
1925
        size_t len, count = 0;
 
1926
        char *ptr;
 
1927
 
 
1928
        for (i = 0; dump_list[i]; i++)
 
1929
                count += strlen(dump_list[i]);
 
1930
 
 
1931
        *debug = malloc(sizeof(char) * (count + 1));
 
1932
        if (!*debug)
 
1933
                return O2CB_ET_NO_MEMORY;
 
1934
 
 
1935
        ptr = *debug;
 
1936
        ptr[count] = '\0';
 
1937
        for (i = 0; dump_list[i]; i++) {
 
1938
                len = strlen(dump_list[i]);
 
1939
                memcpy(ptr, dump_list[i], len);
 
1940
                ptr += len;
 
1941
        }
 
1942
 
 
1943
        return 0;
 
1944
}
 
1945
 
 
1946
errcode_t o2cb_control_daemon_debug(char **debug)
 
1947
{
 
1948
        errcode_t err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1949
        int rc, fd = -1;
 
1950
        char buf[OCFS2_CONTROLD_MAXLINE];
 
1951
        char **dump_list = NULL;
 
1952
 
 
1953
        rc = ocfs2_client_connect();
 
1954
        if (rc < 0) {
 
1955
                /* fprintf(stderr, "Unable to connect to ocfs2_controld: %s\n",
 
1956
                        strerror(-rc)); */
 
1957
                switch (rc) {
 
1958
                        case -EACCES:
 
1959
                        case -EPERM:
 
1960
                                err = O2CB_ET_PERMISSION_DENIED;
 
1961
                                break;
 
1962
 
 
1963
                        default:
 
1964
                                err = O2CB_ET_SERVICE_UNAVAILABLE;
 
1965
                                break;
 
1966
                }
 
1967
                goto out;
 
1968
        }
 
1969
        fd = rc;
 
1970
 
 
1971
        rc = send_message(fd, CM_DUMP);
 
1972
        if (rc) {
 
1973
                /* fprintf(stderr,
 
1974
                        "Unable to send DUMP message: %s\n",
 
1975
                        strerror(-rc)); */
 
1976
                err = O2CB_ET_IO;
 
1977
                goto out;
 
1978
        }
 
1979
 
 
1980
        rc = receive_list(fd, buf, &dump_list);
 
1981
        if (rc) {
 
1982
                /* fprintf(stderr, "Error reading from daemon: %s\n",
 
1983
                        strerror(-rc)); */
 
1984
                err = O2CB_ET_IO;
 
1985
                goto out;
 
1986
        }
 
1987
 
 
1988
        err = dump_list_to_string(dump_list, debug);
 
1989
        o2cb_free_dir_list(dump_list);
 
1990
 
 
1991
out:
 
1992
        if (fd != -1)
 
1993
                close(fd);
 
1994
 
 
1995
        return err;
 
1996
}
 
1997
 
 
1998
 
1260
1999
errcode_t o2cb_get_hb_thread_pid (const char *cluster_name, const char *region_name,
1261
2000
                           pid_t *pid)
1262
2001
{
1306
2045
        return 0;
1307
2046
}
1308
2047
 
 
2048
/*
 
2049
 * The handshake is pretty simple.  We need to read all supported control
 
2050
 * device protocols from the kernel.  Once we've read them, we can write
 
2051
 * the protocol we want to use.  After that, we're good to go.
 
2052
 *
 
2053
 * Right now, we will just allow the T01 protocol and not write any
 
2054
 * code to handle multiples.  We'll add that later if and when it is
 
2055
 * necessary.
 
2056
 *
 
2057
 * The versions read from the kernel are all 4 characers including the
 
2058
 * newline.
 
2059
 */
 
2060
#define OCFS2_CONTROL_PROTO                     "T01\n"
 
2061
#define OCFS2_CONTROL_PROTO_LEN                 4
 
2062
#define OCFS2_CONTROL_MESSAGE_SETNODE_OP        "SETN"
 
2063
#define OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN 14
 
2064
#define OCFS2_CONTROL_MESSAGE_SETVERSION_OP     "SETV"
 
2065
#define OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN      11
 
2066
#define OCFS2_CONTROL_MESSAGE_DOWN_OP           "DOWN"
 
2067
#define OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN    47
 
2068
#define OCFS2_CONTROL_MESSAGE_NODENUM_LEN       8
 
2069
static errcode_t o2cb_control_handshake(unsigned int this_node,
 
2070
                                        struct ocfs2_protocol_version *proto)
 
2071
{
 
2072
        errcode_t err = 0;
 
2073
        int found = 0;
 
2074
        size_t ret;
 
2075
        char buf[OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN + 1];
 
2076
 
 
2077
        if (control_device_fd == -1) {
 
2078
                err = O2CB_ET_INTERNAL_FAILURE;
 
2079
                goto out;
 
2080
        }
 
2081
 
 
2082
        buf[OCFS2_CONTROL_PROTO_LEN] = '\0';
 
2083
        while (1)
 
2084
        {
 
2085
                ret = read(control_device_fd, buf, OCFS2_CONTROL_PROTO_LEN);
 
2086
                if (ret == OCFS2_CONTROL_PROTO_LEN) {
 
2087
                        if (!found && !strcmp(buf,
 
2088
                                              OCFS2_CONTROL_PROTO))
 
2089
                                found = 1;
 
2090
                        continue;
 
2091
                }
 
2092
 
 
2093
                if (ret != 0)
 
2094
                        err = O2CB_ET_IO;
 
2095
                else if (!found)
 
2096
                        err = O2CB_ET_SERVICE_UNAVAILABLE;  /* no match */
 
2097
                break;
 
2098
        }
 
2099
 
 
2100
        if (err)
 
2101
                goto out;
 
2102
 
 
2103
        ret = write(control_device_fd, OCFS2_CONTROL_PROTO,
 
2104
                    OCFS2_CONTROL_PROTO_LEN);
 
2105
        if (ret != OCFS2_CONTROL_PROTO_LEN) {
 
2106
                err = O2CB_ET_IO;
 
2107
                goto out;
 
2108
        }
 
2109
 
 
2110
        snprintf(buf, OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN + 1,
 
2111
                 OCFS2_CONTROL_MESSAGE_SETNODE_OP " %08X\n", this_node);
 
2112
        ret = write(control_device_fd, buf,
 
2113
                    OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN);
 
2114
        if (ret != OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN)
 
2115
                err = O2CB_ET_IO;
 
2116
 
 
2117
        snprintf(buf, OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN + 1,
 
2118
                 OCFS2_CONTROL_MESSAGE_SETVERSION_OP " %02X %02X\n",
 
2119
                 proto->pv_major, proto->pv_minor);
 
2120
        ret = write(control_device_fd, buf,
 
2121
                    OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN);
 
2122
        if (ret != OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN)
 
2123
                err = O2CB_ET_IO;
 
2124
 
 
2125
out:
 
2126
        return err;
 
2127
}
 
2128
 
 
2129
errcode_t o2cb_control_open(unsigned int this_node,
 
2130
                            struct ocfs2_protocol_version *proto)
 
2131
{
 
2132
        errcode_t err = 0;
 
2133
        int rc;
 
2134
 
 
2135
        if (!current_stack) {
 
2136
                err = O2CB_ET_SERVICE_UNAVAILABLE;
 
2137
                goto out;
 
2138
        }
 
2139
 
 
2140
        if (control_device_fd != -1)
 
2141
                goto out;
 
2142
 
 
2143
        rc = open(CONTROL_DEVICE, O_RDWR);
 
2144
        if (rc < 0) {
 
2145
                switch (errno) {
 
2146
                        default:
 
2147
                                err = O2CB_ET_INTERNAL_FAILURE;
 
2148
                                break;
 
2149
 
 
2150
                        case ENOTDIR:
 
2151
                        case ENOENT:
 
2152
                        case EISDIR:
 
2153
                                err = O2CB_ET_SERVICE_UNAVAILABLE;
 
2154
                                break;
 
2155
 
 
2156
                        case EACCES:
 
2157
                        case EPERM:
 
2158
                        case EROFS:
 
2159
                                err = O2CB_ET_PERMISSION_DENIED;
 
2160
                                break;
 
2161
                }
 
2162
                goto out;
 
2163
        }
 
2164
 
 
2165
        control_device_fd = rc;
 
2166
 
 
2167
        err = o2cb_control_handshake(this_node, proto);
 
2168
        if (err) {
 
2169
                close(control_device_fd);
 
2170
                control_device_fd = -1;
 
2171
        }
 
2172
 
 
2173
out:
 
2174
        return err;
 
2175
}
 
2176
 
 
2177
void o2cb_control_close(void)
 
2178
{
 
2179
        if (control_device_fd != -1) {
 
2180
                close(control_device_fd);
 
2181
                control_device_fd = -1;
 
2182
        }
 
2183
}
 
2184
 
 
2185
errcode_t o2cb_control_node_down(const char *uuid, unsigned int nodeid)
 
2186
{
 
2187
        errcode_t err = 0;
 
2188
        size_t ret;
 
2189
        char buf[OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN + 1];
 
2190
 
 
2191
        if (control_device_fd == -1)
 
2192
                return O2CB_ET_INTERNAL_FAILURE;
 
2193
 
 
2194
        snprintf(buf, OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN + 1,
 
2195
                 "DOWN %.32s %08X\n", uuid, nodeid);
 
2196
        ret = write(control_device_fd, buf,
 
2197
                    OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN);
 
2198
        if (ret != OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN)
 
2199
                err = O2CB_ET_IO;
 
2200
 
 
2201
        return err;
 
2202
}
 
2203
 
1309
2204
errcode_t o2cb_get_hb_ctl_path(char *buf, int count)
1310
2205
{
1311
2206
        int fd;