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 <inttypes.h>
16 : : #include <sys/types.h>
17 : : #include "libdevmapper.h"
18 : : #include "lvm-types.h"
19 : :
20 : : #include "activate.h"
21 : : #include "archiver.h"
22 : : #include "defaults.h"
23 : : #include "label.h"
24 : : #include "lib.h"
25 : : #include "locking.h"
26 : : #include "lv_alloc.h"
27 : : #include "lvm-string.h"
28 : : #include "metadata.h"
29 : : #include "segtype.h"
30 : : #include "str_list.h"
31 : : #include "toolcontext.h"
32 : :
33 : : /* Add lv as replicator_dev device */
34 : 0 : int replicator_dev_add_rimage(struct replicator_device *rdev,
35 : : struct logical_volume *lv)
36 : : {
37 [ # # ][ # # ]: 0 : if (!lv || !rdev)
38 : 0 : return_0;
39 : 0 : log_verbose("try add_rimage");
40 : :
41 [ # # ]: 0 : if (lv_is_rimage(lv)) {
42 : 0 : log_error("Logical volume %s is already part of other "
43 : : "replicator.", lv->name);
44 : 0 : return 0;
45 : : }
46 : :
47 [ # # ]: 0 : if (rdev->lv) {
48 : 0 : log_error("Logical volume %s can not be attached to an "
49 : : "already defined replicator_device", lv->name);
50 : 0 : return 0;
51 : : }
52 : :
53 : 0 : lv_set_hidden(lv);
54 : 0 : lv->rdevice = rdev;
55 : 0 : rdev->lv = lv;
56 : :
57 : 0 : return add_seg_to_segs_using_this_lv(lv, rdev->replicator_dev);
58 : : }
59 : :
60 : : /* Remove lv from replicator_dev device */
61 : 0 : struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev)
62 : : {
63 : : struct logical_volume *lv;
64 : :
65 [ # # ][ # # ]: 0 : if (!rdev || !rdev->lv)
66 : 0 : return_NULL;
67 : :
68 : 0 : lv = rdev->lv;
69 [ # # ]: 0 : if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
70 : 0 : return_NULL;
71 : :
72 : : /* FIXME: - check for site references */
73 : 0 : rdev->lv = NULL;
74 : 0 : lv->rdevice = NULL;
75 : 0 : lv_set_visible(lv);
76 : :
77 : 0 : return lv;
78 : : }
79 : :
80 : 0 : int replicator_dev_add_slog(struct replicator_device *rdev,
81 : : struct logical_volume *slog)
82 : : {
83 [ # # ][ # # ]: 0 : if (!slog || !rdev)
84 : 0 : return_0;
85 : :
86 [ # # ]: 0 : if (rdev->slog) {
87 : 0 : log_error("Replicator device in site %s already has sync log.",
88 : : rdev->rsite->name);
89 : 0 : return 0;
90 : : }
91 : :
92 [ # # ]: 0 : if (slog->rdevice) {
93 : 0 : log_error("Sync log %s is already used by replicator %s.",
94 : : slog->name, slog->rdevice->rsite->replicator->name);
95 : 0 : return 0;
96 : : }
97 : :
98 : 0 : lv_set_hidden(slog);
99 : 0 : slog->rdevice = rdev;
100 : 0 : rdev->slog = slog;
101 : :
102 : 0 : return add_seg_to_segs_using_this_lv(slog, rdev->replicator_dev);
103 : : }
104 : :
105 : 0 : struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev)
106 : : {
107 : : struct logical_volume *lv;
108 : :
109 [ # # ]: 0 : if (!rdev)
110 : 0 : return_NULL;
111 : :
112 : 0 : lv = rdev->slog;
113 [ # # ]: 0 : if (!lv) {
114 : 0 : log_error("Replicator device in site %s does not have sync log.",
115 : : rdev->rsite->name);
116 : 0 : return NULL;
117 : : }
118 : :
119 [ # # ]: 0 : if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
120 : 0 : return_NULL;
121 : :
122 : 0 : rdev->slog = NULL;
123 : 0 : lv->rdevice = NULL;
124 : 0 : lv_set_visible(lv);
125 : :
126 : 0 : return lv;
127 : : }
128 : :
129 : 0 : int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
130 : : struct lv_segment *replicator_dev_seg)
131 : : {
132 [ # # ]: 0 : if (!replicator_lv)
133 : 0 : return_0;
134 : :
135 [ # # ]: 0 : if (!(replicator_lv->status & REPLICATOR)) {
136 : 0 : dm_list_init(&replicator_lv->rsites);
137 : 0 : lv_set_hidden(replicator_lv);
138 : 0 : replicator_lv->status |= REPLICATOR;
139 : : }
140 : :
141 [ # # ]: 0 : if (!replicator_dev_seg)
142 : 0 : return 1;
143 : :
144 [ # # ]: 0 : if (replicator_dev_seg->replicator) {
145 : 0 : log_error("Replicator device %s is already part of replicator.",
146 : : replicator_dev_seg->lv->name);
147 : 0 : return 0;
148 : : }
149 : :
150 : 0 : replicator_dev_seg->replicator = replicator_lv;
151 : :
152 : 0 : return add_seg_to_segs_using_this_lv(replicator_lv, replicator_dev_seg);
153 : : }
154 : :
155 : : /**
156 : : * Returns rimage ?? lv upon succeful detach of device
157 : : * entire LV entry should be removed by this crootall ??
158 : : */
159 : 0 : struct logical_volume *replicator_remove_replicator_dev(struct lv_segment *replicator_dev_seg)
160 : : {
161 : 0 : struct logical_volume *lv = NULL;
162 : :
163 : 0 : log_error("FIXME: not implemented.");
164 : : #if 0
165 : : /* FIXME: - this is going to be complex.... */
166 : : if (!replicator_dev_seg)
167 : : return_NULL;
168 : :
169 : : /* if slog or rimage - exit */
170 : :
171 : : if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
172 : : return_NULL;
173 : :
174 : : replicator_seg->rlog_lv = NULL;
175 : : lv->status &= ~REPLICATOR_LOG;
176 : : lv_set_visible(lv);
177 : : #endif
178 : :
179 : 0 : return lv;
180 : : }
181 : :
182 : 0 : int replicator_add_rlog(struct lv_segment *replicator_seg,
183 : : struct logical_volume *rlog_lv)
184 : : {
185 [ # # ]: 0 : if (!rlog_lv)
186 : 0 : return_0;
187 : :
188 [ # # ]: 0 : if (rlog_lv->status & REPLICATOR_LOG) {
189 : 0 : log_error("Rlog device %s is already used.", rlog_lv->name);
190 : 0 : return 0;
191 : : }
192 : :
193 : 0 : lv_set_hidden(rlog_lv);
194 : 0 : rlog_lv->status |= REPLICATOR_LOG;
195 : 0 : replicator_seg->rlog_lv = rlog_lv;
196 : :
197 : 0 : return add_seg_to_segs_using_this_lv(rlog_lv, replicator_seg);
198 : : }
199 : :
200 : 0 : struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg)
201 : : {
202 : : struct logical_volume *lv;
203 : :
204 [ # # ]: 0 : if (!replicator_seg)
205 : 0 : return_0;
206 : :
207 [ # # ]: 0 : if (!(lv = replicator_seg->rlog_lv)) {
208 : 0 : log_error("Replog segment %s does not have rlog.",
209 : : replicator_seg->lv->name);
210 : 0 : return NULL;
211 : : }
212 : :
213 [ # # ]: 0 : if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
214 : 0 : return_NULL;
215 : :
216 : 0 : replicator_seg->rlog_lv = NULL;
217 : 0 : lv->status &= ~REPLICATOR_LOG;
218 : 0 : lv_set_visible(lv);
219 : :
220 : 0 : return lv;
221 : : }
222 : :
223 : :
224 : : #if 0
225 : : /*
226 : : * Create new LV to pretend the original LV
227 : : * this target will have a 'replicator' segment
228 : : */
229 : : int lv_add_replicator(struct logical_volume *origin, const char *rep_suffix)
230 : : {
231 : : struct logical_volume *rep_lv;
232 : : char *name;
233 : : size_t slen;
234 : :
235 : : if (!(name = strstr(origin->name, rep_suffix))) {
236 : : log_error("Failed to find replicator suffix %s in LV name %s",
237 : : rep_suffix, origin->name);
238 : : return 0;
239 : : }
240 : : slen = (size_t)(name - origin->name);
241 : : name = alloca(slen + 1);
242 : : memcpy(name, origin->name, slen);
243 : : name[slen] = 0;
244 : :
245 : : if ((rep_lv = find_lv(origin->vg, name))) {
246 : : rep_lv->status |= VIRTUAL;
247 : : log_very_verbose("Found already created lv %s le:%" PRIu32,
248 : : rep_lv->name, rep_lv->le_count);
249 : : return 1;
250 : : }
251 : :
252 : : if (!(rep_lv = lv_create_empty(name, &origin->lvid,
253 : : LVM_READ | LVM_WRITE | VISIBLE_LV,
254 : : ALLOC_INHERIT, origin->vg)))
255 : : return_0;
256 : :
257 : : log_very_verbose("Created empty lv %s %s le:%" PRIu32,
258 : : rep_lv->name, origin->name, origin->le_count);
259 : :
260 : : if (!lv_add_virtual_segment(rep_lv, 0, origin->le_count,
261 : : get_segtype_from_string(origin->vg->cmd,
262 : : "error")))
263 : : return_0;
264 : :
265 : : rep_lv->status |= VIRTUAL;
266 : : return 1;
267 : : }
268 : :
269 : : int lv_remove_replicator(struct logical_volume *lv)
270 : : {
271 : : return 1;
272 : : }
273 : : #endif
274 : :
275 : : /*
276 : : * Check all replicator structures:
277 : : * only non-clustered vg for replicator
278 : : * only one segment in replicator LV
279 : : * site has correct combination of operation_mode parameters
280 : : * site and devices have correct index numbers
281 : : * duplicate site names, site indexes, device names, device indexes
282 : : */
283 : 0 : int replicator_check_segment(const struct lv_segment *rseg)
284 : : {
285 : : struct replicator_site *rsite, *rsiteb;
286 : : struct replicator_device *rdev, *rdevb;
287 : 0 : struct logical_volume *lv = rseg->lv;
288 : 0 : int r = 1;
289 : :
290 [ # # ]: 0 : if (vg_is_clustered(lv->vg)) {
291 : 0 : log_error("Volume Group %s of replicator %s is clustered",
292 : : lv->vg->name, lv->name);
293 : 0 : return 0;
294 : : }
295 : :
296 [ # # ]: 0 : if (dm_list_size(&lv->segments) != 1) {
297 : 0 : log_error("Replicator %s segment size %d != 1",
298 : : lv->name, dm_list_size(&lv->segments));
299 : 0 : return 0;
300 : : }
301 : :
302 [ # # ]: 0 : dm_list_iterate_items(rsite, &lv->rsites) {
303 [ # # ]: 0 : if (rsite->op_mode == DM_REPLICATOR_SYNC) {
304 [ # # ]: 0 : if (rsite->fall_behind_timeout) {
305 : 0 : log_error("Defined fall_behind_timeout="
306 : : "%d for sync replicator %s/%s.",
307 : : rsite->fall_behind_timeout, lv->name,
308 : : rsite->name);
309 : 0 : r = 0;
310 : : }
311 [ # # ]: 0 : if (rsite->fall_behind_ios) {
312 : 0 : log_error("Defined fall_behind_ios="
313 : : "%d for sync replicator %s/%s.",
314 : : rsite->fall_behind_ios, lv->name, rsite->name);
315 : 0 : r = 0;
316 : : }
317 [ # # ]: 0 : if (rsite->fall_behind_data) {
318 : 0 : log_error("Defined fall_behind_data="
319 : : "%" PRIu64 " for sync replicator %s/%s.",
320 : : rsite->fall_behind_data, lv->name, rsite->name);
321 : 0 : r = 0;
322 : : }
323 : : } else {
324 [ # # ][ # # ]: 0 : if (rsite->fall_behind_timeout && rsite->fall_behind_ios) {
325 : 0 : log_error("Defined fall_behind_timeout and"
326 : : " fall_behind_ios for async replicator %s/%s.",
327 : : lv->name, rsite->name);
328 : 0 : r = 0;
329 : : }
330 [ # # ][ # # ]: 0 : if (rsite->fall_behind_timeout && rsite->fall_behind_data) {
331 : 0 : log_error("Defined fall_behind_timeout and"
332 : : " fall_behind_data for async replicator %s/%s.",
333 : : lv->name, rsite->name);
334 : 0 : r = 0;
335 : : }
336 [ # # ][ # # ]: 0 : if (rsite->fall_behind_ios && rsite->fall_behind_data) {
337 : 0 : log_error("Defined fall_behind_ios and"
338 : : " fall_behind_data for async replicator %s/%s.",
339 : : lv->name, rsite->name);
340 : 0 : r = 0;
341 : : }
342 [ # # ][ # # ]: 0 : if (!rsite->fall_behind_ios && !rsite->fall_behind_data &&
[ # # ]
343 : 0 : !rsite->fall_behind_timeout) {
344 : 0 : log_error("fall_behind_timeout,"
345 : : " fall_behind_ios and fall_behind_data are"
346 : : " undefined for async replicator %s/%s.",
347 : : lv->name, rsite->name);
348 : 0 : r = 0;
349 : : }
350 : : }
351 [ # # ]: 0 : dm_list_iterate_items(rsiteb, &lv->rsites) {
352 [ # # ]: 0 : if (rsite == rsiteb)
353 : 0 : break;
354 [ # # ]: 0 : if (strcasecmp(rsite->name, rsiteb->name) == 0) {
355 : 0 : log_error("Duplicate site name"
356 : : " %s detected for replicator %s.",
357 : : rsite->name, lv->name);
358 : 0 : r = 0;
359 : : }
360 [ # # ][ # # ]: 0 : if ((rsite->vg_name && rsiteb->vg_name &&
[ # # ][ # # ]
[ # # ]
361 : 0 : strcasecmp(rsite->vg_name, rsiteb->vg_name) == 0) ||
362 : 0 : (!rsite->vg_name && !rsiteb->vg_name)) {
363 [ # # ]: 0 : log_error("Duplicate VG name"
364 : : " %s detected for replicator %s.",
365 : : (rsite->vg_name) ? rsite->vg_name : "<local>",
366 : : lv->name);
367 : 0 : r = 0;
368 : : }
369 [ # # ]: 0 : if (rsite->site_index == rsiteb->site_index) {
370 : 0 : log_error("Duplicate site index"
371 : : " %d detected for replicator %s/%s.",
372 : : rsite->site_index, lv->name,
373 : : rsite->name);
374 : 0 : r = 0;
375 : : }
376 [ # # ]: 0 : if (rsite->site_index > rseg->rsite_index_highest) {
377 : 0 : log_error("Site index %d > %d"
378 : : " (too high) for replicator %s/%s.",
379 : : rsite->site_index,
380 : : rseg->rsite_index_highest,
381 : : lv->name, rsite->name);
382 : 0 : r = 0;
383 : : }
384 : : }
385 : :
386 [ # # ]: 0 : dm_list_iterate_items(rdev, &rsite->rdevices) {
387 [ # # ]: 0 : dm_list_iterate_items(rdevb, &rsite->rdevices) {
388 [ # # ]: 0 : if (rdev == rdevb)
389 : 0 : break;
390 [ # # ][ # # ]: 0 : if (rdev->slog && (rdev->slog == rdevb->slog)) {
391 : 0 : log_error("Duplicate "
392 : : "sync log %s detected for "
393 : : "replicator %s.",
394 : : rdev->slog->name, lv->name);
395 : 0 : r = 0;
396 : : }
397 [ # # ]: 0 : if (strcasecmp(rdev->name, rdevb->name) == 0) {
398 : 0 : log_error("Duplicate "
399 : : "device name %s detected "
400 : : "for replicator %s.",
401 : : rdev->name, lv->name);
402 : 0 : r = 0;
403 : : }
404 [ # # ]: 0 : if (rdev->device_index == rdevb->device_index) {
405 : 0 : log_error("Duplicate "
406 : : "device index %" PRId64
407 : : " detected for replicator "
408 : : "%s/%s.", rdev->device_index,
409 : : lv->name, rsite->name);
410 : 0 : r = 0;
411 : : }
412 [ # # ]: 0 : if (rdev->device_index > rseg->rdevice_index_highest) {
413 : 0 : log_error("Device index %" PRIu64 " > %"
414 : : PRIu64 " (too high) for replicator %s/%s.",
415 : : rdev->device_index,
416 : : rseg->rdevice_index_highest,
417 : : lv->name, rsite->name);
418 : 0 : r = 0;
419 : : }
420 : : }
421 : : }
422 : : }
423 : :
424 : 0 : return r;
425 : : }
426 : :
427 : : /**
428 : : * Is this segment part of active replicator
429 : : */
430 : 0 : int lv_is_active_replicator_dev(const struct logical_volume *lv)
431 : : {
432 [ # # ][ # # ]: 0 : return ((lv->status & REPLICATOR) &&
[ # # ][ # # ]
433 : 0 : lv->rdevice &&
434 : 0 : lv->rdevice->rsite &&
435 : 0 : lv->rdevice->rsite->state == REPLICATOR_STATE_ACTIVE);
436 : : }
437 : :
438 : : /**
439 : : * Is this LV replicator control device
440 : : */
441 : 0 : int lv_is_replicator(const struct logical_volume *lv)
442 : : {
443 [ # # # # # : 0 : return ((lv->status & REPLICATOR) &&
# ]
444 : 0 : !dm_list_empty(&lv->segments) &&
445 : 0 : seg_is_replicator(first_seg(lv)));
446 : : }
447 : :
448 : : /**
449 : : * Is this LV replicator device
450 : : */
451 : 0 : int lv_is_replicator_dev(const struct logical_volume *lv)
452 : : {
453 [ # # # # # : 0 : return ((lv->status & REPLICATOR) &&
# ]
454 : 0 : !dm_list_empty(&lv->segments) &&
455 : 0 : seg_is_replicator_dev(first_seg(lv)));
456 : : }
457 : :
458 : : /**
459 : : * Is this LV replicated origin lv
460 : : */
461 : 0 : int lv_is_rimage(const struct logical_volume *lv)
462 : : {
463 [ # # ][ # # ]: 0 : return (lv->rdevice && lv->rdevice->lv == lv);
464 : : }
465 : :
466 : : /**
467 : : * Is this LV rlog
468 : : */
469 : 0 : int lv_is_rlog(const struct logical_volume *lv)
470 : : {
471 : 0 : return (lv->status & REPLICATOR_LOG);
472 : : }
473 : :
474 : : /**
475 : : * Is this LV sync log
476 : : */
477 : 0 : int lv_is_slog(const struct logical_volume *lv)
478 : : {
479 [ # # ][ # # ]: 0 : return (lv->rdevice && lv->rdevice->slog == lv);
480 : : }
481 : :
482 : : /**
483 : : * Returns first replicator-dev in site in case the LV is replicator-dev,
484 : : * NULL otherwise
485 : : */
486 : 0 : struct logical_volume *first_replicator_dev(const struct logical_volume *lv)
487 : : {
488 : : struct replicator_device *rdev;
489 : : struct replicator_site *rsite;
490 : :
491 [ # # ]: 0 : if (lv_is_replicator_dev(lv))
492 [ # # ]: 0 : dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
493 [ # # ]: 0 : dm_list_iterate_items(rdev, &rsite->rdevices)
494 : 0 : return rdev->replicator_dev->lv;
495 : 0 : break;
496 : : }
497 : :
498 : 0 : return NULL;
499 : : }
500 : :
501 : : /**
502 : : * Add VG to sorted VGs list
503 : : *
504 : : * Maintain the alphabeticaly ordered list, avoid duplications.
505 : : *
506 : : * \return
507 : : * Returns newly created or already present vgs_list entry.
508 : : * Returns NULL in error case.
509 : : */
510 : 0 : struct vgs_list *vgs_list_add(struct dm_pool *mem,
511 : : struct dm_list *list,
512 : : const char *vg_name,
513 : : const char *vgid,
514 : : uint32_t flags)
515 : : {
516 : : struct vgs_list *vgsl, *ins;
517 : :
518 : : /* Is already in the list ? */
519 [ # # ]: 0 : if ((vgsl = vgs_list_lookup(list, vg_name)))
520 : 0 : return vgsl;
521 : :
522 [ # # ]: 0 : if (!(vgsl = dm_pool_alloc(mem, sizeof(*vgsl)))) {
523 : 0 : log_error("Allocation of vgs_list failed.");
524 : 0 : return NULL;
525 : : }
526 : :
527 [ # # ]: 0 : if (!(vgsl->vg_name = dm_pool_strdup(mem, vg_name))) {
528 : 0 : dm_pool_free(mem, vgsl);
529 : 0 : log_error("Allocation of vg_name failed.");
530 : 0 : return NULL;
531 : : }
532 : :
533 [ # # # # ]: 0 : if (vgid &&
534 : 0 : !(vgsl->vgid = dm_pool_strdup(mem, vgid))) {
535 : 0 : dm_pool_free(mem, vgsl);
536 : 0 : log_error("Allocation of vgid failed.");
537 : 0 : return NULL;
538 : : } else
539 : 0 : vgsl->vgid = NULL;
540 : :
541 : 0 : vgsl->flags = flags;
542 : 0 : vgsl->vg = NULL;
543 [ # # ]: 0 : dm_list_iterate_items(ins, list)
544 [ # # ]: 0 : if (strcmp(vg_name, ins->vg_name) < 0) {
545 : 0 : list = &ins->list;
546 : 0 : break;
547 : : }
548 : :
549 : 0 : dm_list_add(list, &vgsl->list);
550 : :
551 : 0 : return vgsl;
552 : : }
553 : :
554 : : /**
555 : : * Find vgs_list with given vg_name in VGs list.
556 : : *
557 : : * \param list
558 : : * List of vgs_list elements.
559 : : * \param vg_name
560 : : * Name of VG to be found.
561 : : * \return
562 : : * Returns vgs_list element with VG if vg_name is found.
563 : : * Returns NULL if vg_name is not found.
564 : : */
565 : 0 : struct vgs_list *vgs_list_lookup(struct dm_list *l, const char *vg_name)
566 : : {
567 : : struct vgs_list *vgsl;
568 : :
569 [ # # ]: 0 : dm_list_iterate_items(vgsl, l)
570 [ # # ]: 0 : if (!strcmp(vg_name, vgsl->vg_name))
571 : 0 : return vgsl;
572 : :
573 : 0 : return NULL;
574 : : }
575 : :
576 : : /**
577 : : * Read and lock multiple VGs stored in vgs_list alphabeticaly.
578 : : * On the success list is spliced to vgs_vg->vg vgs list and left
579 : : * UNINITIALIZED and shall NOT be used until calling vgs_list_release().
580 : : *
581 : : * \param list
582 : : * Contains list of vgs_list entries.
583 : : * \param vgs_vg
584 : : * Contains master VGs list.
585 : : *
586 : : * \return
587 : : * Returns 1 if all VG in vgs_list are correctly openned and locked.
588 : : * Returns 0 if there is some problem with any VG.
589 : : *
590 : : * (Needed to allow support for FAILED_INCONSISTENT)
591 : : */
592 : 0 : int vgs_list_read(struct cmd_context *cmd, struct dm_list *list,
593 : : struct vgs_list *vgs_vg)
594 : : {
595 : : struct vgs_list *vgsl;
596 : :
597 : : /* Iterate through alphabeticaly ordered VGs list */
598 [ # # ]: 0 : dm_list_iterate_items(vgsl, list) {
599 : 0 : vgsl->vg = vg_read(cmd, vgsl->vg_name, vgsl->vgid, vgsl->flags);
600 [ # # ]: 0 : if (vg_read_error(vgsl->vg)) {
601 : 0 : log_debug("Failed to vg_read %s", vgsl->vg_name);
602 : 0 : return 0;
603 : : }
604 : : }
605 : :
606 : 0 : dm_list_init(&vgs_vg->vg->vgs);
607 : 0 : dm_list_splice(list, &vgs_vg->vg->vgs);
608 : :
609 : 0 : return 1;
610 : : }
611 : :
612 : : /**
613 : : * Release opened and locked VGs from list.
614 : : * List is spliced back from vgs_vg to list.
615 : : *
616 : : * \param list
617 : : * Contains list of vgs_list entries.
618 : : * \param vgs_vg
619 : : * Contains master VG with vgs list of active VGs.
620 : : */
621 : 0 : void vgs_list_release(struct dm_list *list, struct vgs_list *vgs_vg)
622 : : {
623 : : struct vgs_list *vgsl;
624 : :
625 [ # # ]: 0 : if (!vg_read_error(vgs_vg->vg)) {
626 : 0 : dm_list_init(list);
627 : 0 : dm_list_splice(&vgs_vg->vg->vgs, list);
628 : : }
629 : :
630 [ # # ]: 0 : dm_list_iterate_back_items(vgsl, list) {
631 [ # # ]: 0 : if (vg_read_error(vgsl->vg))
632 : 0 : vg_release(vgsl->vg);
633 : : else
634 : 0 : unlock_and_release_vg(vgsl->vg->cmd, vgsl->vg, vgsl->vg_name);
635 : 0 : vgsl->vg = NULL;
636 : : }
637 : 0 : }
638 : :
639 : : /**
640 : : * Find all needed remote VGs for processing given LV.
641 : : * Missing VGs are added to VG's vgs list.
642 : : */
643 : 0 : int find_replicator_vgs(struct logical_volume *lv)
644 : : {
645 : : struct replicator_site *rsite;
646 : 0 : int ret = 1;
647 : :
648 [ # # ]: 0 : if (!lv_is_replicator_dev(lv))
649 : 0 : return 1;
650 : :
651 [ # # ]: 0 : dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
652 [ # # # # ]: 0 : if (!rsite->vg_name ||
653 : 0 : vgs_list_lookup(&lv->vg->vgs, rsite->vg_name))
654 : 0 : continue;
655 : 0 : ret = 0;
656 : : /* Using cmd memory pool for list allocation */
657 [ # # ]: 0 : if (!vgs_list_add(lv->vg->cmd->mem, &lv->vg->vgs,
658 : : rsite->vg_name, NULL, 0)) {
659 : 0 : lv->vg->missing_vgs = 0; /* do not retry */
660 : 0 : stack;
661 : 0 : break;
662 : : }
663 : :
664 : 0 : log_debug("VG: %s added as missing.", rsite->vg_name);
665 : 0 : lv->vg->missing_vgs++;
666 : : }
667 : :
668 : 0 : return ret;
669 : : }
670 : :
671 : : /**
672 : : * Resolve all remote VGs from replicators' sites
673 : : * This function is used in activation context and needs all VGs already locked
674 : : */
675 : 0 : int lv_read_replicator_vgs(struct logical_volume *lv)
676 : : {
677 : : struct replicator_device *rdev;
678 : : struct replicator_site *rsite;
679 : : struct volume_group *vg;
680 : :
681 [ # # ]: 0 : if (!lv_is_replicator_dev(lv))
682 : 0 : return 1;
683 : :
684 [ # # ]: 0 : dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
685 [ # # ]: 0 : if (!rsite->vg_name)
686 : 0 : continue;
687 : 0 : vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, 0); // READ_WITHOUT_LOCK
688 [ # # ]: 0 : if (vg_read_error(vg)) {
689 : 0 : log_error("Unable to read volume group %s",
690 : : rsite->vg_name);
691 : 0 : goto bad;
692 : : }
693 : 0 : rsite->vg = vg;
694 : : /* CHECKME: handling missing LVs needs to be better */
695 [ # # ]: 0 : dm_list_iterate_items(rdev, &rsite->rdevices)
696 [ # # ]: 0 : if (!(rdev->lv = find_lv(vg, rdev->name))) {
697 : 0 : log_error("Unable to find %s in volume group %s",
698 : : rdev->name, rsite->vg_name);
699 : 0 : goto bad;
700 : : }
701 : : }
702 : :
703 : 0 : return 1;
704 : : bad:
705 : 0 : lv_release_replicator_vgs(lv);
706 : 0 : return 0;
707 : : }
708 : :
709 : : /**
710 : : * Release all VG resources taken by replicators' sites
711 : : * This function is used in activation context and needs all VGs already locked
712 : : */
713 : 0 : void lv_release_replicator_vgs(struct logical_volume *lv)
714 : : {
715 : : struct replicator_site *rsite;
716 : :
717 [ # # ]: 0 : if (!lv_is_replicator_dev(lv))
718 : 0 : return;
719 : :
720 [ # # ]: 0 : dm_list_iterate_back_items(rsite, &first_seg(lv)->replicator->rsites)
721 [ # # ][ # # ]: 0 : if (rsite->vg_name && rsite->vg) {
722 : 0 : vg_release(rsite->vg);
723 : 0 : rsite->vg = NULL;
724 : : }
725 : : }
726 : :
727 : 0 : static int _write_replicator_header(struct cmd_context *cmd, struct logical_volume *lv)
728 : : {
729 : 0 : return 0;
730 : : }
731 : :
732 : : /*
733 : : * Initialize log contents
734 : : *
735 : : * log_name = "mirror log", "replicator log"
736 : : */
737 : 0 : static int _init_log(struct cmd_context *cmd,
738 : : struct logical_volume *log_lv, int in_sync,
739 : : struct dm_list *tags, int remove_on_failure,
740 : : const char *log_name,
741 : : int (*write_header) (struct cmd_context *cmd,
742 : : struct logical_volume *lv))
743 : : {
744 : : struct str_list *sl;
745 : : struct lvinfo info;
746 : 0 : uint64_t orig_status = log_lv->status;
747 : 0 : int was_active = 0;
748 : :
749 [ # # ][ # # ]: 0 : if (!activation() && in_sync) {
750 : 0 : log_error("Aborting. Unable to create in-sync %s "
751 : : "while activation is disabled.", log_name);
752 : 0 : return 0;
753 : : }
754 : :
755 : : /* If the LV is active, deactivate it first. */
756 [ # # ][ # # ]: 0 : if (lv_info(cmd, log_lv, &info, 0, 0) && info.exists) {
757 [ # # ][ # # ]: 0 : (void)deactivate_lv(cmd, log_lv);
758 : : /*
759 : : * FIXME: workaround to fail early
760 : : * Ensure that log is really deactivated because deactivate_lv
761 : : * on cluster do not fail if there is log_lv with different UUID.
762 : : */
763 [ # # ][ # # ]: 0 : if (lv_info(cmd, log_lv, &info, 0, 0) && info.exists) {
764 : 0 : log_error("Aborting. Unable to deactivate %s.",
765 : : log_name);
766 : 0 : goto revert_new_lv;
767 : : }
768 : 0 : was_active = 1;
769 : : }
770 : :
771 : : /* Temporary make it visible for set_lv() */
772 : 0 : lv_set_visible(log_lv);
773 : :
774 : : /* Temporary tag mirror log for activation */
775 [ # # ]: 0 : dm_list_iterate_items(sl, tags)
776 [ # # ]: 0 : if (!str_list_add(cmd->mem, &log_lv->tags, sl->str)) {
777 : 0 : log_error("Aborting. Unable to tag %s.", log_name);
778 : 0 : goto activate_lv;
779 : : }
780 : :
781 : : /* store mirror log on disk(s) */
782 [ # # ][ # # ]: 0 : if (!vg_write(log_lv->vg) || !vg_commit(log_lv->vg))
783 : : goto activate_lv;
784 : :
785 : 0 : backup(log_lv->vg);
786 : :
787 [ # # # # ]: 0 : if (!activate_lv(cmd, log_lv)) {
[ # # ]
788 : 0 : log_error("Aborting. Failed to activate %s.", log_name);
789 : 0 : goto revert_new_lv;
790 : : }
791 : :
792 : : /* Remove the temporary tags */
793 [ # # ]: 0 : dm_list_iterate_items(sl, tags)
794 [ # # ]: 0 : if (!str_list_del(&log_lv->tags, sl->str))
795 : 0 : log_error("Failed to remove tag %s from %s.",
796 : : log_name, sl->str);
797 : :
798 [ # # ][ # # ]: 0 : if (activation() && !set_lv(cmd, log_lv, log_lv->size,
[ # # ]
799 : : in_sync ? -1 : 0)) {
800 : 0 : log_error("Aborting. Failed to wipe %s.", log_name);
801 : 0 : goto deactivate_and_revert_new_lv;
802 : : }
803 : :
804 [ # # ][ # # ]: 0 : if (activation() && !write_header(cmd, log_lv)) { /* FIXME */
805 : 0 : log_error("Aborting. Failed to write %s header.", log_name);
806 : 0 : goto deactivate_and_revert_new_lv;
807 : : }
808 : :
809 [ # # ][ # # ]: 0 : if (!deactivate_lv(cmd, log_lv)) {
[ # # ]
810 : 0 : log_error("Aborting. Failed to deactivate %s. "
811 : : "Manual intervention required.", log_name);
812 : 0 : return 0;
813 : : }
814 : :
815 : 0 : lv_set_hidden(log_lv);
816 : :
817 [ # # # # ]: 0 : if (was_active && !activate_lv(cmd, log_lv))
[ # # ][ # # ]
818 : 0 : return_0;
819 : :
820 : 0 : return 1;
821 : :
822 : : deactivate_and_revert_new_lv:
823 [ # # ][ # # ]: 0 : if (!deactivate_lv(cmd, log_lv)) {
[ # # ]
824 : 0 : log_error("Unable to deactivate %s LV. "
825 : : "Manual intervention required.", log_name);
826 : 0 : return 0;
827 : : }
828 : :
829 : : revert_new_lv:
830 : 0 : log_lv->status = orig_status;
831 : :
832 [ # # ]: 0 : dm_list_iterate_items(sl, tags)
833 [ # # ]: 0 : if (!str_list_del(&log_lv->tags, sl->str))
834 : 0 : log_error("Failed to remove tag %s from %s.",
835 : : log_name, sl->str);
836 : :
837 [ # # ][ # # ]: 0 : if (remove_on_failure && !lv_remove(log_lv)) {
838 : 0 : log_error("Manual intervention may be required to remove "
839 : : "abandoned log LV before retrying.");
840 : 0 : return 0;
841 : : }
842 : :
843 [ # # ][ # # ]: 0 : if (!vg_write(log_lv->vg) || !vg_commit(log_lv->vg))
844 : 0 : log_error("Manual intervention may be required to "
845 : : "remove/restore abandoned log LV before retrying.");
846 : : else
847 : 0 : backup(log_lv->vg);
848 : :
849 : : activate_lv:
850 [ # # ][ # # ]: 0 : if (was_active && !remove_on_failure && !activate_lv(cmd, log_lv))
[ # # ][ # # ]
[ # # ]
851 : 0 : return_0;
852 : :
853 : 0 : return 0;
854 : : }
855 : :
856 : 0 : static int _init_replicator_log(struct cmd_context *cmd,
857 : : struct logical_volume *log_lv, int in_sync,
858 : : struct dm_list *tags, int remove_on_failure)
859 : : {
860 [ # # ]: 0 : if (!_init_log(cmd, log_lv, in_sync, tags, remove_on_failure,
861 : : "replicator log", _write_replicator_header))
862 : 0 : return_0;
863 : :
864 : 0 : return 1;
865 : : }
866 : :
867 : 0 : static int _init_replicator_sync_log(struct cmd_context *cmd,
868 : : struct logical_volume *log_lv, int in_sync,
869 : : struct dm_list *tags, int remove_on_failure)
870 : : {
871 [ # # ]: 0 : if (!_init_log(cmd, log_lv, in_sync, tags, remove_on_failure,
872 : : "sync log", _write_replicator_header))
873 : 0 : return_0;
874 : :
875 : 0 : return 1;
876 : : }
877 : :
878 : : //!_init_repliator_log(lv->vg->cmd, first_seg(lv)->log_lv,
879 : : // 1, &lv->tags, 0)) {
880 : :
881 : : /* can be shared */
882 : 0 : static struct logical_volume *_create_log(struct logical_volume *lv,
883 : : struct alloc_handle *ah,
884 : : alloc_policy_t alloc,
885 : : const char *lv_name,
886 : : const char *suffix)
887 : : {
888 : : struct logical_volume *log_lv;
889 : : char *log_name;
890 : : size_t len;
891 : :
892 : 0 : len = strlen(lv_name) + 32;
893 : 0 : if (!(log_name = alloca(len))) {
894 : : log_error("log_name allocation failed.");
895 : : return NULL;
896 : : }
897 : :
898 [ # # ]: 0 : if (dm_snprintf(log_name, len, "%s%s", lv_name, suffix) < 0) {
899 : 0 : log_error("log_name allocation failed.");
900 : 0 : return NULL;
901 : : }
902 : :
903 [ # # ]: 0 : if (!(log_lv = lv_create_empty(log_name, NULL,
904 : : VISIBLE_LV | LVM_READ | LVM_WRITE,
905 : : alloc, lv->vg)))
906 : 0 : return_NULL;
907 : :
908 [ # # ]: 0 : if (!lv_add_log_segment(ah, 0, log_lv, MIRROR_LOG))
909 : 0 : return_NULL;
910 : :
911 : 0 : return log_lv;
912 : : }
913 : :
914 : 0 : static struct logical_volume *_set_up_replicator_log(struct cmd_context *cmd,
915 : : struct alloc_handle *ah,
916 : : struct logical_volume *lv,
917 : : uint32_t log_size __attribute((unused)),
918 : : alloc_policy_t alloc,
919 : : int in_sync)
920 : : {
921 : : struct logical_volume *log_lv;
922 : : const char *suffix, *c;
923 : : char *lv_name;
924 : : size_t len;
925 : : struct lv_segment *seg;
926 : :
927 : 0 : init_mirror_in_sync(in_sync);
928 : :
929 : : /* Replicator log name is lv_name + suffix, determined as the following:
930 : : * 1. suffix is:
931 : : * o "_rlog" for the original replicator LV.
932 : : * o "_rlogtmp_%d" for temporary mirror LV,
933 : : * 2. lv_name is:
934 : : * o lv->name, if the log is temporary
935 : : * o otherwise, the top-level LV name
936 : : */
937 : 0 : seg = first_seg(lv);
938 [ # # # # ]: 0 : if (seg_type(seg, 0) == AREA_LV &&
939 : 0 : strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER)) {
940 : 0 : lv_name = lv->name;
941 : 0 : suffix = "_rlogtmp_%d";
942 [ # # ]: 0 : } else if ((c = strstr(lv->name, MIRROR_SYNC_LAYER))) {
943 : 0 : len = (size_t)(c - lv->name + 1);
944 [ # # ]: 0 : if (!(lv_name = alloca(len)) ||
945 : 0 : !dm_snprintf(lv_name, len, "%s", lv->name)) {
946 : 0 : log_error("replicator log name allocation failed");
947 : 0 : return 0;
948 : : }
949 : 0 : suffix = "_rlog";
950 : : } else {
951 : 0 : lv_name = lv->name;
952 : 0 : suffix = "_rlog";
953 : : }
954 : :
955 [ # # ]: 0 : if (!(log_lv = _create_log(lv, ah, alloc, lv_name, suffix))) {
956 : 0 : log_error("Failed to create replicator log.");
957 : 0 : return NULL;
958 : : }
959 : :
960 [ # # ]: 0 : if (!_init_replicator_log(cmd, log_lv, in_sync, &lv->tags, 1)) {
961 : 0 : log_error("Failed to initialise replicator log.");
962 : 0 : return NULL;
963 : : }
964 : :
965 : 0 : return log_lv;
966 : : }
967 : :
968 : :
969 : 0 : int add_replicator_log(struct cmd_context *cmd, struct logical_volume *lv,
970 : : uint32_t log_size, struct dm_list *allocatable_pvs,
971 : : alloc_policy_t alloc)
972 : : {
973 : : struct alloc_handle *ah;
974 : : const struct segment_type *segtype;
975 : : struct dm_list *parallel_areas;
976 : : float sync_percent;
977 : : percent_range_t percent_range;
978 : : int in_sync;
979 : : struct logical_volume *log_lv;
980 : : struct lvinfo info;
981 : 0 : int r = 0;
982 : :
983 : 0 : log_error("ADDREPLICATORLOG size %d", log_size);
984 : :
985 [ # # ]: 0 : if (dm_list_size(&lv->segments) != 1) {
986 : 0 : log_error("Multiple-segment replicator log is not supported");
987 : 0 : return 0;
988 : : }
989 : :
990 : : /*
991 : : * We are unable to convert the log of inactive cluster replictors
992 : : */
993 [ # # ][ # # ]: 0 : if (vg_is_clustered(lv->vg) &&
[ # # ]
994 : : !(lv_info(cmd, lv, &info, 0, 0) && info.exists)) {
995 : 0 : log_error("Unable to convert the log of inactive "
996 : : "cluster mirror %s", lv->name);
997 : 0 : return 0;
998 : : }
999 : :
1000 [ # # ]: 0 : if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv, 0)))
1001 : 0 : return_0;
1002 : :
1003 [ # # ]: 0 : if (!(segtype = get_segtype_from_string(cmd, "replicator")))
1004 : 0 : return_0;
1005 : :
1006 [ # # ]: 0 : if (activation() && segtype->ops->target_present &&
[ # # # # ]
1007 : 0 : !segtype->ops->target_present(cmd, NULL, NULL)) {
1008 : 0 : log_error("%s: Required device-mapper target(s) not "
1009 : : "detected in your kernel", segtype->name);
1010 : 0 : return 0;
1011 : : }
1012 : :
1013 : : /* allocate destination extents */
1014 : 0 : ah = allocate_extents(lv->vg, NULL, segtype,
1015 : : 0, 0, 1, log_size, 0,
1016 : : allocatable_pvs, alloc, parallel_areas);
1017 [ # # ]: 0 : if (!ah) {
1018 : 0 : log_error("Unable to allocate extents for replicator log.");
1019 : 0 : return 0;
1020 : : }
1021 : :
1022 : : /* check sync status */
1023 : : // if (lv_mirror_percent(cmd, lv, 0, &sync_percent, &percent_range,
1024 : : // NULL) &&
1025 : : // (percent_range == PERCENT_100))
1026 : : // in_sync = 1;
1027 : : // else
1028 : 0 : in_sync = 0;
1029 : :
1030 [ # # ]: 0 : if (!(log_lv = _set_up_replicator_log(cmd, ah, lv, log_size,
1031 : : alloc, in_sync)))
1032 : 0 : goto_out;
1033 : :
1034 [ # # ]: 0 : if (!attach_mirror_log(first_seg(lv), log_lv))
1035 : 0 : goto_out;
1036 : :
1037 : 0 : r = 1;
1038 : : out:
1039 : 0 : alloc_destroy(ah);
1040 : 0 : return r;
1041 : : }
|