Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
3 : : *
4 : : * This file is part of LVM2.
5 : : *
6 : : * This copyrighted material is made available to anyone wishing to use,
7 : : * modify, copy, or redistribute it subject to the terms and conditions
8 : : * of the GNU Lesser General Public License v.2.1.
9 : : *
10 : : * You should have received a copy of the GNU Lesser General Public License
11 : : * along with this program; if not, write to the Free Software Foundation,
12 : : * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13 : : */
14 : :
15 : : #include "lib.h"
16 : : #include "toolcontext.h"
17 : : #include "metadata.h"
18 : : #include "segtype.h"
19 : : #include "text_export.h"
20 : : #include "text_import.h"
21 : : #include "config.h"
22 : : #include "activate.h"
23 : : #include "str_list.h"
24 : : #include "targets.h" /* build_dlid */
25 : : #ifdef DMEVENTD
26 : : # include "sharedlib.h"
27 : : # include "libdevmapper-event.h"
28 : : #endif
29 : :
30 : : /* Dm kernel module name for replicator */
31 : : #define REPLICATOR_MODULE "replicator"
32 : : #define REPLICATOR_DEV_MODULE "replicator-dev"
33 : :
34 : : /*
35 : : * Macro used as return argument - returns 0.
36 : : * return is left to be written in the function for better readability.
37 : : */
38 : : #define SEG_LOG_ERROR(t, p...) \
39 : : log_error(t " segment %s of logical volume %s.", ## p, \
40 : : config_parent_name(sn), seg->lv->name), 0;
41 : :
42 : :
43 : : /*
44 : : * Replicator target
45 : : */
46 : 0 : static const char *_replicator_name(const struct lv_segment *seg)
47 : : {
48 : 0 : return seg->segtype->name;
49 : : }
50 : :
51 : : /* FIXME: missing implementation */
52 : 0 : static void _replicator_display(const struct lv_segment *seg)
53 : : {
54 : : //const char *size;
55 : : //uint32_t s;
56 : :
57 : 0 : log_print(" Replicator");
58 [ # # ]: 0 : if (seg->rlog_lv)
59 : 0 : log_print(" Replicator volume\t%s", seg->rlog_lv->name);
60 : 0 : }
61 : :
62 : : /* Wrapper for get_config_uint32() with default value */
63 : 0 : static uint32_t _get_config_uint32(const struct config_node *cn,
64 : : const char *path,
65 : : uint32_t def)
66 : : {
67 : : uint32_t t;
68 : :
69 [ # # ]: 0 : return get_config_uint32(cn, path, &t) ? t : def;
70 : : }
71 : :
72 : : /* Wrapper for get_config_uint64() with default value */
73 : 0 : static uint64_t _get_config_uint64(const struct config_node *cn,
74 : : const char *path,
75 : : uint64_t def)
76 : : {
77 : : uint64_t t;
78 : :
79 [ # # ]: 0 : return get_config_uint64(cn, path, &t) ? t : def;
80 : : }
81 : :
82 : :
83 : : /* Strings replicator_state_t enum */
84 : : static const char _state_txt[NUM_REPLICATOR_STATE][8] = {
85 : : "passive",
86 : : "active"
87 : : };
88 : :
89 : : /* Parse state string */
90 : 0 : static replicator_state_t _get_state(const struct config_node *sn,
91 : : const char *path, replicator_state_t def)
92 : : {
93 : : char *str;
94 : : unsigned i;
95 : :
96 [ # # ]: 0 : if (get_config_str(sn, path, &str)) {
97 [ # # ]: 0 : for (i = 0; i < sizeof(_state_txt)/sizeof(_state_txt[0]); ++i)
98 [ # # ]: 0 : if (strcasecmp(str, _state_txt[i]) == 0)
99 : 0 : return (replicator_state_t) i;
100 : :
101 : 0 : log_warn("%s: unknown value '%s', using default '%s' state",
102 : : path, str, _state_txt[def]);
103 : : }
104 : :
105 : 0 : return def;
106 : : }
107 : :
108 : : /* Strings for replicator_action_t enum */
109 : : static const char _op_mode_txt[NUM_DM_REPLICATOR_MODES][8] = {
110 : : "sync",
111 : : "warn",
112 : : "stall",
113 : : "drop",
114 : : "fail"
115 : : };
116 : :
117 : :
118 : : /* Parse action string */
119 : 0 : static dm_replicator_mode_t _get_op_mode(const struct config_node *sn,
120 : : const char *path, dm_replicator_mode_t def)
121 : : {
122 : : char *str;
123 : : unsigned i;
124 : :
125 [ # # ]: 0 : if (get_config_str(sn, path, &str)) {
126 [ # # ]: 0 : for (i = 0; i < sizeof(_op_mode_txt)/sizeof(_op_mode_txt[0]); ++i)
127 [ # # ]: 0 : if (strcasecmp(str, _op_mode_txt[i]) == 0) {
128 : 0 : log_very_verbose("Setting %s to %s",
129 : : path, _op_mode_txt[i]);
130 : 0 : return (dm_replicator_mode_t) i;
131 : : }
132 : 0 : log_warn("%s: unknown value '%s', using default '%s' operation mode",
133 : : path, str, _op_mode_txt[def]);
134 : : }
135 : :
136 : 0 : return def;
137 : : }
138 : :
139 : 0 : static struct replicator_site *_get_site(struct logical_volume *replicator,
140 : : const char *key)
141 : : {
142 : 0 : struct dm_pool *mem = replicator->vg->vgmem;
143 : : struct replicator_site *rsite;
144 : :
145 : 0 : log_very_verbose("_get_site %s in LV %p", key, replicator->name);
146 : :
147 [ # # ]: 0 : dm_list_iterate_items(rsite, &replicator->rsites)
148 [ # # ]: 0 : if (strcasecmp(rsite->name, key) == 0)
149 : 0 : return rsite;
150 : :
151 : 0 : log_very_verbose("adding new site %s in seg", key);
152 : :
153 [ # # ]: 0 : if (!(rsite = dm_pool_zalloc(mem, sizeof(*rsite))))
154 : 0 : return_NULL;
155 : :
156 [ # # ]: 0 : if (!(rsite->name = dm_pool_strdup(mem, key)))
157 : 0 : return_NULL;
158 : :
159 : 0 : rsite->replicator = replicator;
160 : 0 : dm_list_init(&rsite->rdevices);
161 : 0 : dm_list_add(&replicator->rsites, &rsite->list);
162 : :
163 : 0 : return rsite;
164 : : }
165 : :
166 : :
167 : : /* Parse replicator site element */
168 : 0 : static int _add_site(struct lv_segment *seg,
169 : : const char *key,
170 : : const struct config_node *sn)
171 : : {
172 : 0 : struct dm_pool *mem = seg->lv->vg->vgmem;
173 : : const struct config_node *cn;
174 : : struct replicator_site *rsite;
175 : :
176 [ # # ]: 0 : if (!(rsite = _get_site(seg->lv, key)))
177 : 0 : return_0;
178 : :
179 [ # # ]: 0 : if (!find_config_node(sn, "site_index"))
180 : 0 : return SEG_LOG_ERROR("Mandatory site_index is missing for");
181 : :
182 : 0 : rsite->state = _get_state(sn, "state", REPLICATOR_STATE_PASSIVE);
183 : 0 : rsite->site_index = _get_config_uint32(sn, "site_index", 0);
184 [ # # ]: 0 : if (rsite->site_index > seg->rsite_index_highest)
185 : 0 : return SEG_LOG_ERROR("site_index=%d > highest_site_index=%d for",
186 : : rsite->site_index, seg->rsite_index_highest);
187 : :
188 : 0 : rsite->fall_behind_data = _get_config_uint64(sn, "fall_behind_data", 0);
189 : 0 : rsite->fall_behind_ios = _get_config_uint32(sn, "fall_behind_ios", 0);
190 : 0 : rsite->fall_behind_timeout = _get_config_uint32(sn, "fall_behind_timeout", 0);
191 : 0 : rsite->op_mode = DM_REPLICATOR_SYNC;
192 : :
193 [ # # # # ]: 0 : if (rsite->fall_behind_data ||
[ # # ]
194 : 0 : rsite->fall_behind_ios ||
195 : 0 : rsite->fall_behind_timeout) {
196 [ # # ][ # # ]: 0 : if (rsite->fall_behind_data && rsite->fall_behind_ios)
197 : 0 : return SEG_LOG_ERROR("Defined both fall_behind_data "
198 : : "and fall_behind_ios in");
199 : :
200 [ # # ][ # # ]: 0 : if (rsite->fall_behind_data && rsite->fall_behind_timeout)
201 : 0 : return SEG_LOG_ERROR("Defined both fall_behind_data "
202 : : "and fall_behind_timeout in");
203 : :
204 [ # # ][ # # ]: 0 : if (rsite->fall_behind_ios && rsite->fall_behind_timeout)
205 : 0 : return SEG_LOG_ERROR("Defined both fall_behind_ios "
206 : : "and fall_behind_timeout in");
207 : :
208 : 0 : rsite->op_mode = _get_op_mode(sn, "operation_mode",
209 : : rsite->op_mode);
210 : : }
211 : :
212 [ # # ]: 0 : if ((cn = find_config_node(sn, "volume_group"))) {
213 [ # # ][ # # ]: 0 : if (!cn->v || cn->v->type != CFG_STRING)
214 : 0 : return SEG_LOG_ERROR("volume_group must be a string in");
215 : :
216 [ # # ]: 0 : if (!(rsite->vg_name = dm_pool_strdup(mem, cn->v->v.str)))
217 : 0 : return_0;
218 : :
219 [ # # ]: 0 : } else if (rsite->site_index != 0)
220 : 0 : return SEG_LOG_ERROR("volume_group is mandatory for remote site in");
221 : :
222 : 0 : log_very_verbose("VG/Site: %s/%s state=%s site_index=%d op_mode=%s aios=%d adata=%"
223 : : PRId64 " atimeout=%d", rsite->vg_name, key,
224 : : _state_txt[rsite->state], rsite->site_index,
225 : : _op_mode_txt[rsite->op_mode], rsite->fall_behind_ios,
226 : : rsite->fall_behind_data, rsite->fall_behind_timeout);
227 : :
228 : 0 : return 1;
229 : : }
230 : :
231 : :
232 : : /* Import replicator segment */
233 : 0 : static int _replicator_text_import(struct lv_segment *seg,
234 : : const struct config_node *sn,
235 : : struct dm_hash_table *pv_hash __attribute((unused)))
236 : : {
237 : : const struct config_node *cn;
238 : : struct logical_volume *rlog_lv;
239 : :
240 : 0 : log_very_verbose("%s segment '%s' k:%s a:%d", __func__, seg->lv->name, sn->sib->key, seg->area_count);
241 : :
242 [ # # ]: 0 : if (!replicator_add_replicator_dev(seg->lv, NULL))
243 : 0 : return_0;
244 : :
245 [ # # ][ # # ]: 0 : if (!(cn = find_config_node(sn, "replicator_log")) ||
[ # # ]
246 : 0 : !cn->v || cn->v->type != CFG_STRING)
247 : 0 : return SEG_LOG_ERROR("Replicator log type must be a string in");
248 : :
249 [ # # ]: 0 : if (!(rlog_lv = find_lv(seg->lv->vg, cn->v->v.str)))
250 : 0 : return SEG_LOG_ERROR("Unknown replicator log %s in",
251 : : cn->v->v.str);
252 : :
253 [ # # ][ # # ]: 0 : if (!(cn = find_config_node(sn, "replicator_log_type")) ||
[ # # ]
254 : 0 : !cn->v || cn->v->type != CFG_STRING)
255 : 0 : return SEG_LOG_ERROR("Replicator log's type must be a string in");
256 [ # # ]: 0 : if (strcasecmp(cn->v->v.str, "ringbuffer"))
257 : 0 : return SEG_LOG_ERROR("Only ringbuffer replicator log type is supported in");
258 : :
259 [ # # ]: 0 : if (!(seg->rlog_type = dm_pool_strdup(seg->lv->vg->vgmem, cn->v->v.str)))
260 : 0 : return_0;
261 : :
262 : :
263 : 0 : log_very_verbose("replicator_log = %s", rlog_lv->name);
264 : 0 : log_very_verbose("replicator_log_type = %s", seg->rlog_type);
265 : :
266 [ # # ]: 0 : if (!replicator_add_rlog(seg, rlog_lv))
267 : 0 : return_0;
268 : :
269 : 0 : seg->rdevice_index_highest = _get_config_uint64(sn, "highest_device_index", 0);
270 : 0 : seg->rsite_index_highest = _get_config_uint32(sn, "highest_site_index", 0);
271 : :
272 : 0 : seg->region_size = _get_config_uint32(sn, "sync_log_size", 0);
273 : :
274 [ # # ]: 0 : for (; sn; sn = sn->sib)
275 [ # # ]: 0 : if (!sn->v) {
276 [ # # ]: 0 : for (cn = sn->sib; cn; cn = cn->sib)
277 [ # # ][ # # ]: 0 : if (!cn->v && (strcasecmp(cn->key ,sn->key) == 0))
278 : 0 : return SEG_LOG_ERROR("Detected duplicate site "
279 : : "name %s in", sn->key);
280 [ # # ]: 0 : if (!_add_site(seg, sn->key, sn->child))
281 : 0 : return_0;
282 : : }
283 : 0 : return 1;
284 : : }
285 : :
286 : : /* Export replicator segment */
287 : 0 : static int _replicator_text_export(const struct lv_segment *seg,
288 : : struct formatter *f)
289 : : {
290 : : struct replicator_site *rsite;
291 : :
292 [ # # ]: 0 : if (!seg->rlog_lv)
293 : 0 : return_0;
294 : :
295 [ # # ]: 0 : outf(f, "replicator_log = \"%s\"", seg->rlog_lv->name);
296 [ # # ]: 0 : outf(f, "replicator_log_type = \"%s\"", seg->rlog_type);
297 [ # # ]: 0 : outf(f, "highest_device_index = %" PRIu64, seg->rdevice_index_highest);
298 [ # # ]: 0 : outf(f, "highest_site_index = %d", seg->rsite_index_highest);
299 : :
300 [ # # ]: 0 : if (seg->region_size)
301 [ # # ]: 0 : outsize(f, (uint64_t)seg->region_size,
302 : : "sync_log_size = %" PRIu32, seg->region_size);
303 : :
304 [ # # ]: 0 : if (!dm_list_empty(&seg->lv->rsites))
305 [ # # ]: 0 : outnl(f);
306 : :
307 [ # # ]: 0 : dm_list_iterate_items(rsite, &seg->lv->rsites) {
308 [ # # ]: 0 : outf(f, "%s {", rsite->name);
309 : 0 : out_inc_indent(f);
310 : :
311 [ # # ]: 0 : outf(f, "state = \"%s\"", _state_txt[rsite->state]);
312 [ # # ]: 0 : outf(f, "site_index = %d", rsite->site_index);
313 : :
314 : : /* Only non-default parameters are written */
315 [ # # ]: 0 : if (rsite->op_mode != DM_REPLICATOR_SYNC)
316 [ # # ]: 0 : outf(f, "operation_mode = \"%s\"",
317 : : _op_mode_txt[rsite->op_mode]);
318 [ # # ]: 0 : if (rsite->fall_behind_timeout)
319 [ # # ]: 0 : outfc(f, "# seconds", "fall_behind_timeout = %u",
320 : : rsite->fall_behind_timeout);
321 [ # # ]: 0 : if (rsite->fall_behind_ios)
322 [ # # ]: 0 : outfc(f, "# io operations", "fall_behind_ios = %u",
323 : : rsite->fall_behind_ios);
324 [ # # ]: 0 : if (rsite->fall_behind_data)
325 [ # # ]: 0 : outsize(f, rsite->fall_behind_data, "fall_behind_data = %" PRIu64,
326 : : rsite->fall_behind_data);
327 [ # # ][ # # ]: 0 : if (rsite->state != REPLICATOR_STATE_ACTIVE && rsite->vg_name)
328 [ # # ]: 0 : outf(f, "volume_group = \"%s\"", rsite->vg_name);
329 : :
330 : 0 : out_dec_indent(f);
331 [ # # ]: 0 : outf(f, "}");
332 : : }
333 : :
334 : 0 : return 1;
335 : : }
336 : :
337 : : #ifdef DEVMAPPER_SUPPORT
338 : 0 : static int _replicator_add_target_line(struct dev_manager *dm,
339 : : struct dm_pool *mem,
340 : : struct cmd_context *cmd,
341 : : void **target_state,
342 : : struct lv_segment *seg,
343 : : struct dm_tree_node *node,
344 : : uint64_t len,
345 : : uint32_t *pvmove_mirror_count)
346 : : {
347 : : const char *rlog_dlid;
348 : : struct replicator_site *rsite;
349 : :
350 : 0 : log_very_verbose("Activate replicator '%s' %s",
351 : : seg->lv->name, seg->lv->lvid.s);
352 [ # # ]: 0 : if (!seg->rlog_lv)
353 : 0 : return_0;
354 : :
355 [ # # ]: 0 : if (!(rlog_dlid = build_dlid(dm, seg->rlog_lv->lvid.s, NULL)))
356 : 0 : return_0;
357 : :
358 [ # # ]: 0 : dm_list_iterate_items(rsite, &seg->lv->rsites) {
359 [ # # ]: 0 : if (!dm_tree_node_add_replicator_target(node,
360 : 0 : seg->rlog_lv->size,
361 : : rlog_dlid,
362 : : seg->rlog_type,
363 : : rsite->site_index,
364 : : rsite->op_mode,
365 : : rsite->fall_behind_timeout,
366 : : rsite->fall_behind_data,
367 : : rsite->fall_behind_ios)) {
368 [ # # ]: 0 : if (rsite->site_index == 0) {
369 : 0 : log_error("Failed to add replicator log '%s' "
370 : : "to replicator '%s'.",
371 : : rlog_dlid, seg->lv->name);
372 : 0 : return 0;
373 : : }
374 : : // FIXME:
375 : : }
376 : : }
377 : :
378 : 0 : return 1;
379 : : }
380 : :
381 : : /* FIXME: write something useful for replicator here */
382 : 0 : static int _replicator_target_percent(void **target_state,
383 : : percent_range_t *percent_range,
384 : : struct dm_pool *mem,
385 : : struct cmd_context *cmd,
386 : : struct lv_segment *seg,
387 : : char *params, uint64_t *total_numerator,
388 : : uint64_t *total_denominator)
389 : : {
390 : 0 : return 1;
391 : : }
392 : :
393 : : /* Check for module presence */
394 : 0 : static int _replicator_target_present(struct cmd_context *cmd,
395 : : const struct lv_segment *seg __attribute((unused)),
396 : : unsigned *attributes __attribute((unused)))
397 : : {
398 : : static int _checked = 0;
399 : : static int _present = 0;
400 : :
401 [ # # ]: 0 : if (!_checked) {
402 : 0 : _present = target_present(cmd, REPLICATOR_MODULE, 1);
403 : 0 : _checked = 1;
404 : : }
405 : :
406 : 0 : return _present;
407 : : }
408 : :
409 : : #endif
410 : :
411 : 0 : static int _replicator_modules_needed(struct dm_pool *mem,
412 : : const struct lv_segment *seg __attribute((unused)),
413 : : struct dm_list *modules)
414 : : {
415 [ # # ]: 0 : if (!str_list_add(mem, modules, REPLICATOR_MODULE))
416 : 0 : return_0;
417 : :
418 [ # # ]: 0 : if (!str_list_add(mem, modules, REPLICATOR_DEV_MODULE))
419 : 0 : return_0;
420 : :
421 : 0 : return 1;
422 : : }
423 : :
424 : 6 : static void _replicator_destroy(const struct segment_type *segtype)
425 : : {
426 : 6 : dm_free((void *)segtype);
427 : 6 : }
428 : :
429 : : static struct segtype_handler _replicator_ops = {
430 : : .name = _replicator_name,
431 : : .display = _replicator_display,
432 : : .text_import = _replicator_text_import,
433 : : .text_export = _replicator_text_export,
434 : : #ifdef DEVMAPPER_SUPPORT
435 : : .add_target_line = _replicator_add_target_line,
436 : : .target_percent = _replicator_target_percent,
437 : : .target_present = _replicator_target_present,
438 : : #endif
439 : : .modules_needed = _replicator_modules_needed,
440 : : .destroy = _replicator_destroy,
441 : : };
442 : :
443 : : /*
444 : : * Replicator-dev target
445 : : */
446 : 0 : static void _replicator_dev_display(const struct lv_segment *seg)
447 : : {
448 : : //const char *size;
449 : : //uint32_t s;
450 : : // FIXME: debug test code for now
451 : 0 : log_print(" Replicator\t\t%u", seg->area_count);
452 : 0 : log_print(" Mirror size\t\t%u", seg->area_len);
453 [ # # ]: 0 : if (seg->log_lv)
454 : 0 : log_print(" Replicator log volume\t%s", seg->rlog_lv->name);
455 : :
456 : 0 : }
457 : :
458 : 0 : static int _add_device(struct lv_segment *seg,
459 : : const char *site_name,
460 : : const struct config_node *sn,
461 : : uint64_t devidx)
462 : : {
463 : 0 : struct dm_pool *mem = seg->lv->vg->vgmem;
464 : 0 : struct logical_volume *lv = NULL;
465 : 0 : struct logical_volume *slog_lv = NULL;
466 : 0 : struct replicator_site *rsite = _get_site(seg->replicator, site_name);
467 : : struct replicator_device *rdev;
468 : 0 : const char *dev_str = NULL;
469 : 0 : const char *slog_str = NULL;
470 : : const struct config_node *cn;
471 : :
472 [ # # ]: 0 : dm_list_iterate_items(rdev, &rsite->rdevices)
473 [ # # ]: 0 : if (rdev->replicator_dev == seg)
474 : 0 : return SEG_LOG_ERROR("Duplicate site found in");
475 : :
476 [ # # ]: 0 : if ((cn = find_config_node(sn, "sync_log"))) {
477 [ # # ][ # # ]: 0 : if (!cn->v || !cn->v->v.str)
478 : 0 : return SEG_LOG_ERROR("Sync log must be a string in");
479 : 0 : slog_str = cn->v->v.str;
480 : : }
481 : :
482 [ # # ][ # # ]: 0 : if (!(cn = find_config_node(sn, "logical_volume")) ||
[ # # ]
483 : 0 : !cn->v || !cn->v->v.str)
484 : 0 : return SEG_LOG_ERROR("Logical volume must be a string in");
485 : :
486 : 0 : dev_str = cn->v->v.str;
487 : :
488 [ # # ]: 0 : if (!seg->lv->rdevice) {
489 [ # # ]: 0 : if (slog_str)
490 : 0 : return SEG_LOG_ERROR("Sync log %s defined for local "
491 : : "device in", slog_str);
492 : :
493 : : /* Check for device in current VG */
494 [ # # ]: 0 : if (!(lv = find_lv(seg->lv->vg, dev_str)))
495 : 0 : return SEG_LOG_ERROR("Logical volume %s not found in",
496 : : dev_str);
497 : : } else {
498 [ # # ]: 0 : if (!slog_str)
499 : 0 : return SEG_LOG_ERROR("Sync log is missing for remote "
500 : : "device in");
501 : : /* Check for slog device in current VG */
502 [ # # ]: 0 : if (!(slog_lv = find_lv(seg->lv->vg, slog_str)))
503 : 0 : return SEG_LOG_ERROR("Sync log %s not found in",
504 : : slog_str);
505 : : }
506 : :
507 [ # # ]: 0 : if (!(rdev = dm_pool_zalloc(mem, sizeof(*rdev))))
508 : 0 : return_0;
509 : :
510 [ # # ]: 0 : if (!(rdev->name = dm_pool_strdup(mem, dev_str)))
511 : 0 : return_0;
512 : :
513 : 0 : log_very_verbose("Created rdev=%p lv=%p str=%p",
514 : : rdev, seg->lv, slog_str);
515 : 0 : rdev->replicator_dev = seg;
516 : 0 : rdev->rsite = rsite;
517 : 0 : rdev->device_index = devidx;
518 : :
519 [ # # ]: 0 : if (!seg->lv->rdevice) {
520 [ # # ]: 0 : if (!replicator_dev_add_rimage(rdev, lv))
521 : 0 : return SEG_LOG_ERROR("LV inconsistency found in");
522 : 0 : seg->lv->rdevice = rdev;
523 : : } else {
524 [ # # # # ]: 0 : if (!slog_str ||
525 : 0 : !(rdev->slog_name = dm_pool_strdup(mem, slog_str)))
526 : 0 : return_0;
527 : :
528 [ # # ]: 0 : if (!replicator_dev_add_slog(rdev, slog_lv))
529 : 0 : return SEG_LOG_ERROR("Sync log inconsistency found in");
530 : :
531 : : // we keep only name reference for remote LV
532 : : //log_verbose("FIND REMOTE VG %p %s", rsite->vg, rsite->vg_name);
533 : : //lv = find_lv(rsite->vg, dev_str);
534 : : //log_verbose("FIND REMOTE %s %p %s", dev_str, lv, (lv) ? lv->name : "NOT FOUND");
535 : : }
536 : :
537 : 0 : dm_list_add(&rsite->rdevices, &rdev->list);// linked site list
538 : :
539 : 0 : return 1;
540 : : }
541 : :
542 : : /* Import replicator segment */
543 : 0 : static int _replicator_dev_text_import(struct lv_segment *seg,
544 : : const struct config_node *sn,
545 : : struct dm_hash_table *pv_hash __attribute((unused)))
546 : : {
547 : : const struct config_node *cn;
548 : : struct logical_volume *replicator;
549 : : uint64_t devidx;
550 : :
551 : 0 : log_very_verbose("%s segment '%s' k:%s a:%d", __func__, seg->lv->name, sn->sib->key, seg->area_count);
552 : :
553 [ # # ]: 0 : if (!(cn = find_config_node(sn, "replicator")))
554 : 0 : return SEG_LOG_ERROR("Replicator is missing for");
555 : :
556 [ # # ][ # # ]: 0 : if (!cn->v || !cn->v->v.str)
557 : 0 : return SEG_LOG_ERROR("Replicator must be a string for");
558 : :
559 [ # # ]: 0 : if (!(replicator = find_lv(seg->lv->vg, cn->v->v.str)))
560 : 0 : return SEG_LOG_ERROR("Unknown replicator %s for", cn->v->v.str);
561 : :
562 [ # # ]: 0 : if (!replicator_add_replicator_dev(replicator, seg))
563 : 0 : return_0;
564 : :
565 : 0 : log_very_verbose("replicator=%s", replicator->name);
566 : :
567 : : /* Mandatory */
568 [ # # # # ]: 0 : if (!find_config_node(sn, "device_index") ||
569 : 0 : !get_config_uint64(sn, "device_index", &devidx))
570 : 0 : return SEG_LOG_ERROR("Could not read 'device_index' for");
571 : :
572 : : /* Read devices from sites */
573 [ # # ]: 0 : for (; sn; sn = sn->sib)
574 [ # # ][ # # ]: 0 : if (!(sn->v) && !_add_device(seg, sn->key, sn->child, devidx))
575 : 0 : return_0;
576 : :
577 [ # # ]: 0 : if (!seg->lv->rdevice)
578 : 0 : return SEG_LOG_ERROR("Replicator device without site in");
579 : :
580 : 0 : seg->rlog_lv = NULL;
581 : 0 : seg->lv->status |= REPLICATOR;
582 : :
583 : 0 : return 1;
584 : : }
585 : :
586 : : /* Export replicator-dev segment */
587 : 0 : static int _replicator_dev_text_export(const struct lv_segment *seg,
588 : : struct formatter *f)
589 : : {
590 : : struct replicator_site *rsite;
591 : : struct replicator_device *rdev;
592 : :
593 [ # # ][ # # ]: 0 : if (!seg->replicator || !seg->lv->rdevice)
594 : 0 : return_0;
595 : :
596 [ # # ]: 0 : outf(f, "replicator = \"%s\"", seg->replicator->name);
597 [ # # ]: 0 : outf(f, "device_index = %" PRId64, seg->lv->rdevice->device_index);
598 : :
599 [ # # ]: 0 : outnl(f);
600 : :
601 [ # # ]: 0 : dm_list_iterate_items(rsite, &seg->replicator->rsites) {
602 [ # # ]: 0 : dm_list_iterate_items(rdev, &rsite->rdevices) {
603 [ # # ]: 0 : if (rdev->replicator_dev != seg)
604 : 0 : continue;
605 : :
606 [ # # ]: 0 : outf(f, "%s {", rdev->rsite->name);
607 : :
608 : 0 : out_inc_indent(f);
609 : :
610 [ # # ][ # # ]: 0 : outf(f, "logical_volume = \"%s\"",
611 : : rdev->name ? rdev->name : rdev->lv->name);
612 : :
613 [ # # ]: 0 : if (rdev->slog)
614 [ # # ]: 0 : outf(f, "sync_log = \"%s\"", rdev->slog->name);
615 [ # # ]: 0 : else if (rdev->slog_name)
616 [ # # ]: 0 : outf(f, "sync_log = \"%s\"", rdev->slog_name);
617 : :
618 : 0 : out_dec_indent(f);
619 : :
620 [ # # ]: 0 : outf(f, "}");
621 : : }
622 : : }
623 : :
624 : 0 : return 1;
625 : : }
626 : :
627 : : #ifdef DEVMAPPER_SUPPORT
628 : : /*
629 : : * Add target for passive site matching the device index
630 : : */
631 : 0 : static int _replicator_dev_add_target_line(struct dev_manager *dm,
632 : : struct dm_pool *mem,
633 : : struct cmd_context *cmd,
634 : : void **target_state,
635 : : struct lv_segment *seg,
636 : : struct dm_tree_node *node,
637 : : uint64_t len,
638 : : uint32_t *pvmove_mirror_count)
639 : : {
640 : : const char *replicator_dlid, *rdev_dlid, *slog_dlid;
641 : : struct replicator_device *rdev, *rdev_search;
642 : : struct replicator_site *rsite;
643 : : uint32_t slog_size;
644 : : uint32_t slog_flags;
645 : :
646 [ # # ]: 0 : if (!lv_is_active_replicator_dev(seg->lv)) {
647 : : /* Create passive linear mapping */
648 : 0 : log_very_verbose("Inactive replicator %s using %s.",
649 : : seg->lv->name, seg->lv->rdevice->lv->name);
650 [ # # ]: 0 : if (!dm_tree_node_add_linear_target(node, seg->lv->size))
651 : 0 : return_0;
652 [ # # ]: 0 : if (!(rdev_dlid = build_dlid(dm, seg->lv->rdevice->lv->lvid.s, NULL)))
653 : 0 : return_0;
654 : 0 : return dm_tree_node_add_target_area(node, NULL, rdev_dlid, 0);
655 [ # # ]: 0 : } else if (seg->lv->rdevice->rsite->site_index) {
656 : 0 : log_error("Active site with site_index != 0 (%s, %d)",
657 : : seg->lv->rdevice->rsite->name,
658 : : seg->lv->rdevice->rsite->site_index);
659 : 0 : return 0; /* Replicator without any active site */
660 : : }
661 : :
662 : : /*
663 : : * At this point all devices that have some connection with replicator
664 : : * must be present in dm_tree
665 : : */
666 : 0 : log_very_verbose("Creating replicator %s (size %" PRIu64 ") %s %s",
667 : : seg->lv->name, seg->lv->size,
668 : : seg->lv->rdevice->lv->name,
669 : : seg->lv->rdevice->lv->lvid.s );
670 : :
671 [ # # # # ]: 0 : if (!seg_is_replicator_dev(seg) ||
672 : 0 : !(replicator_dlid = build_dlid(dm, seg->replicator->lvid.s, NULL)))
673 : 0 : return_0;
674 : :
675 : : /* Select remote devices with the same device index */
676 [ # # ]: 0 : dm_list_iterate_items(rsite, &seg->replicator->rsites) {
677 : 0 : log_verbose("Adding site: %s", rsite->name);
678 [ # # ]: 0 : if (rsite->site_index == 0) {
679 : : /* Local slink0 device */
680 : 0 : rdev = seg->lv->rdevice;
681 : : } else {
682 : : //log_verbose("Adding remote sites from: %s list size: %d", seg->replicator_lv->name, dm_list_size(&seg->replicator_lv->rsites));
683 : 0 : rdev = NULL;
684 [ # # ]: 0 : dm_list_iterate_items(rdev_search, &rsite->rdevices) {
685 [ # # ]: 0 : if (rdev_search->replicator_dev == seg) {
686 [ # # ]: 0 : log_verbose("Found %s in %s", (rdev_search->lv) ?
687 : : rdev_search->lv->name : rdev_search->name,
688 : : rsite->name);
689 : 0 : rdev = rdev_search;
690 : 0 : break;
691 : : }
692 : : }
693 : :
694 [ # # ]: 0 : if (!rdev) {
695 : 0 : log_error(INTERNAL_ERROR "rdev list not found.");
696 : 0 : return 0;
697 : : }
698 : : }
699 : :
700 [ # # # # ]: 0 : if (!rdev->lv ||
701 : 0 : !(rdev_dlid = build_dlid(dm, rdev->lv->lvid.s, NULL)))
702 : 0 : return_0;
703 : :
704 : 0 : slog_dlid = NULL;
705 : :
706 : : /* Using either disk or core (in memory) log */
707 [ # # ]: 0 : if (rdev->slog) {
708 : 0 : slog_flags = DM_NOSYNC;
709 : 0 : slog_size = (uint32_t) rdev->slog->size;
710 : : /* slog_size = 2048; FIXME: HACK */
711 [ # # ]: 0 : if (!(slog_dlid = build_dlid(dm, rdev->slog->lvid.s, NULL)))
712 : 0 : return_0;
713 [ # # ][ # # ]: 0 : } else if (rdev->slog_name &&
714 : 0 : sscanf(rdev->slog_name, "%" PRIu32, &slog_size) == 1) {
715 : 0 : slog_flags = DM_CORELOG | DM_FORCESYNC;
716 [ # # ]: 0 : if (slog_size == 0) {
717 : 0 : log_error("Failed to use empty corelog size "
718 : : "in replicator '%s'.",
719 : : rsite->replicator->name);
720 : 0 : return 0;
721 : : }
722 : : } else {
723 : 0 : slog_flags = DM_CORELOG | DM_FORCESYNC;
724 : 0 : slog_size = 0; /* NOLOG */
725 : : }
726 : :
727 [ # # ]: 0 : if (!dm_tree_node_add_replicator_dev_target(node,
728 : 0 : seg->lv->size,
729 : : replicator_dlid,
730 : 0 : seg->lv->rdevice->device_index,
731 : : rdev_dlid,
732 : : rsite->site_index,
733 : : slog_dlid,
734 : : slog_flags,
735 : : slog_size)) {
736 : 0 : return_0;
737 : : /*
738 : : * CHECKME: handle 'state = dropped' in future
739 : : */
740 : : }
741 : : }
742 : :
743 : 0 : return 1;
744 : : }
745 : :
746 : : /* FIXME: write something useful for replicator-dev here */
747 : 0 : static int _replicator_dev_target_percent(void **target_state,
748 : : percent_range_t *percent_range,
749 : : struct dm_pool *mem,
750 : : struct cmd_context *cmd,
751 : : struct lv_segment *seg,
752 : : char *params,
753 : : uint64_t *total_numerator,
754 : : uint64_t *total_denominator)
755 : : {
756 : 0 : return 1;
757 : : }
758 : :
759 : : /* Check for module presence */
760 : 0 : static int _replicator_dev_target_present(struct cmd_context *cmd,
761 : : const struct lv_segment *seg __attribute((unused)),
762 : : unsigned *attributes __attribute((unused)))
763 : : {
764 : : static int _checked = 0;
765 : : static int _present = 0;
766 : :
767 [ # # ]: 0 : if (!_checked) {
768 : 0 : _present = target_present(cmd, REPLICATOR_DEV_MODULE, 1);
769 : 0 : _checked = 1;
770 : : }
771 : :
772 : 0 : return _present;
773 : : }
774 : :
775 : : #endif
776 : :
777 : : static struct segtype_handler _replicator_dev_ops = {
778 : : .name = _replicator_name,
779 : : .display = _replicator_dev_display,
780 : : .text_import = _replicator_dev_text_import,
781 : : .text_export = _replicator_dev_text_export,
782 : : #ifdef DEVMAPPER_SUPPORT
783 : : .add_target_line = _replicator_dev_add_target_line,
784 : : .target_percent = _replicator_dev_target_percent,
785 : : .target_present = _replicator_dev_target_present,
786 : : #endif
787 : : .modules_needed = _replicator_modules_needed,
788 : : .destroy = _replicator_destroy,
789 : : };
790 : :
791 : : #ifdef REPLICATOR_INTERNAL
792 : 3 : int init_replicator_segtype(struct segtype_library *seglib)
793 : : #else /* Shared */
794 : : int init_multiple_segtype(struct segtype_library *seglib);
795 : : int init_multiple_segtype(struct segtype_library *seglib)
796 : : #endif
797 : : {
798 : : struct segment_type *segtype;
799 : :
800 [ - + ]: 3 : if (!(segtype = dm_malloc(sizeof(*segtype))))
801 : 0 : return_0;
802 : :
803 : 3 : segtype->ops = &_replicator_ops;
804 : 3 : segtype->name = REPLICATOR_MODULE;
805 : 3 : segtype->private = NULL;
806 : 3 : segtype->flags = SEG_REPLICATOR;
807 : :
808 [ - + ]: 3 : if (!lvm_register_segtype(seglib, segtype))
809 : 0 : return_0;
810 : :
811 : 3 : log_very_verbose("Initialised segtype: " REPLICATOR_MODULE);
812 : :
813 [ - + ]: 3 : if (!(segtype = dm_malloc(sizeof(*segtype))))
814 : 0 : return_0;
815 : :
816 : 3 : segtype->ops = &_replicator_dev_ops;
817 : 3 : segtype->name = REPLICATOR_DEV_MODULE;
818 : 3 : segtype->private = NULL;
819 : 3 : segtype->flags = SEG_REPLICATOR_DEV;
820 : :
821 [ - + ]: 3 : if (!lvm_register_segtype(seglib, segtype))
822 : 0 : return_0;
823 : :
824 : 3 : log_very_verbose("Initialised segtype: " REPLICATOR_DEV_MODULE);
825 : :
826 : 3 : return 1;
827 : : }
|