[lvm-devel] [PATCH 10/12] Replicator: replicator_manip changes

Zdenek Kabelac zkabelac at redhat.com
Tue Jun 29 16:26:10 UTC 2010


Changes for replicator_manip.c source file.

Adding new API functions.

Lots of lines for log creation are copied from mirror code and then
are adapted for _slog. Code is done with hope we could share same
parametrized code later for both targets - mirror and replicator.
But with recent changes to mirrored logs it is a harder task.

Signed-off-by: Zdenek Kabelac <zkabelac at redhat.com>
---
 lib/metadata/replicator_manip.c |  806 +++++++++++++++++++++++++++++++++++----
 1 files changed, 741 insertions(+), 65 deletions(-)

diff --git a/lib/metadata/replicator_manip.c b/lib/metadata/replicator_manip.c
index b3a2fff..c6000aa 100644
--- a/lib/metadata/replicator_manip.c
+++ b/lib/metadata/replicator_manip.c
@@ -15,19 +15,25 @@
 #include "lib.h"
 #include "locking.h"
 #include "metadata.h"
+#include "defaults.h"
 #include "segtype.h"
 #include "toolcontext.h"
+#include "activate.h"
+#include "archiver.h"
+#include "lv_alloc.h"
+#include "str_list.h"
 
 /* Add lv as replicator_dev device */
-int replicator_dev_add_rimage(struct replicator_device *rdev,
-			      struct logical_volume *lv)
+static int _replicator_device_add_rimage(struct replicator_device *rdev,
+					 struct logical_volume *lv)
 {
 	if (!lv || !rdev)
 		return_0;
 
 	if (lv_is_rimage(lv)) {
+
 		log_error("Logical volume %s is already part of other "
-			  "replicator.", lv->name);
+			  "replicator.   %p  %p", lv->name, lv->rdevice, rdev);
 		return 0;
 	}
 
@@ -39,13 +45,14 @@ int replicator_dev_add_rimage(struct replicator_device *rdev,
 
 	lv_set_hidden(lv);
 	lv->rdevice = rdev;
+	rdev->replicator_dev->lv->rdevice = rdev;
 	rdev->lv = lv;
 
 	return add_seg_to_segs_using_this_lv(lv, rdev->replicator_dev);
 }
 
 /* Remove lv from replicator_dev device */
-struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev)
+static struct logical_volume *_replicator_device_remove_rimage(struct replicator_device *rdev)
 {
 	struct logical_volume *lv;
 
@@ -64,8 +71,8 @@ struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rd
 	return lv;
 }
 
-int replicator_dev_add_slog(struct replicator_device *rdev,
-			    struct logical_volume *slog)
+static int _replicator_device_add_slog(struct replicator_device *rdev,
+				       struct logical_volume *slog)
 {
 	if (!slog || !rdev)
 		return_0;
@@ -89,15 +96,14 @@ int replicator_dev_add_slog(struct replicator_device *rdev,
 	return add_seg_to_segs_using_this_lv(slog, rdev->replicator_dev);
 }
 
-struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev)
+static struct logical_volume *_replicator_device_remove_slog(struct replicator_device *rdev)
 {
 	struct logical_volume *lv;
 
 	if (!rdev)
 		return_NULL;
 
-	lv = rdev->slog;
-	if (!lv) {
+	if (!(lv = rdev->slog)) {
 		log_error("Replicator device in site %s does not have sync log.",
 			  rdev->rsite->name);
 		return NULL;
@@ -113,16 +119,40 @@ struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev
 	return lv;
 }
 
-int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
+static char *_replicator_device_slog_name(struct logical_volume *replicator,
+                                          unsigned site_index,
+					  uint64_t device_index)
+{
+	char *name;
+	size_t len = strlen(replicator->name) + 12 + 22 + 10;
+
+	if (!(name = dm_pool_zalloc(replicator->vg->vgmem, len))) {
+		log_error("Allocation of slog name failed.");
+		return NULL;
+	}
+
+	if (!dm_snprintf(name, len, "%s_%u_%" PRIu64 "_slog", replicator->name,
+			 site_index, device_index) < 0) {
+		log_error("Error in name creation");
+		return NULL;
+	}
+
+        return name;
+}
+
+/*
+ * Connection of NULL lv_segment will turn LV into replicator LV
+ */
+int replicator_add_replicator_dev(struct logical_volume *replicator,
 				  struct lv_segment *replicator_dev_seg)
 {
-	if (!replicator_lv)
+	if (!replicator)
 		return_0;
 
-	if (!(replicator_lv->status & REPLICATOR)) {
-		dm_list_init(&replicator_lv->rsites);
-		lv_set_hidden(replicator_lv);
-		replicator_lv->status |= REPLICATOR;
+	if (!(replicator->status & REPLICATOR)) {
+		dm_list_init(&replicator->rsites);
+		lv_set_hidden(replicator);
+		replicator->status |= REPLICATOR;
 	}
 
 	if (!replicator_dev_seg)
@@ -134,9 +164,11 @@ int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
 		return 0;
 	}
 
-	replicator_dev_seg->replicator = replicator_lv;
+	replicator_dev_seg->replicator = replicator;
+	replicator_dev_seg->rlog_lv = NULL;
+	replicator_dev_seg->lv->status |= REPLICATOR;
 
-	return add_seg_to_segs_using_this_lv(replicator_lv, replicator_dev_seg);
+	return add_seg_to_segs_using_this_lv(replicator, replicator_dev_seg);
 }
 
 /**
@@ -145,25 +177,25 @@ int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
  */
 struct logical_volume *replicator_remove_replicator_dev(struct lv_segment *replicator_dev_seg)
 {
-	struct logical_volume *lv = NULL;
-
-	log_error("FIXME: not implemented.");
-#if 0
-	/* FIXME: - this is going to be complex.... */
 	if (!replicator_dev_seg)
 		return_NULL;
 
-	/* if slog or rimage - exit */
+	if (!_replicator_device_remove_rimage(replicator_dev_seg->lv->rdevice)) {
+		log_error("Can not release rimage device");
+                return NULL;
+	}
 
-	if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
+	if (!remove_seg_from_segs_using_this_lv(replicator_dev_seg->replicator, replicator_dev_seg))
 		return_NULL;
 
-	replicator_seg->rlog_lv = NULL;
-	lv->status &= ~REPLICATOR_LOG;
-	lv_set_visible(lv);
-#endif
+	dm_list_del(&replicator_dev_seg->lv->rdevice->list);
 
-	return lv;
+	replicator_dev_seg->lv->status &= ~REPLICATOR;
+	replicator_dev_seg->rlog_lv = NULL;
+	replicator_dev_seg->replicator = NULL;
+	lv_set_visible(replicator_dev_seg->lv);
+
+	return replicator_dev_seg->lv;
 }
 
 int replicator_add_rlog(struct lv_segment *replicator_seg,
@@ -207,52 +239,232 @@ struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg)
 	return lv;
 }
 
+struct replicator_site *replicator_add_site(struct logical_volume *replicator,
+					    const char *site_name)
+{
+	struct replicator_site *rsite;
+
+	if (find_site_in_replicator(replicator, site_name)) {
+		log_error("Site name %s already exists.", site_name);
+		return NULL;
+	}
+
+	if (!(rsite = dm_pool_zalloc(replicator->vg->vgmem,
+				     sizeof(*rsite)))) {
+		log_error("Allocation of replicator site failed.");
+		return NULL;
+	}
+
+	if (!(rsite->name = dm_pool_strdup(replicator->vg->vgmem,
+					   site_name))) {
+		log_error("Allocation of replicator site name failed.");
+		return NULL;
+	}
+
+	rsite->replicator = replicator;
+	dm_list_init(&rsite->rdevices);
+	dm_list_add(&replicator->rsites, &rsite->list);
+
+	return rsite;
+}
+
+int replicator_remove_site(struct replicator_site *rsite)
+{
+	log_error("FIXME: replicator_remove_site implementation is missing.");
+	dm_list_del(&rsite->list);
+
+	return 1;
+}
+
+int replicator_site_add_device(struct replicator_site *rsite,
+			       struct lv_segment *replicator_dev_seg,
+			       const char *name,
+			       struct logical_volume *rimage_lv,
+			       uint32_t slog_core,
+			       struct logical_volume *slog,
+			       uint64_t device_index)
+{
+	struct dm_pool *mem = replicator_dev_seg->lv->vg->vgmem;
+	struct replicator_device *rdev;
+
+	if (!(rdev = dm_pool_zalloc(mem, sizeof(*rdev)))) {
+		log_error("Allocation of replicator device failed.");
+		return 0;
+	}
+
+	if (!(rdev->name = dm_pool_strdup(mem, name))) {
+		log_error("Allocation of replicator device name failed.");
+		return 0;
+	}
+
+	log_very_verbose("Created %s/%s", rsite->name, name);
+
+	rdev->rsite = rsite;
+	rdev->replicator_dev = replicator_dev_seg;
+	rdev->device_index = device_index;
+	rdev->slog_core = slog_core;
+
+	dm_list_add(&rsite->rdevices, &rdev->list);// linked site list
+
+	if (rimage_lv && !_replicator_device_add_rimage(rdev, rimage_lv))
+		return_0;
+
+	if (slog_core && slog) {
+		log_error("Either slog or corelog must be used.");
+		return 0;
+	}
+
+	if (slog && !_replicator_device_add_slog(rdev, slog))
+		return_0;
+
+	return 1;
+}
+
+int replicator_site_remove_device(struct replicator_device *rdev)
+{
+	dm_list_del(&rdev->list);
+
+	return 1;
+}
 
-#if 0
 /*
- * Create new LV to pretend the original LV
- * this target will have a 'replicator' segment
+ * Create new layered LV over the original LV
+ * this target will have a 'replicator-dev' segment
  */
-int lv_add_replicator(struct logical_volume *origin, const char *rep_suffix)
+int lv_add_replicator_dev(struct logical_volume *replicator,
+			  struct logical_volume *lv)
 {
-	struct logical_volume *rep_lv;
-	char *name;
-	size_t slen;
+	const struct segment_type *segtype;
+	struct logical_volume *rimage_lv;
+	struct logical_volume *slog;
+	struct lv_segment *seg;
+	struct replicator_site *rsite;
+	const char *slog_name;
+	uint64_t dev_idx = first_seg(replicator)->rdevice_index_highest;
 
-	if (!(name = strstr(origin->name, rep_suffix))) {
-		log_error("Failed to find replicator suffix %s in LV name %s",
-			  rep_suffix, origin->name);
+	if (!(segtype = get_segtype_from_string(lv->vg->cmd, "replicator-dev")))
+		return_0;
+
+	if (activation() && segtype->ops->target_present &&
+	    !segtype->ops->target_present(lv->vg->cmd, NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", segtype->name);
 		return 0;
 	}
-	slen = (size_t)(name - origin->name);
-	name = alloca(slen + 1);
-	memcpy(name, origin->name, slen);
-	name[slen] = 0;
 
-	if ((rep_lv = find_lv(origin->vg, name))) {
-		rep_lv->status |= VIRTUAL;
-		return 1;
+	/* If replicator does not have any site defined, add local default site */
+	if (dm_list_empty(&replicator->rsites)) {
+		if (!replicator_add_site(replicator, DEFAULT_REPLICATOR_LOCAL_SITE_NAME))
+			return_0;
+		first_seg(replicator)->rsite_index_highest++;
 	}
 
-	if (!(rep_lv = lv_create_empty(name, &origin->lvid,
-				       LVM_READ | LVM_WRITE | VISIBLE_LV,
-				       ALLOC_INHERIT, origin->vg)))
-		return_0;
+	first_seg(replicator)->rdevice_index_highest++;
+	dm_list_iterate_items(rsite, &replicator->rsites) {
+		if (rsite->site_index == 0) {
+			if (!(rimage_lv = insert_layer_for_lv(lv->vg->cmd, lv, 0, "_rimage")))
+				return_0;
+
+			seg = first_seg(lv);
+			seg->segtype = segtype; /* switch to replicator-dev */
 
-	if (!lv_add_virtual_segment(rep_lv, 0, origin->le_count,
-				    get_segtype_from_string(origin->vg->cmd,
-							    "error")))
+			if (!replicator_add_replicator_dev(replicator, seg))
+				return_0;
+
+			if (!replicator_site_add_device(rsite, seg, rimage_lv->name,
+							rimage_lv, 0, NULL, dev_idx))
+				return_0;
+		} else {
+			// FIXME: corelog support missing
+			slog_name = _replicator_device_slog_name(replicator, rsite->site_index,
+								 dev_idx);
+			if (!(slog = find_lv(lv->vg, slog_name))) {
+				log_error("Cannot find slog LV %s for %s/%s",
+					  slog_name, rsite->name, lv->name);
+				return 0;
+			}
+
+			if (!replicator_site_add_device(rsite, seg, lv->name,
+							NULL, 0, slog, dev_idx))
+				return_0;
+		}
+	}
+
+	return 1;
+}
+
+int lv_remove_replicator_dev(struct logical_volume *lv)
+{
+	struct replicator_site *rsite;
+	struct replicator_device *rdev, *trdev;
+	struct logical_volume *replicator = first_seg(lv)->replicator;
+	uint64_t device_index = lv->rdevice->device_index;
+
+	dm_list_iterate_items(rsite, &replicator->rsites) {
+		if (rsite->site_index == 0)
+			continue;
+		dm_list_iterate_items_safe(rdev, trdev, &rsite->rdevices) {
+			if (rdev->device_index != device_index)
+				continue;
+			if (!_replicator_device_remove_slog(rdev))
+				return_0;
+			dm_list_del(&rdev->list);
+		}
+	}
+
+	if (!replicator_remove_replicator_dev(first_seg(lv)))
 		return_0;
 
-	rep_lv->status |= VIRTUAL;
 	return 1;
 }
 
-int lv_remove_replicator(struct logical_volume *lv)
+int lv_add_replicator_site(struct logical_volume *replicator,
+			   const struct replicator_site *rsite)
 {
+	struct replicator_site *nrsite;
+
+	if (find_site_in_replicator(replicator, rsite->name)) {
+		log_error("Site %s already exists.", rsite->name);
+		return 0;
+	}
+
+	if (!(nrsite = replicator_add_site(replicator, rsite->name)))
+		return_0;
+
+	if (rsite->vg_name &&
+	    !(nrsite->vg_name = dm_pool_strdup(replicator->vg->vgmem,
+					       rsite->vg_name))) {
+		log_error("Allocation of replicator site vg_name failed.");
+		return 0;
+	}
+
+	nrsite->site_index = first_seg(replicator)->rsite_index_highest++;
+	nrsite->op_mode = rsite->op_mode;
+	nrsite->fall_behind_data = rsite->fall_behind_data;
+	nrsite->fall_behind_ios = rsite->fall_behind_ios;
+	nrsite->fall_behind_timeout = rsite->fall_behind_timeout;
+
 	return 1;
 }
-#endif
+
+int lv_remove_replicator_site(struct logical_volume *replicator,
+			      const char *site_name)
+{
+	log_error("FIXME remove replicator site.");
+	return 0;
+}
+
+struct replicator_site *find_site_in_replicator(struct logical_volume *replicator,
+						const char *site_name)
+{
+	struct replicator_site *rsite;
+
+	dm_list_iterate_items(rsite, &replicator->rsites)
+		if (strcmp(rsite->name, site_name) == 0)
+			return rsite;
+
+	return NULL;
+}
 
 /*
  * Check all replicator structures:
@@ -266,7 +478,7 @@ int check_replicator_segment(const struct lv_segment *rseg)
 {
 	struct replicator_site *rsite, *rsiteb;
 	struct replicator_device *rdev, *rdevb;
-        struct logical_volume *lv = rseg->lv;
+	struct logical_volume *lv = rseg->lv;
 	int r = 1;
 
 	if (vg_is_clustered(lv->vg)) {
@@ -356,8 +568,8 @@ int check_replicator_segment(const struct lv_segment *rseg)
 					  rsite->name);
 				r = 0;
 			}
-			if (rsite->site_index > rseg->rsite_index_highest) {
-				log_error("Site index %d > %d (too high) "
+			if (rsite->site_index >= rseg->rsite_index_highest) {
+				log_error("Site index %d >= %d (too high) "
 					  "for replicator site %s/%s.",
 					  rsite->site_index,
 					  rseg->rsite_index_highest,
@@ -367,6 +579,20 @@ int check_replicator_segment(const struct lv_segment *rseg)
 		}
 
 		dm_list_iterate_items(rdev, &rsite->rdevices) {
+			if (rdev->rsite->site_index == 0) {
+				if (strcasecmp(rdev->name,
+					       rdev->replicator_dev->lv->name) == 0) {
+					log_error("Self referenced device name "
+						  "%s detected for replicator %s.",
+						  rdev->name, lv->name);
+					r = 0;
+				}
+			} else if (!rdev->slog && !rdev->slog_core) {
+				log_error("Undefined slog for %s/%s "
+					  " for replicator %s.",
+					  rdev->rsite->name, rdev->name, lv->name);
+				r = 0;
+			}
 			dm_list_iterate_items(rdevb, &rsite->rdevices) {
 				if (rdev == rdevb)
 					break;
@@ -376,6 +602,13 @@ int check_replicator_segment(const struct lv_segment *rseg)
 						  rdev->slog->name, lv->name);
 					r = 0;
 				}
+				if (strcasecmp(rdev->name,
+					       rdevb->replicator_dev->lv->name) == 0) {
+					log_error("Internal self reference device"
+						  "name %s detected for replicator %s.",
+						  rdev->name, lv->name);
+					r = 0;
+				}
 				if (strcasecmp(rdev->name, rdevb->name) == 0) {
 					log_error("Duplicate device name %s "
 						  "detected for replicator %s.",
@@ -390,9 +623,9 @@ int check_replicator_segment(const struct lv_segment *rseg)
 						  lv->name, rsite->name);
 					r = 0;
 				}
-				if (rdev->device_index > rseg->rdevice_index_highest) {
+				if (rdev->device_index >= rseg->rdevice_index_highest) {
 					log_error("Device index %" PRIu64
-						  " > %" PRIu64 " (too high) "
+						  " >= %" PRIu64 " (too high) "
 						  "for replicator site %s/%s.",
 						  rdev->device_index,
 						  rseg->rdevice_index_highest,
@@ -411,7 +644,7 @@ int check_replicator_segment(const struct lv_segment *rseg)
  */
 int lv_is_active_replicator_dev(const struct logical_volume *lv)
 {
-	return ((lv->status & REPLICATOR) &&
+	return (lv_is_replicator_dev(lv) &&
 		lv->rdevice &&
 		lv->rdevice->rsite &&
 		lv->rdevice->rsite->state == REPLICATOR_STATE_ACTIVE);
@@ -442,7 +675,8 @@ int lv_is_replicator_dev(const struct logical_volume *lv)
  */
 int lv_is_rimage(const struct logical_volume *lv)
 {
-	return (lv->rdevice && lv->rdevice->lv == lv);
+	return (!lv_is_replicator_dev(lv) &&
+		(lv->rdevice && lv->rdevice->lv == lv));
 }
 
 /**
@@ -646,13 +880,13 @@ int lv_read_replicator_vgs(struct logical_volume *lv)
 	struct replicator_site *rsite;
 	struct volume_group *vg;
 
-	if (!lv_is_replicator_dev(lv))
+	if (!lv_is_active_replicator_dev(lv))
 		return 1;
 
 	dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
 		if (!rsite->vg_name)
 			continue;
-		vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, 0); // READ_WITHOUT_LOCK
+		vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, READ_WITHOUT_LOCK);
 		if (vg_read_error(vg)) {
 			log_error("Unable to read volume group %s",
 				  rsite->vg_name);
@@ -691,3 +925,445 @@ void lv_release_replicator_vgs(struct logical_volume *lv)
 			rsite->vg = NULL;
 		}
 }
+
+static int _write_replicator_header(struct cmd_context *cmd, struct logical_volume *lv)
+{
+	return 1;
+}
+
+/*
+ * Initialize log contents
+ *
+ * log_name = "mirror log", "replicator sync log"
+ */
+static int _init_log(struct cmd_context *cmd,
+		     struct logical_volume *log_lv, int in_sync,
+		     struct dm_list *tags, int remove_on_failure,
+		     const char *log_name,
+		     int (*write_header) (struct cmd_context *cmd,
+					  struct logical_volume *lv))
+{
+	struct str_list *sl;
+	struct lvinfo info;
+	uint64_t orig_status = log_lv->status;
+	int was_active = 0;
+
+	if (!activation() && in_sync) {
+		log_error("Aborting. Unable to create in-sync %s "
+			  "while activation is disabled.", log_name);
+		return 0;
+	}
+
+	/* If the LV is active, deactivate it first. */
+	if (lv_info(cmd, log_lv, &info, 0, 0) && info.exists) {
+		(void)deactivate_lv(cmd, log_lv);
+		/*
+		 * FIXME: workaround to fail early
+		 * Ensure that log is really deactivated because deactivate_lv
+		 * on cluster do not fail if there is log_lv with different UUID.
+		 */
+		if (lv_info(cmd, log_lv, &info, 0, 0) && info.exists) {
+			log_error("Aborting. Unable to deactivate %s.",
+				  log_name);
+			goto revert_new_lv;
+		}
+		was_active = 1;
+	}
+
+	/* Temporary make it visible for set_lv() */
+	lv_set_visible(log_lv);
+
+	/* Temporary tag mirror log for activation */
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_add(cmd->mem, &log_lv->tags, sl->str)) {
+			log_error("Aborting. Unable to tag %s.", log_name);
+			goto activate_lv;
+		}
+
+	/* store mirror log on disk(s) */
+	if (!vg_write(log_lv->vg) || !vg_commit(log_lv->vg))
+		goto activate_lv;
+
+	backup(log_lv->vg);
+
+	if (!activate_lv(cmd, log_lv)) {
+		log_error("Aborting. Failed to activate %s.", log_name);
+		goto revert_new_lv;
+	}
+
+	/* Remove the temporary tags */
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_del(&log_lv->tags, sl->str))
+			log_error("Failed to remove tag %s from %s.",
+				  log_name, sl->str);
+
+	if (activation() && !set_lv(cmd, log_lv, log_lv->size,
+				    in_sync ? -1 : 0)) {
+		log_error("Aborting. Failed to wipe %s.", log_name);
+		goto deactivate_and_revert_new_lv;
+	}
+
+	if (activation() && !write_header(cmd, log_lv)) { /* FIXME */
+		log_error("Aborting. Failed to write %s header.", log_name);
+		goto deactivate_and_revert_new_lv;
+	}
+
+	if (!deactivate_lv(cmd, log_lv)) {
+		log_error("Aborting. Failed to deactivate %s. "
+			  "Manual intervention required.", log_name);
+		return 0;
+	}
+
+	lv_set_hidden(log_lv);
+
+	if (was_active && !activate_lv(cmd, log_lv))
+		return_0;
+
+	return 1;
+
+deactivate_and_revert_new_lv:
+	if (!deactivate_lv(cmd, log_lv)) {
+		log_error("Unable to deactivate %s LV. "
+			  "Manual intervention required.", log_name);
+		return 0;
+	}
+
+revert_new_lv:
+	log_lv->status = orig_status;
+
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_del(&log_lv->tags, sl->str))
+			log_error("Failed to remove tag %s from %s.",
+				  log_name, sl->str);
+
+	if (remove_on_failure && !lv_remove(log_lv)) {
+		log_error("Manual intervention may be required to remove "
+			  "abandoned log LV before retrying.");
+		return 0;
+	}
+
+	if (!vg_write(log_lv->vg) || !vg_commit(log_lv->vg))
+		log_error("Manual intervention may be required to "
+			  "remove/restore abandoned log LV before retrying.");
+	else
+		backup(log_lv->vg);
+
+activate_lv:
+	if (was_active && !remove_on_failure && !activate_lv(cmd, log_lv))
+		return_0;
+
+	return 0;
+}
+
+#if 0
+static int _init_replicator_log(struct cmd_context *cmd,
+				struct logical_volume *log_lv, int in_sync,
+				struct dm_list *tags, int remove_on_failure)
+{
+	if (!_init_log(cmd, log_lv, in_sync, tags, remove_on_failure,
+		       "replicator log", _write_replicator_header))
+		return_0;
+
+	return 1;
+}
+#endif
+
+static int _init_replicator_sync_log(struct cmd_context *cmd,
+				     struct logical_volume *log_lv, int in_sync,
+				     struct dm_list *tags, int remove_on_failure)
+{
+	if (!_init_log(cmd, log_lv, in_sync, tags, remove_on_failure,
+		       "sync log", _write_replicator_header))
+		return_0;
+
+	return 1;
+}
+
+/* Could be shared with mirror */
+static struct logical_volume *_create_log(struct logical_volume *lv,
+					  struct alloc_handle *ah,
+					  alloc_policy_t alloc,
+					  const char *lv_name,
+					  const char *suffix,
+					  uint64_t status)
+{
+	struct logical_volume *log_lv;
+	char *log_name;
+	size_t len;
+
+	len = strlen(lv_name) + 32;
+	if (!(log_name = alloca(len))) {
+		log_error("log_name allocation failed.");
+		return NULL;
+	}
+
+	if (dm_snprintf(log_name, len, "%s%s", lv_name, suffix) < 0) {
+		log_error("log_name allocation failed.");
+		return NULL;
+	}
+
+	if (!(log_lv = lv_create_empty(log_name, NULL,
+				       VISIBLE_LV | LVM_READ | LVM_WRITE,
+				       alloc, lv->vg)))
+		return_NULL;
+
+	if (!lv_add_log_segment(ah, 0, log_lv, status))
+		return_NULL;
+
+	return log_lv;
+}
+
+#if 0
+static struct logical_volume *_set_up_replicator_log(struct cmd_context *cmd,
+						     struct alloc_handle *ah,
+						     struct logical_volume *lv,
+						     uint32_t log_size __attribute((unused)),
+						     alloc_policy_t alloc,
+						     int in_sync)
+{
+	struct logical_volume *log_lv;
+	const char *suffix, *c;
+	char *lv_name;
+	size_t len;
+	struct lv_segment *seg;
+
+	//init_mirror_in_sync(in_sync);
+
+	/* Replicator log name is lv_name + suffix, determined as the following:
+	 *   1. suffix is:
+	 *        o "_rlog" for the original replicator LV.
+	 *        o "_rlogtmp_%d" for temporary mirror LV,
+	 *   2. lv_name is:
+	 *        o lv->name, if the log is temporary
+	 *        o otherwise, the top-level LV name
+	 */
+	seg = first_seg(lv);
+	if (seg_type(seg, 0) == AREA_LV &&
+	    strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER)) {
+		lv_name = lv->name;
+		suffix = "_rlogtmp_%d";
+	} else if ((c = strstr(lv->name, MIRROR_SYNC_LAYER))) {
+		len = (size_t)(c - lv->name + 1);
+		if (!(lv_name = alloca(len)) ||
+		    !dm_snprintf(lv_name, len, "%s", lv->name)) {
+			log_error("replicator log name allocation failed");
+			return 0;
+		}
+		suffix = "_rlog";
+	} else {
+		lv_name = lv->name;
+		suffix = "_rlog";
+	}
+
+	if (!(log_lv = _create_log(lv, ah, alloc, lv_name, suffix, REPLICATOR_LOG))) {
+		log_error("Failed to create replicator log.");
+		return NULL;
+	}
+
+	if (!_init_replicator_log(cmd, log_lv, in_sync, &lv->tags, 1)) {
+		log_error("Failed to initialise replicator log.");
+		return NULL;
+	}
+
+	return log_lv;
+}
+#endif
+
+static struct logical_volume *_set_up_sync_log(struct cmd_context *cmd,
+					       struct alloc_handle *ah,
+					       struct logical_volume *replicator,
+                                               unsigned site_index,
+					       uint64_t device_index,
+					       alloc_policy_t alloc,
+					       int in_sync)
+{
+	struct logical_volume *log_lv;
+	const char *suffix = "";
+	char *lv_name;
+
+	if (!(lv_name = _replicator_device_slog_name(replicator, site_index, device_index)))
+		return_NULL;
+
+	if (!(log_lv = _create_log(replicator, ah, alloc, lv_name, suffix,
+				   REPLICATOR_LOG))) {
+		log_error("Failed to create replicator sync log.");
+		return NULL;
+	}
+
+	if (!_init_replicator_sync_log(cmd, log_lv, in_sync, &replicator->tags, 1)) {
+		log_error("Failed to initialise replicator sync log.");
+		return NULL;
+	}
+
+	return log_lv;
+}
+
+int lv_add_sync_log(struct logical_volume *replicator,
+		    unsigned site_index,
+		    uint64_t device_index,
+		    struct dm_list *allocatable_pvs,
+		    alloc_policy_t alloc)
+{
+	struct cmd_context *cmd = replicator->vg->cmd;
+	const struct segment_type *segtype;
+	struct alloc_handle *ah;
+	uint32_t region_size;
+	int in_sync;
+	int r = 1;
+
+	if (!(segtype = get_segtype_from_string(cmd, "striped")))
+		return_0;
+
+	if (activation() && segtype->ops->target_present &&
+	    !segtype->ops->target_present(cmd, NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", segtype->name);
+		return 0;
+	}
+
+	region_size = adjusted_mirror_region_size(replicator->vg->extent_size,
+						  replicator->le_count,
+						  first_seg(replicator)->region_size);
+
+	/* allocate destination extents */
+	ah = allocate_extents(replicator->vg, NULL, segtype,
+			      0, 0, 1, region_size, 0,
+			      allocatable_pvs, alloc, NULL);
+	if (!ah) {
+		log_error("Unable to allocate extents for replicator sync log.");
+		return 0;
+	}
+
+	/* check sync status */
+	in_sync = 0;
+
+	if (!_set_up_sync_log(cmd, ah, replicator, site_index, device_index,
+			      alloc, in_sync)) {
+                stack;
+		r = 0;
+	}
+
+	alloc_destroy(ah);
+
+        return r;
+}
+
+int vg_prepare_replicator(struct volume_group *vg,
+			  const struct lvcreate_params *lp)
+{
+	struct logical_volume *replicator;
+	struct replicator_device *rdev;
+	struct replicator_site *rsite;
+	unsigned site_index;
+	uint64_t device_index;
+
+	if (lp->replicator_dev || lp->rsite.name) {
+		if (!(replicator = find_lv(vg, lp->replicator))) {
+			log_error("Replicator \"%s\" not found.", lp->replicator);
+			return 0;
+		}
+
+		if (lp->replicator_dev) {
+			device_index = first_seg(replicator)->rdevice_index_highest;
+			dm_list_iterate_items(rsite, &replicator->rsites) {
+				if (rsite->site_index != 0 &&
+				    !lv_add_sync_log(replicator,
+						     rsite->site_index,
+						     device_index,
+						     lp->pvh, lp->alloc))
+					return_0;
+			}
+		}
+		if (lp->rsite.name) {
+			site_index = first_seg(replicator)->rsite_index_highest;
+			dm_list_iterate_items(rsite, &replicator->rsites) {
+				if (rsite->site_index != 0)
+					continue;
+
+				dm_list_iterate_items(rdev, &rsite->rdevices) {
+					if (!lv_add_sync_log(replicator,
+							     site_index,
+							     rdev->device_index,
+							     lp->pvh, lp->alloc))
+						return_0;
+				}
+			}
+		}
+	}
+
+	/* For site creation - no new LV will created */
+	if (lp->rsite.name && strlen(lp->replicator)) {
+		if (!(replicator = find_lv(vg, lp->replicator))) {
+			log_error("Replicator %s does not exists",
+				  lp->replicator);
+			return 0;
+		}
+		if (!lv_add_replicator_site(replicator, &lp->rsite))
+			return_0;
+
+		if (!archive(vg))
+			return_0;
+
+		/* store vg on disk(s) */
+		if (!vg_write(vg) || !vg_commit(vg))
+			return_0;
+
+		backup(vg);
+	}
+
+	return 1;
+}
+
+int vg_add_replicator(struct logical_volume *replicator,
+		      const char *rlog_type,
+		      uint32_t region_size)
+{
+	const struct segment_type *segtype;
+	float sync_percent;
+	percent_range_t percent_range;
+	struct logical_volume *rlog_lv;
+	struct lv_segment *repseg;
+	struct lvinfo info;
+
+	/*
+	 * We are unable to convert the log of inactive cluster replictors
+	 */
+	if (vg_is_clustered(replicator->vg)
+	    && !(lv_info(replicator->vg->cmd, replicator, &info, 0, 0) &&
+		 info.exists)) {
+		log_error("Replicator in this VG is not supported.");
+		return 0;
+	}
+
+	if (!(segtype = get_segtype_from_string(replicator->vg->cmd,
+						"replicator")))
+		return_0;
+
+	if (activation() && segtype->ops->target_present &&
+	    !segtype->ops->target_present(replicator->vg->cmd, NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", segtype->name);
+		return 0;
+	}
+
+	if (!(rlog_lv = insert_layer_for_lv(replicator->vg->cmd,
+					    replicator, 0, "_rlog"))) {
+		log_error("Failed to insert replicator _rlog");
+		return 0;
+	}
+
+	repseg = first_seg(replicator);
+	repseg->segtype = segtype;
+
+	repseg->rlog_type = rlog_type; //"ringbuffer";
+	repseg->rdevice_index_highest = 0;
+	repseg->rsite_index_highest = 0;
+	repseg->region_size = region_size;
+
+	replicator_add_replicator_dev(replicator, NULL);
+
+	if (!replicator_add_rlog(repseg, rlog_lv))
+		return_0;
+
+	return 1;
+}
-- 
1.7.1




More information about the lvm-devel mailing list