Beispiel #1
0
static int lvchange_monitoring(struct cmd_context *cmd,
			       struct logical_volume *lv)
{
	struct lvinfo info;

	if (!lv_info(cmd, lv, 0, &info, 0, 0) || !info.exists) {
		log_error("Logical volume, %s, is not active", lv->name);
		return 0;
	}

	/* do not monitor pvmove lv's */
	if (lv->status & PVMOVE)
		return 1;

	if ((dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) &&
	    !monitor_dev_for_events(cmd, lv, 0, dmeventd_monitor_mode()))
		return_0;

	return 1;
}
Beispiel #2
0
static int _lock_for_cluster(struct cmd_context *cmd, unsigned char clvmd_cmd,
			     uint32_t flags, const char *name)
{
	int status;
	int i;
	char *args;
	const char *node = "";
	int len;
	int dmeventd_mode;
	int saved_errno = errno;
	lvm_response_t *response = NULL;
	int num_responses;

	assert(name);

	len = strlen(name) + 3;
	args = alloca(len);
	strcpy(args + 2, name);

	/* Maskoff lock flags */
	args[0] = flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_NONBLOCK | LCK_HOLD); 
	args[1] = flags & (LCK_LOCAL | LCK_CLUSTER_VG);

	if (mirror_in_sync())
		args[1] |= LCK_MIRROR_NOSYNC_MODE;

	/*
	 * Must handle tri-state return from dmeventd_monitor_mode.
	 * But DMEVENTD_MONITOR_IGNORE is not propagated across the cluster.
	 */
	dmeventd_mode = dmeventd_monitor_mode();
	if (dmeventd_mode != DMEVENTD_MONITOR_IGNORE && dmeventd_mode)
		args[1] |= LCK_DMEVENTD_MONITOR_MODE;

	if (cmd->partial_activation)
		args[1] |= LCK_PARTIAL_MODE;

	/*
	 * VG locks are just that: locks, and have no side effects
	 * so we only need to do them on the local node because all
	 * locks are cluster-wide.
	 * Also, if the lock is exclusive it makes no sense to try to
	 * acquire it on all nodes, so just do that on the local node too.
	 * One exception, is that P_ locks /do/ get distributed across
	 * the cluster because they might have side-effects.
	 */
	if (strncmp(name, "P_", 2) &&
	    (clvmd_cmd == CLVMD_CMD_LOCK_VG ||
	     (flags & LCK_TYPE_MASK) == LCK_EXCL ||
	     (flags & LCK_LOCAL) ||
	     !(flags & LCK_CLUSTER_VG)))
		node = ".";

	status = _cluster_request(clvmd_cmd, node, args, len,
				  &response, &num_responses);

	/* If any nodes were down then display them and return an error */
	for (i = 0; i < num_responses; i++) {
		if (response[i].status == EHOSTDOWN) {
			log_error("clvmd not running on node %s",
				  response[i].node);
			status = 0;
			errno = response[i].status;
		} else if (response[i].status) {
			log_error("Error locking on node %s: %s",
				  response[i].node,
				  response[i].response[0] ?
				  	response[i].response :
				  	strerror(response[i].status));
			status = 0;
			errno = response[i].status;
		}
	}

	saved_errno = errno;
	_cluster_free_request(response, num_responses);
	errno = saved_errno;

	return status;
}
Beispiel #3
0
static int lvchange_resync(struct cmd_context *cmd,
			      struct logical_volume *lv)
{
	int active = 0;
	int monitored;
	struct lvinfo info;
	struct logical_volume *log_lv;

	if (!(lv->status & MIRRORED)) {
		log_error("Unable to resync %s because it is not mirrored.",
			  lv->name);
		return 1;
	}

	if (lv->status & PVMOVE) {
		log_error("Unable to resync pvmove volume %s", lv->name);
		return 0;
	}

	if (lv->status & LOCKED) {
		log_error("Unable to resync locked volume %s", lv->name);
		return 0;
	}

	if (lv_info(cmd, lv, 0, &info, 1, 0)) {
		if (info.open_count) {
			log_error("Can't resync open logical volume \"%s\"",
				  lv->name);
			return 0;
		}

		if (info.exists) {
			if (!arg_count(cmd, yes_ARG) &&
			    yes_no_prompt("Do you really want to deactivate "
					  "logical volume %s to resync it? [y/n]: ",
					  lv->name) == 'n') {
				log_error("Logical volume \"%s\" not resynced",
					  lv->name);
				return 0;
			}

			if (sigint_caught())
				return 0;

			active = 1;
		}
	}

	/* Activate exclusively to ensure no nodes still have LV active */
	monitored = dmeventd_monitor_mode();
	init_dmeventd_monitor(0);

	if (!deactivate_lv(cmd, lv)) {
		log_error("Unable to deactivate %s for resync", lv->name);
		return 0;
	}

	if (vg_is_clustered(lv->vg) && lv_is_active(lv)) {
		log_error("Can't get exclusive access to clustered volume %s",
			  lv->name);
		return 0;
	}

	init_dmeventd_monitor(monitored);

	log_lv = first_seg(lv)->log_lv;

	log_very_verbose("Starting resync of %s%s%s mirror \"%s\"",
			 (active) ? "active " : "",
			 vg_is_clustered(lv->vg) ? "clustered " : "",
			 (log_lv) ? "disk-logged" : "core-logged",
			 lv->name);

	/*
	 * If this mirror has a core log (i.e. !log_lv),
	 * then simply deactivating/activating will cause
	 * it to reset the sync status.  We only need to
	 * worry about persistent logs.
	 */
	if (!log_lv && !(lv->status & LV_NOTSYNCED)) {
		if (active && !activate_lv(cmd, lv)) {
			log_error("Failed to reactivate %s to resynchronize "
				  "mirror", lv->name);
			return 0;
		}
		return 1;
	}

	lv->status &= ~LV_NOTSYNCED;

	if (log_lv) {
		/* Separate mirror log so we can clear it */
		detach_mirror_log(first_seg(lv));

		if (!vg_write(lv->vg)) {
			log_error("Failed to write intermediate VG metadata.");
			if (!attach_mirror_log(first_seg(lv), log_lv))
				stack;
			if (active && !activate_lv(cmd, lv))
				stack;
			return 0;
		}

		if (!vg_commit(lv->vg)) {
			log_error("Failed to commit intermediate VG metadata.");
			if (!attach_mirror_log(first_seg(lv), log_lv))
				stack;
			if (active && !activate_lv(cmd, lv))
				stack;
			return 0;
		}

		backup(lv->vg);

		if (!activate_lv(cmd, log_lv)) {
			log_error("Unable to activate %s for mirror log resync",
				  log_lv->name);
			return 0;
		}

		log_very_verbose("Clearing log device %s", log_lv->name);
		if (!set_lv(cmd, log_lv, log_lv->size, 0)) {
			log_error("Unable to reset sync status for %s", lv->name);
			if (!deactivate_lv(cmd, log_lv))
				log_error("Failed to deactivate log LV after "
					  "wiping failed");
			return 0;
		}

		if (!deactivate_lv(cmd, log_lv)) {
			log_error("Unable to deactivate log LV %s after wiping "
				  "for resync", log_lv->name);
			return 0;
		}

		/* Put mirror log back in place */
		if (!attach_mirror_log(first_seg(lv), log_lv))
			stack;
	}

	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
	if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
		log_error("Failed to update metadata on disk.");
		return 0;
	}

	if (active && !activate_lv(cmd, lv)) {
		log_error("Failed to reactivate %s after resync", lv->name);
		return 0;
	}

	return 1;
}
static int _lock_for_cluster(struct cmd_context *cmd, unsigned char clvmd_cmd,
			     uint32_t flags, const char *name)
{
	int status;
	int i;
	char *args;
	const char *node = "";
	int len;
	int dmeventd_mode;
	int saved_errno;
	lvm_response_t *response = NULL;
	int num_responses;

	assert(name);

	len = strlen(name) + 3;
	args = alloca(len);
	strcpy(args + 2, name);

	/* args[0] holds bottom 8 bits except LCK_LOCAL (0x40). */
	args[0] = flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_NONBLOCK | LCK_HOLD | LCK_CLUSTER_VG); 

	args[1] = 0;

	if (flags & LCK_ORIGIN_ONLY)
		args[1] |= LCK_ORIGIN_ONLY_MODE;

	if (flags & LCK_REVERT)
		args[1] |= LCK_REVERT_MODE;

	if (mirror_in_sync())
		args[1] |= LCK_MIRROR_NOSYNC_MODE;

	if (test_mode())
		args[1] |= LCK_TEST_MODE;

	/*
	 * We propagate dmeventd_monitor_mode() to clvmd faithfully, since
	 * dmeventd monitoring is tied to activation which happens inside clvmd
	 * when locking_type = 3.
	 */
	dmeventd_mode = dmeventd_monitor_mode();
	if (dmeventd_mode == DMEVENTD_MONITOR_IGNORE)
		args[1] |= LCK_DMEVENTD_MONITOR_IGNORE;

	if (dmeventd_mode)
		args[1] |= LCK_DMEVENTD_MONITOR_MODE;

	if (cmd->partial_activation)
		args[1] |= LCK_PARTIAL_MODE;

	/*
	 * VG locks are just that: locks, and have no side effects
	 * so we only need to do them on the local node because all
	 * locks are cluster-wide.
	 *
	 * P_ locks /do/ get distributed across the cluster because they might
	 * have side-effects.
	 *
	 * SYNC_NAMES and VG_BACKUP use the VG name directly without prefix.
	 */
	if (clvmd_cmd == CLVMD_CMD_SYNC_NAMES) {
		if (flags & LCK_LOCAL)
			node = NODE_LOCAL;
	} else if (clvmd_cmd != CLVMD_CMD_VG_BACKUP) {
		if (strncmp(name, "P_", 2) &&
		    (clvmd_cmd == CLVMD_CMD_LOCK_VG ||
		     (flags & LCK_LOCAL) ||
		     !(flags & LCK_CLUSTER_VG)))
			node = NODE_LOCAL;
		else if (flags & LCK_REMOTE)
			node = NODE_REMOTE;
	}

	status = _cluster_request(clvmd_cmd, node, args, len,
				  &response, &num_responses);

	/* If any nodes were down then display them and return an error */
	for (i = 0; i < num_responses; i++) {
		if (response[i].status == EHOSTDOWN) {
			log_error("clvmd not running on node %s",
				  response[i].node);
			status = 0;
			errno = response[i].status;
		} else if (response[i].status) {
			log_error("Error locking on node %s: %s",
				  response[i].node,
				  response[i].response[0] ?
				  	response[i].response :
				  	strerror(response[i].status));
			status = 0;
			errno = response[i].status;
		}
	}

	saved_errno = errno;
	_cluster_free_request(response, num_responses);
	errno = saved_errno;

	return status;
}