~wb-munzinger/+junk/ocfs2-tools

« back to all changes in this revision

Viewing changes to ocfs2_controld/cman.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:
 
1
/* -*- mode: c; c-basic-offset: 8; -*-
 
2
 * vim: noexpandtab sw=8 ts=8 sts=0:
 
3
 */
 
4
 
 
5
/******************************************************************************
 
6
*******************************************************************************
 
7
**
 
8
**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
 
9
**
 
10
**  This copyrighted material is made available to anyone wishing to use,
 
11
**  modify, copy, or redistribute it subject to the terms and conditions
 
12
**  of the GNU General Public License v.2.
 
13
**
 
14
*******************************************************************************
 
15
******************************************************************************/
 
16
 
 
17
/*
 
18
 * Copyright (C) 2007 Oracle.  All rights reserved.
 
19
 *
 
20
 *  This copyrighted material is made available to anyone wishing to use,
 
21
 *  modify, copy, or redistribute it subject to the terms and conditions
 
22
 *  of the GNU General Public License v.2.
 
23
 */
 
24
 
 
25
#include <stdio.h>
 
26
#include <string.h>
 
27
#include <stdlib.h>
 
28
#include <time.h>
 
29
#include <errno.h>
 
30
#include <unistd.h>
 
31
#include <syslog.h>
 
32
#include <libcman.h>
 
33
 
 
34
#include "ocfs2-kernel/kernel-list.h"
 
35
#include "o2cb/o2cb.h"
 
36
 
 
37
#include "ocfs2_controld.h"
 
38
 
 
39
int                     our_nodeid;
 
40
static int              cman_ci;
 
41
static char *           clustername;
 
42
static cman_cluster_t   cluster;
 
43
static cman_handle_t    ch;
 
44
static cman_handle_t    ch_admin;
 
45
extern struct list_head mounts;
 
46
static cman_node_t      old_nodes[O2NM_MAX_NODES];
 
47
static int              old_node_count;
 
48
static cman_node_t      cman_nodes[O2NM_MAX_NODES];
 
49
static int              cman_node_count;
 
50
 
 
51
const char *stackname = "cman";
 
52
 
 
53
int kill_stack_node(int nodeid)
 
54
{
 
55
        int error;
 
56
 
 
57
        log_debug("killing node %d", nodeid);
 
58
 
 
59
        error = cman_kill_node(ch_admin, nodeid);
 
60
        if (error)
 
61
                log_debug("Unable to kill node %d, %d %d", nodeid, error,
 
62
                          errno);
 
63
 
 
64
        return error;
 
65
}
 
66
 
 
67
static int is_member(cman_node_t *node_list, int count, int nodeid)
 
68
{
 
69
        int i;
 
70
 
 
71
        for (i = 0; i < count; i++) {
 
72
                if (node_list[i].cn_nodeid == nodeid)
 
73
                        return node_list[i].cn_member;
 
74
        }
 
75
        return 0;
 
76
}
 
77
 
 
78
static int is_old_member(int nodeid)
 
79
{
 
80
        return is_member(old_nodes, old_node_count, nodeid);
 
81
}
 
82
 
 
83
static int is_cman_member(int nodeid)
 
84
{
 
85
        return is_member(cman_nodes, cman_node_count, nodeid);
 
86
}
 
87
 
 
88
static cman_node_t *find_cman_node(int nodeid)
 
89
{
 
90
        int i;
 
91
 
 
92
        for (i = 0; i < cman_node_count; i++) {
 
93
                if (cman_nodes[i].cn_nodeid == nodeid)
 
94
                        return &cman_nodes[i];
 
95
        }
 
96
        return NULL;
 
97
}
 
98
 
 
99
char *nodeid2name(int nodeid)
 
100
{
 
101
        cman_node_t *cn;
 
102
 
 
103
        cn = find_cman_node(nodeid);
 
104
        if (!cn)
 
105
                return NULL;
 
106
        return cn->cn_name;
 
107
}
 
108
 
 
109
int validate_cluster(const char *cluster)
 
110
{
 
111
        if (!clustername) {
 
112
                log_error("Trying to validate before cman is alive");
 
113
                return 0;
 
114
        }
 
115
 
 
116
        if (!cluster)
 
117
                return 0;
 
118
 
 
119
        return !strcmp(cluster, clustername);
 
120
}
 
121
 
 
122
int get_clustername(const char **cluster)
 
123
{
 
124
        if (!clustername) {
 
125
                log_error("Trying to validate before cman is alive");
 
126
                return -EIO;
 
127
        }
 
128
 
 
129
        if (!cluster) {
 
130
                log_error("NULL passed!");
 
131
                return -EINVAL;
 
132
        }
 
133
 
 
134
        *cluster = clustername;
 
135
        return 0;
 
136
}
 
137
 
 
138
 
 
139
/* keep track of the nodes */
 
140
static void statechange(void)
 
141
{
 
142
        int i, rv;
 
143
 
 
144
        old_node_count = cman_node_count;
 
145
        memcpy(&old_nodes, &cman_nodes, sizeof(old_nodes));
 
146
 
 
147
        cman_node_count = 0;
 
148
        memset(&cman_nodes, 0, sizeof(cman_nodes));
 
149
        rv = cman_get_nodes(ch, O2NM_MAX_NODES, &cman_node_count,
 
150
                            cman_nodes);
 
151
        if (rv < 0) {
 
152
                log_debug("cman_get_nodes error %d %d", rv, errno);
 
153
                return;
 
154
        }
 
155
 
 
156
        for (i = 0; i < old_node_count; i++) {
 
157
                if (old_nodes[i].cn_member &&
 
158
                    !is_cman_member(old_nodes[i].cn_nodeid)) {
 
159
 
 
160
                        log_debug("cman: node %d removed",
 
161
                                   old_nodes[i].cn_nodeid);
 
162
                }
 
163
        }
 
164
 
 
165
        for (i = 0; i < cman_node_count; i++) {
 
166
                if (cman_nodes[i].cn_member &&
 
167
                    !is_old_member(cman_nodes[i].cn_nodeid)) {
 
168
 
 
169
                        log_debug("cman: node %d added",
 
170
                                  cman_nodes[i].cn_nodeid);
 
171
                }
 
172
        }
 
173
}
 
174
 
 
175
static void cman_callback(cman_handle_t h, void *private, int reason, int arg)
 
176
{
 
177
        switch (reason) {
 
178
                case CMAN_REASON_TRY_SHUTDOWN:
 
179
                        if (!have_mounts())
 
180
                                cman_replyto_shutdown(ch, 1);
 
181
                        else {
 
182
                                log_debug("no to cman shutdown");
 
183
                                cman_replyto_shutdown(ch, 0);
 
184
                        }
 
185
                        break;
 
186
 
 
187
                case CMAN_REASON_STATECHANGE:
 
188
                        statechange();
 
189
                        break;
 
190
        }
 
191
}
 
192
 
 
193
static void dead_cman(int ci)
 
194
{
 
195
        if (ci != cman_ci) {
 
196
                log_error("Unknown connection %d", ci);
 
197
                return;
 
198
        }
 
199
 
 
200
        log_error("cman connection died");
 
201
        shutdown_daemon();
 
202
        connection_dead(ci);
 
203
}
 
204
 
 
205
static void process_cman(int ci)
 
206
{
 
207
        int rv;
 
208
 
 
209
        if (ci != cman_ci) {
 
210
                log_error("Unknown connection %d", ci);
 
211
                return;
 
212
        }
 
213
 
 
214
        rv = cman_dispatch(ch, CMAN_DISPATCH_ALL);
 
215
        if (rv == -1 && errno == EHOSTDOWN) {
 
216
                log_error("cman connection died");
 
217
                shutdown_daemon();
 
218
        }
 
219
}
 
220
 
 
221
int setup_stack(void)
 
222
{
 
223
        cman_node_t node;
 
224
        int rv, fd;
 
225
 
 
226
        ch = cman_init(NULL);
 
227
        if (!ch) {
 
228
                log_error("cman_init error %d", errno);
 
229
                rv = -ENOTCONN;
 
230
                goto fail_finish;
 
231
        }
 
232
 
 
233
        ch_admin = cman_admin_init(NULL);
 
234
        if (!ch_admin) {
 
235
                log_error("cman_admin_init error %d", errno);
 
236
                rv = -ENOTCONN;
 
237
                goto fail_finish;
 
238
        }
 
239
 
 
240
        rv = cman_start_notification(ch, cman_callback);
 
241
        if (rv < 0) {
 
242
                log_error("cman_start_notification error %d %d", rv, errno);
 
243
                goto fail_finish;
 
244
        }
 
245
 
 
246
        /* FIXME: wait here for us to be a member of the cluster */
 
247
 
 
248
        memset(&cluster, 0, sizeof(cluster));
 
249
        rv = cman_get_cluster(ch, &cluster);
 
250
        if (rv < 0) {
 
251
                log_error("cman_get_cluster error %d %d", rv, errno);
 
252
                goto fail_stop;
 
253
        }
 
254
        clustername = cluster.ci_name;
 
255
 
 
256
        memset(&node, 0, sizeof(node));
 
257
        rv = cman_get_node(ch, CMAN_NODEID_US, &node);
 
258
        if (rv < 0) {
 
259
                log_error("cman_get_node error %d %d", rv, errno);
 
260
                goto fail_stop;
 
261
        }
 
262
        our_nodeid = node.cn_nodeid;
 
263
 
 
264
        fd = cman_get_fd(ch);
 
265
 
 
266
        old_node_count = 0;
 
267
        memset(&old_nodes, 0, sizeof(old_nodes));
 
268
        cman_node_count = 0;
 
269
        memset(&cman_nodes, 0, sizeof(cman_nodes));
 
270
 
 
271
        /* Fill the node list */
 
272
        statechange();
 
273
 
 
274
        cman_ci = connection_add(fd, process_cman, dead_cman);
 
275
        if (cman_ci < 0) {
 
276
                rv = cman_ci;
 
277
                log_error("Unable to add cman client: %s",
 
278
                          strerror(-cman_ci));
 
279
                goto fail_stop;
 
280
        }
 
281
 
 
282
        return 0;
 
283
 
 
284
 fail_stop:
 
285
        cman_stop_notification(ch);
 
286
 fail_finish:
 
287
        if (ch_admin)
 
288
                cman_finish(ch_admin);
 
289
        if (ch)
 
290
                cman_finish(ch);
 
291
        ch = ch_admin = NULL;
 
292
        return rv;
 
293
}
 
294
 
 
295
void exit_stack(void)
 
296
{
 
297
        if (ch_admin)
 
298
                cman_finish(ch_admin);
 
299
        if (ch) {
 
300
                log_debug("closing cman connection");
 
301
                cman_stop_notification(ch);
 
302
                cman_finish(ch);
 
303
        }
 
304
}