[lvm-devel] [PATCH 22/25] Replicator: lvchange implementation

Zdenek Kabelac zkabelac at redhat.com
Sun Aug 8 08:57:34 UTC 2010


Signed-off-by: Zdenek Kabelac <zkabelac at redhat.com>
---
 tools/commands.h |    6 ++
 tools/lvchange.c |  195 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 196 insertions(+), 5 deletions(-)

diff --git a/tools/commands.h b/tools/commands.h
index 595da54..a2b6690 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -80,6 +80,10 @@ xx(lvchange,
    "\t[-r|--readahead ReadAheadSectors|auto|none]\n"
    "\t[--refresh]\n"
    "\t[--resync]\n"
+   "\t[--replicator ReplicatorName]\n"
+   "\t[--site SiteName [--sitepolicy {sync|warn|stall|drop|fail}]\n"
+   "\t  [{--fallbehindios IOCount|--fallbehindsize Size[bBsSkKmMgG]|\n"
+   "\t    --fallbehindtimeout Secs}]]]\n"
    "\t[--sysinit]\n"
    "\t[-t|--test]\n"
    "\t[-v|--verbose]\n"
@@ -91,6 +95,8 @@ xx(lvchange,
    ignorelockingfailure_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG,
    monitor_ARG, noudevsync_ARG, partial_ARG, permission_ARG, persistent_ARG,
    poll_ARG, readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG,
+   fallbehindios_ARG, fallbehindsize_ARG, fallbehindtimeout_ARG,
+   remotevg_ARG, replicator_ARG, replicatorlogtype_ARG, site_ARG, sitepolicy_ARG,
    sysinit_ARG, test_ARG, yes_ARG)
 
 xx(lvconvert,
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 4186b53..f3b5f67 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -15,6 +15,11 @@
 
 #include "tools.h"
 
+/* Internal data storage used for process_each_lv callbacks */
+struct lvchange_data {
+	struct dm_list activate_names;
+};
+
 static int lvchange_permission(struct cmd_context *cmd,
 			       struct logical_volume *lv)
 {
@@ -514,12 +519,153 @@ static int lvchange_tag(struct cmd_context *cmd, struct logical_volume *lv,
 	return 1;
 }
 
+static int lvchange_site(struct cmd_context *cmd, struct logical_volume *lv,
+			 int *skip_available, int *changed)
+{
+	struct lvinfo info;
+	struct replicator_site nrsite;
+	struct logical_volume *replicator;
+	struct replicator_site *rsite;
+	const char *replicator_name, *trname;
+	int active;
+
+	*changed = 0;
+	replicator = (lv_is_replicator(lv)) ? lv : first_seg(lv)->replicator;
+	rsite = find_local_site_in_replicator(replicator);
+
+	if (arg_count(cmd, replicator_ARG)) {
+		if (lv == replicator) {
+			log_error("Replicator specified twice.");
+			return 0;
+		}
+		replicator_name = arg_str_value(cmd, replicator_ARG, "");
+		/* Strip the volume group from the replicator */
+		if ((trname = strrchr(replicator_name, (int)'/')))
+			replicator_name = trname + 1;
+		/* Skip different replicator */
+		if (strcmp(replicator->name, replicator_name)) {
+			log_debug("Replicator %s/%s name does not match %s.",
+				  replicator->name, lv->name, replicator_name);
+			return 1;
+		}
+	}
+
+	if (arg_count(cmd, site_ARG)) {
+		nrsite.name = arg_str_value(cmd, site_ARG,
+					    DEFAULT_REPLICATOR_LOCAL_SITE_NAME);
+
+		/* Skip different replicator */
+		if (!(rsite = find_site_in_replicator(replicator, nrsite.name))) {
+			log_debug("Replicator %s/%s does not have site %s.",
+				  replicator->name, lv->name, nrsite.name);
+			return 1;
+		}
+	}
+
+	if (arg_count(cmd, remotevg_ARG)) {
+		log_error("Cannot change remotevg.");
+		return 0;
+	}
+
+	if (arg_count(cmd, replicatorlogtype_ARG)) {
+		log_error("Cannot change replicator log type.");
+		return 0;
+	}
+
+	memset(&nrsite, 0, sizeof(nrsite));
+	nrsite.state = NUM_REPLICATOR_STATE; /* invalid state */
+	if (arg_count(cmd, available_ARG)) {
+		if (rsite->site_index != 0) {
+			log_error("Cannot change state of remote site %s/%s.",
+				  replicator->name, rsite->name);
+			return 0;
+		}
+		switch (arg_uint_value(cmd, available_ARG, 0)) {
+		case CHANGE_ALY:
+		case CHANGE_AE:
+		case CHANGE_AY:
+			nrsite.state = REPLICATOR_STATE_ACTIVE;
+			break;
+		default:
+			nrsite.state = REPLICATOR_STATE_PASSIVE;
+		}
+
+		if (rsite->state != nrsite.state) {
+			rsite->state = nrsite.state;
+			(*changed)++;
+		}
+	}
+
+	if (!get_replicator_site_params(cmd, rsite, changed))
+		return_0;
+
+	if (!*changed)
+		return 1;
+
+	/* Replicator heads needs to be updated */
+	if (lv == replicator)
+		lv = first_replicated(replicator);
+
+	active = (lv_info(cmd, lv, &info, 0, 0) && info.exists);
+
+	if (active && !arg_count(cmd, force_ARG) &&
+	    yes_no_prompt("Replicator LVs %s will be deactivated. "
+			  "Continue? [y/n]: ",
+			  replicator->name) == 'n') {
+		log_error("%s site not changed.", rsite->name);
+		return 0;
+	}
+
+	if (active) {
+		/* FIXME: some cases may require synchronization of data from log */
+		if (arg_count(cmd, available_ARG) &&
+		    (nrsite.state == REPLICATOR_STATE_PASSIVE)) {
+			if (!lvchange_availability(cmd, lv))
+				return_0;
+			*skip_available = 1; /* skip later change of available */
+		} else if (!deactivate_lv(cmd, lv)) {
+			log_error("Unable to deactivate replicator %s.",
+				  replicator->name);
+			return 0;
+		}
+	}
+
+	if (!vg_write(lv->vg) || !vg_commit(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	if (active && !arg_count(cmd, available_ARG) &&
+	    !activate_lv(cmd, lv)) {
+		log_debug("Retry to activate replicator %s.",
+			  replicator->name);
+		return 0;
+	}
+
+	return 1;
+}
+
 static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
-			   void *handle __attribute__((unused)))
+			   void *handle)
 {
 	int doit = 0, docmds = 0;
 	int dmeventd_mode, archived = 0;
 	struct logical_volume *origin;
+	struct lvchange_data *lvc_data = handle;
+	int site_changed;
+	int skip_available = 0;
+
+	if (str_list_match_item(&lvc_data->activate_names, lv->name)) {
+		if (lv_is_replicator(lv))
+			lv = first_replicated(lv);
+
+		if (!activate_lv(cmd, lv)) {
+			log_error("Reactivation of replicator %s failed.",
+				  lv->rdevice->rsite->replicator->name);
+			return ECMD_FAILED;
+		}
+		return ECMD_PROCESSED;
+	}
 
 	if (!(lv->vg->status & LVM_WRITE) &&
 	    (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
@@ -569,7 +715,8 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 	    lv_is_virtual_origin(origin = origin_from_cow(lv)))
 		lv = origin;
 
-	if (!(lv_is_visible(lv)) && !lv_is_virtual_origin(lv)) {
+	if (!lv_is_visible(lv) && !lv_is_virtual_origin(lv) &&
+	    !lv_is_replicator(lv)) {
 		log_error("Unable to change internal LV %s directly",
 			  lv->name);
 		return ECMD_FAILED;
@@ -663,6 +810,23 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 		docmds++;
 	}
 
+        /* Update replicator paramaters */
+	if ((lv_is_replicator(lv) || lv_is_replicated(lv)) &&
+	    (arg_count(cmd, site_ARG) || arg_count(cmd, replicator_ARG))) {
+		if (!archived && !archive(lv->vg)) {
+			stack;
+			return ECMD_FAILED;
+		}
+		archived = 1;
+		site_changed = 0;
+		if (!lvchange_site(cmd, lv, &skip_available, &site_changed))
+			docmds++;
+		else if (site_changed) {
+			doit++;
+			docmds++;
+		}
+	}
+
 	if (doit)
 		log_print("Logical volume \"%s\" changed", lv->name);
 
@@ -673,7 +837,7 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 		}
 
 	/* availability change */
-	if (arg_count(cmd, available_ARG)) {
+	if (!skip_available && arg_count(cmd, available_ARG)) {
 		if (!lvchange_availability(cmd, lv)) {
 			stack;
 			return ECMD_FAILED;
@@ -705,7 +869,18 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 	}
 
 	if (doit != docmds) {
-		stack;
+		if (lv->vg->cmd_missing_vgs) {
+			/* Note: using cmd mempool to live across VG lifetime. */
+			if (!str_list_add(lv->vg->cmd->mem,
+					  &lvc_data->activate_names,
+					  lv->name)) {
+				log_error("Allocation of lv name failed.");
+				lv->vg->cmd_missing_vgs = 0;
+			}
+			/* Returns ECMD_FAILED for reprocessing. */
+		} else
+			stack;
+
 		return ECMD_FAILED;
 	}
 
@@ -718,8 +893,18 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
 		arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
 		arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
 		arg_count(cmd, addtag_ARG) || arg_count(cmd, deltag_ARG) ||
+		arg_count(cmd, fallbehindios_ARG) ||
+		arg_count(cmd, fallbehindsize_ARG) ||
+		arg_count(cmd, fallbehindtimeout_ARG) ||
+		arg_count(cmd, remotevg_ARG) || arg_count(cmd, replicator_ARG) ||
+		arg_count(cmd, replicatorlogtype_ARG) ||
+		arg_count(cmd, site_ARG) || arg_count(cmd, sitepolicy_ARG) ||
 		arg_count(cmd, resync_ARG) || arg_count(cmd, alloc_ARG);
 
+	struct lvchange_data lvc_data;
+
+	dm_list_init(&lvc_data.activate_names);
+
 	if (!update &&
             !arg_count(cmd, available_ARG) && !arg_count(cmd, refresh_ARG) &&
             !arg_count(cmd, monitor_ARG) && !arg_count(cmd, poll_ARG) &&
@@ -768,6 +953,6 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
 	}
 
 	return process_each_lv(cmd, argc, argv,
-			       update ? READ_FOR_UPDATE : 0, NULL,
+			       update ? READ_FOR_UPDATE : 0, &lvc_data,
 			       &lvchange_single);
 }
-- 
1.7.2.1




More information about the lvm-devel mailing list