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

Zdenek Kabelac zkabelac at redhat.com
Wed Jul 7 12:34:54 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 7966cff..9e27ad9 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 [--sitemode {sync|warn|stall|drop|fail}]\n"
+   "\t  [{--fallbehinddata Size[bBsSkKmMgG]|\n"
+   "\t    --fallbehindios IOCount|--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,
+   fallbehinddata_ARG, fallbehindios_ARG, fallbehindtimeout_ARG,
+   replicator_ARG, replicatorlogtype_ARG, remotevg_ARG, site_ARG, sitemode_ARG,
    sysinit_ARG, test_ARG, yes_ARG)
 
 xx(lvconvert,
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 126e61a..4d43db4 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,156 @@ 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)
+{
+	struct lvinfo info;
+	struct replicator_site nrsite;
+	struct logical_volume *replicator;
+	struct replicator_site *rsite;
+	const char *replicator_name, *trname;
+	int active;
+	int 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 2;
+		}
+	}
+
+	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 2;
+		}
+	}
+
+	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 2;
+
+	/* Replicator heads needs to be updated */
+	if (lv == replicator)
+		lv = first_replicator_dev(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 skip_available = 0;
+
+	struct str_list *sl;
+	dm_list_iterate_items(sl, &lvc_data->activate_names)
+		log_error("LIST %s  %p", sl->str, sl->str);
+
+	if (str_list_match_item(&lvc_data->activate_names, lv->name)) {
+		if (lv_is_replicator(lv))
+			lv = first_replicator_dev(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 +718,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 +813,21 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 		docmds++;
 	}
 
+        /* Update replicator paramaters */
+	if ((lv_is_replicator(lv) || lv_is_replicator_dev(lv)) &&
+	    (arg_count(cmd, site_ARG) || arg_count(cmd, replicator_ARG))) {
+		if (!archived && !archive(lv->vg)) {
+			stack;
+			return ECMD_FAILED;
+		}
+		archived = 1;
+		switch (lvchange_site(cmd, lv, &skip_available)) {
+		case 0: docmds++; break;
+		case 1: docmds++; doit++; break;
+		default: /* 2 = ok, but nothing changed */;
+		}
+	}
+
 	if (doit)
 		log_print("Logical volume \"%s\" changed", lv->name);
 
@@ -673,7 +838,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 +870,18 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 	}
 
 	if (doit != docmds) {
-		stack;
+		if (lv->vg->cmd_missing_vgs) {
+			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;
+			}
+		} else
+			stack;
+		/* Note: using cmd mempool to live across vg lifetime */
+		/* return ECMD_FAILED for reprocessing */
+
 		return ECMD_FAILED;
 	}
 
@@ -718,8 +894,16 @@ 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, replicator_ARG) || arg_count(cmd, site_ARG) ||
+		arg_count(cmd, remotevg_ARG) || arg_count(cmd, replicatorlogtype_ARG) ||
+		arg_count(cmd, fallbehinddata_ARG) || arg_count(cmd, fallbehindios_ARG) ||
+		arg_count(cmd, fallbehindtimeout_ARG) || arg_count(cmd, sitemode_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) &&
@@ -767,7 +951,8 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
 		return EINVALID_CMD_LINE;
 	}
 
+	log_error("LVCHANGE DATA  %d ", argc);
 	return process_each_lv(cmd, argc, argv,
-			       update ? READ_FOR_UPDATE : 0, NULL,
+			       update ? READ_FOR_UPDATE : 0, &lvc_data,
 			       &lvchange_single);
 }
-- 
1.7.1.1




More information about the lvm-devel mailing list