2 * Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
4 * This file is part of LVM2.
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.
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
19 #include "toolcontext.h"
21 /* Add lv as replicator_dev device */
22 int replicator_dev_add_rimage(struct replicator_device *rdev,
23 struct logical_volume *lv)
28 if (lv_is_rimage(lv)) {
29 log_error("Logical volume %s is already part of other "
30 "replicator.", lv->name);
35 log_error("Logical volume %s can not be attached to an "
36 "already defined replicator device", lv->name);
44 return add_seg_to_segs_using_this_lv(lv, rdev->replicator_dev);
47 /* Remove lv from replicator_dev device */
48 struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev)
50 struct logical_volume *lv;
52 if (!rdev || !rdev->lv)
56 if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
59 /* FIXME: - check for site references */
67 int replicator_dev_add_slog(struct replicator_device *rdev,
68 struct logical_volume *slog)
74 log_error("Replicator device in site %s already has sync log.",
80 log_error("Sync log %s is already used by replicator %s.",
81 slog->name, slog->rdevice->rsite->replicator->name);
89 return add_seg_to_segs_using_this_lv(slog, rdev->replicator_dev);
92 struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev)
94 struct logical_volume *lv;
101 log_error("Replicator device in site %s does not have sync log.",
106 if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
116 int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
117 struct lv_segment *replicator_dev_seg)
122 if (!(replicator_lv->status & REPLICATOR)) {
123 dm_list_init(&replicator_lv->rsites);
124 lv_set_hidden(replicator_lv);
125 replicator_lv->status |= REPLICATOR;
128 if (!replicator_dev_seg)
131 if (replicator_dev_seg->replicator) {
132 log_error("Replicator device %s is already part of replicator.",
133 replicator_dev_seg->lv->name);
137 replicator_dev_seg->replicator = replicator_lv;
139 return add_seg_to_segs_using_this_lv(replicator_lv, replicator_dev_seg);
143 * Returns rimage ?? lv upon succeful detach of device
144 * entire LV entry should be removed by this crootall ??
146 struct logical_volume *replicator_remove_replicator_dev(struct lv_segment *replicator_dev_seg)
148 struct logical_volume *lv = NULL;
150 log_error("FIXME: not implemented.");
152 /* FIXME: - this is going to be complex.... */
153 if (!replicator_dev_seg)
156 /* if slog or rimage - exit */
158 if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
161 replicator_seg->rlog_lv = NULL;
162 lv->status &= ~REPLICATOR_LOG;
169 int replicator_add_rlog(struct lv_segment *replicator_seg,
170 struct logical_volume *rlog_lv)
175 if (rlog_lv->status & REPLICATOR_LOG) {
176 log_error("Rlog device %s is already used.", rlog_lv->name);
180 lv_set_hidden(rlog_lv);
181 rlog_lv->status |= REPLICATOR_LOG;
182 replicator_seg->rlog_lv = rlog_lv;
184 return add_seg_to_segs_using_this_lv(rlog_lv, replicator_seg);
187 struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg)
189 struct logical_volume *lv;
194 if (!(lv = replicator_seg->rlog_lv)) {
195 log_error("Replog segment %s does not have rlog.",
196 replicator_seg->lv->name);
200 if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
203 replicator_seg->rlog_lv = NULL;
204 lv->status &= ~REPLICATOR_LOG;
213 * Create new LV to pretend the original LV
214 * this target will have a 'replicator' segment
216 int lv_add_replicator(struct logical_volume *origin, const char *rep_suffix)
218 struct logical_volume *rep_lv;
222 if (!(name = strstr(origin->name, rep_suffix))) {
223 log_error("Failed to find replicator suffix %s in LV name %s",
224 rep_suffix, origin->name);
227 slen = (size_t)(name - origin->name);
228 name = alloca(slen + 1);
229 memcpy(name, origin->name, slen);
232 if ((rep_lv = find_lv(origin->vg, name))) {
233 rep_lv->status |= VIRTUAL;
237 if (!(rep_lv = lv_create_empty(name, &origin->lvid,
238 LVM_READ | LVM_WRITE | VISIBLE_LV,
239 ALLOC_INHERIT, origin->vg)))
242 if (!lv_add_virtual_segment(rep_lv, 0, origin->le_count,
243 get_segtype_from_string(origin->vg->cmd,
247 rep_lv->status |= VIRTUAL;
251 int lv_remove_replicator(struct logical_volume *lv)
258 * Check all replicator structures:
259 * only non-clustered VG for Replicator
260 * only one segment in replicator LV
261 * site has correct combination of operation_mode parameters
262 * site and related devices have correct index numbers
263 * duplicate site names, site indexes, device names, device indexes
265 int check_replicator_segment(const struct lv_segment *rseg)
267 struct replicator_site *rsite, *rsiteb;
268 struct replicator_device *rdev, *rdevb;
269 struct logical_volume *lv = rseg->lv;
272 if (vg_is_clustered(lv->vg)) {
273 log_error("Volume Group %s of replicator %s is clustered",
274 lv->vg->name, lv->name);
278 if (dm_list_size(&lv->segments) != 1) {
279 log_error("Replicator %s segment size %d != 1",
280 lv->name, dm_list_size(&lv->segments));
284 dm_list_iterate_items(rsite, &lv->rsites) {
285 if (rsite->op_mode == DM_REPLICATOR_SYNC) {
286 if (rsite->fall_behind_timeout) {
287 log_error("Defined fall_behind_timeout="
288 "%d for sync replicator %s/%s.",
289 rsite->fall_behind_timeout, lv->name,
293 if (rsite->fall_behind_ios) {
294 log_error("Defined fall_behind_ios="
295 "%d for sync replicator %s/%s.",
296 rsite->fall_behind_ios, lv->name, rsite->name);
299 if (rsite->fall_behind_data) {
300 log_error("Defined fall_behind_data="
301 "%" PRIu64 " for sync replicator %s/%s.",
302 rsite->fall_behind_data, lv->name, rsite->name);
306 if (rsite->fall_behind_timeout && rsite->fall_behind_ios) {
307 log_error("Defined fall_behind_timeout and"
308 " fall_behind_ios for async replicator %s/%s.",
309 lv->name, rsite->name);
312 if (rsite->fall_behind_timeout && rsite->fall_behind_data) {
313 log_error("Defined fall_behind_timeout and"
314 " fall_behind_data for async replicator %s/%s.",
315 lv->name, rsite->name);
318 if (rsite->fall_behind_ios && rsite->fall_behind_data) {
319 log_error("Defined fall_behind_ios and"
320 " fall_behind_data for async replicator %s/%s.",
321 lv->name, rsite->name);
324 if (!rsite->fall_behind_ios &&
325 !rsite->fall_behind_data &&
326 !rsite->fall_behind_timeout) {
327 log_error("fall_behind_timeout,"
328 " fall_behind_ios and fall_behind_data are"
329 " undefined for async replicator %s/%s.",
330 lv->name, rsite->name);
334 dm_list_iterate_items(rsiteb, &lv->rsites) {
337 if (strcasecmp(rsite->name, rsiteb->name) == 0) {
338 log_error("Duplicate site name "
339 "%s detected for replicator %s.",
340 rsite->name, lv->name);
343 if ((rsite->vg_name && rsiteb->vg_name &&
344 strcasecmp(rsite->vg_name, rsiteb->vg_name) == 0) ||
345 (!rsite->vg_name && !rsiteb->vg_name)) {
346 log_error("Duplicate VG name "
347 "%s detected for replicator %s.",
348 (rsite->vg_name) ? rsite->vg_name : "<local>",
352 if (rsite->site_index == rsiteb->site_index) {
353 log_error("Duplicate site index %d detected "
354 "for replicator site %s/%s.",
355 rsite->site_index, lv->name,
359 if (rsite->site_index > rseg->rsite_index_highest) {
360 log_error("Site index %d > %d (too high) "
361 "for replicator site %s/%s.",
363 rseg->rsite_index_highest,
364 lv->name, rsite->name);
369 dm_list_iterate_items(rdev, &rsite->rdevices) {
370 dm_list_iterate_items(rdevb, &rsite->rdevices) {
373 if (rdev->slog && (rdev->slog == rdevb->slog)) {
374 log_error("Duplicate sync log %s "
375 "detected for replicator %s.",
376 rdev->slog->name, lv->name);
379 if (strcasecmp(rdev->name, rdevb->name) == 0) {
380 log_error("Duplicate device name %s "
381 "detected for replicator %s.",
382 rdev->name, lv->name);
385 if (rdev->device_index == rdevb->device_index) {
386 log_error("Duplicate device index %"
387 PRId64 " detected for "
388 "replicator site %s/%s.",
390 lv->name, rsite->name);
393 if (rdev->device_index > rseg->rdevice_index_highest) {
394 log_error("Device index %" PRIu64
395 " > %" PRIu64 " (too high) "
396 "for replicator site %s/%s.",
398 rseg->rdevice_index_highest,
399 lv->name, rsite->name);
410 * Is this segment part of active replicator
412 int lv_is_active_replicator_dev(const struct logical_volume *lv)
414 return ((lv->status & REPLICATOR) &&
416 lv->rdevice->rsite &&
417 lv->rdevice->rsite->state == REPLICATOR_STATE_ACTIVE);
421 * Is this LV replicator control device
423 int lv_is_replicator(const struct logical_volume *lv)
425 return ((lv->status & REPLICATOR) &&
426 !dm_list_empty(&lv->segments) &&
427 seg_is_replicator(first_seg(lv)));
431 * Is this LV replicator device
433 int lv_is_replicator_dev(const struct logical_volume *lv)
435 return ((lv->status & REPLICATOR) &&
436 !dm_list_empty(&lv->segments) &&
437 seg_is_replicator_dev(first_seg(lv)));
441 * Is this LV replicated origin lv
443 int lv_is_rimage(const struct logical_volume *lv)
445 return (lv->rdevice && lv->rdevice->lv == lv);
451 int lv_is_rlog(const struct logical_volume *lv)
453 return (lv->status & REPLICATOR_LOG);
457 * Is this LV sync log
459 int lv_is_slog(const struct logical_volume *lv)
461 return (lv->rdevice && lv->rdevice->slog == lv);
465 * Returns first replicator-dev in site in case the LV is replicator-dev,
468 struct logical_volume *first_replicator_dev(const struct logical_volume *lv)
470 struct replicator_device *rdev;
471 struct replicator_site *rsite;
473 if (lv_is_replicator_dev(lv))
474 dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
475 dm_list_iterate_items(rdev, &rsite->rdevices)
476 return rdev->replicator_dev->lv;
484 * Add VG open parameters to sorted cmd_vg list.
486 * Maintain the alphabeticaly ordered list, avoid duplications.
488 * \return Returns newly created or already present cmd_vg entry,
489 * or NULL in error case.
491 struct cmd_vg *cmd_vg_add(struct dm_pool *mem, struct dm_list *cmd_vgs,
492 const char *vg_name, const char *vgid,
495 struct cmd_vg *cvl, *ins;
497 if (!vg_name && !vgid) {
498 log_error("Either vg_name or vgid must be set.");
502 /* Is it already in the list ? */
503 if ((cvl = cmd_vg_lookup(cmd_vgs, vg_name, vgid)))
506 if (!(cvl = dm_pool_zalloc(mem, sizeof(*cvl)))) {
507 log_error("Allocation of cmd_vg failed.");
511 if (vg_name && !(cvl->vg_name = dm_pool_strdup(mem, vg_name))) {
512 dm_pool_free(mem, cvl);
513 log_error("Allocation of vg_name failed.");
517 if (vgid && !(cvl->vgid = dm_pool_strdup(mem, vgid))) {
518 dm_pool_free(mem, cvl);
519 log_error("Allocation of vgid failed.");
526 dm_list_iterate_items(ins, cmd_vgs)
527 if (strcmp(vg_name, ins->vg_name) < 0) {
528 cmd_vgs = &ins->list; /* new position */
532 dm_list_add(cmd_vgs, &cvl->list);
538 * Find cmd_vg with given vg_name in cmd_vgs list.
540 * \param cmd_vgs List of cmd_vg entries.
542 * \param vg_name Name of VG to be found.
544 * \param vgid UUID of VG to be found.
546 * \return Returns cmd_vg entry if vg_name or vgid is found,
549 struct cmd_vg *cmd_vg_lookup(struct dm_list *cmd_vgs,
550 const char *vg_name, const char *vgid)
554 dm_list_iterate_items(cvl, cmd_vgs)
555 if ((vgid && cvl->vgid && !strcmp(vgid, cvl->vgid)) ||
556 (vg_name && cvl->vg_name && !strcmp(vg_name, cvl->vg_name)))
562 * Read and lock multiple VGs stored in cmd_vgs list alphabeticaly.
563 * On the success list head pointer is set to VGs' cmd_vgs.
564 * (supports FAILED_INCONSISTENT)
566 * \param cmd_vg Contains list of cmd_vg entries.
568 * \return Returns 1 if all VG in cmd_vgs list are correctly
569 * openned and locked, 0 otherwise.
571 int cmd_vg_read(struct cmd_context *cmd, struct dm_list *cmd_vgs)
575 /* Iterate through alphabeticaly ordered cmd_vg list */
576 dm_list_iterate_items(cvl, cmd_vgs) {
577 cvl->vg = vg_read(cmd, cvl->vg_name, cvl->vgid, cvl->flags);
578 if (vg_read_error(cvl->vg)) {
579 log_debug("Failed to vg_read %s", cvl->vg_name);
582 cvl->vg->cmd_vgs = cmd_vgs; /* Make it usable in VG */
589 * Release opened and locked VGs from list.
591 * \param cmd_vgs Contains list of cmd_vg entries.
593 void free_cmd_vgs(struct dm_list *cmd_vgs)
597 /* Backward iterate cmd_vg list */
598 dm_list_iterate_back_items(cvl, cmd_vgs) {
599 if (vg_read_error(cvl->vg))
602 unlock_and_free_vg(cvl->vg->cmd, cvl->vg, cvl->vg_name);
608 * Find all needed remote VGs for processing given LV.
609 * Missing VGs are added to VG's cmd_vg list and flag cmd_missing_vgs is set.
611 int find_replicator_vgs(struct logical_volume *lv)
613 struct replicator_site *rsite;
616 if (!lv_is_replicator_dev(lv))
619 dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
620 if (!rsite->vg_name || !lv->vg->cmd_vgs ||
621 cmd_vg_lookup(lv->vg->cmd_vgs, rsite->vg_name, NULL))
624 /* Using cmd memory pool for cmd_vg list allocation */
625 if (!cmd_vg_add(lv->vg->cmd->mem, lv->vg->cmd_vgs,
626 rsite->vg_name, NULL, 0)) {
627 lv->vg->cmd_missing_vgs = 0; /* do not retry */
632 log_debug("VG: %s added as missing.", rsite->vg_name);
633 lv->vg->cmd_missing_vgs++;
640 * Read all remote VGs from lv's replicator sites.
641 * Function is used in activation context and needs all VGs already locked.
643 int lv_read_replicator_vgs(struct logical_volume *lv)
645 struct replicator_device *rdev;
646 struct replicator_site *rsite;
647 struct volume_group *vg;
649 if (!lv_is_replicator_dev(lv))
652 dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
655 vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, 0); // READ_WITHOUT_LOCK
656 if (vg_read_error(vg)) {
657 log_error("Unable to read volume group %s",
662 /* FIXME: handling missing LVs needs to be better */
663 dm_list_iterate_items(rdev, &rsite->rdevices)
664 if (!(rdev->lv = find_lv(vg, rdev->name))) {
665 log_error("Unable to find %s in volume group %s",
666 rdev->name, rsite->vg_name);
673 lv_release_replicator_vgs(lv);
678 * Release all VG resources taken by lv's replicator sites.
679 * Function is used in activation context and needs all VGs already locked.
681 void lv_release_replicator_vgs(struct logical_volume *lv)
683 struct replicator_site *rsite;
685 if (!lv_is_replicator_dev(lv))
688 dm_list_iterate_back_items(rsite, &first_seg(lv)->replicator->rsites)
689 if (rsite->vg_name && rsite->vg) {