Exemplo n.º 1
0
int vg_add_snapshot(struct logical_volume *origin,
		    struct logical_volume *cow, union lvid *lvid,
		    uint32_t extent_count, uint32_t chunk_size)
{
	struct logical_volume *snap;
	struct lv_segment *seg;

	/*
	 * Is the cow device already being used ?
	 */
	if (lv_is_cow(cow)) {
		log_error("'%s' is already in use as a snapshot.", cow->name);
		return 0;
	}

	if (cow == origin) {
		log_error("Snapshot and origin LVs must differ.");
		return 0;
	}

	if (!(snap = lv_create_empty("snapshot%d",
				     lvid, LVM_READ | LVM_WRITE | VISIBLE_LV,
				     ALLOC_INHERIT, origin->vg)))
		return_0;

	snap->le_count = extent_count;

	if (!(seg = alloc_snapshot_seg(snap, 0, 0)))
		return_0;

	init_snapshot_seg(seg, origin, cow, chunk_size);

	return 1;
}
Exemplo n.º 2
0
static percent_t _snap_percent(const struct logical_volume *lv) {
    percent_t perc;

    if (!lv_is_cow(lv) || !lv_snapshot_percent(lv, &perc))
        perc = PERCENT_INVALID;

    return perc;
}
Exemplo n.º 3
0
static dm_percent_t _snap_percent(const struct logical_volume *lv)
{
	dm_percent_t percent;

	if (!lv_is_cow(lv) || !lv_snapshot_percent(lv, &percent))
		percent = DM_PERCENT_INVALID;

	return percent;
}
Exemplo n.º 4
0
int lv_is_merging_cow(const struct logical_volume *cow)
{
	struct lv_segment *snap_seg;

	if (!lv_is_cow(cow))
		return 0;

	snap_seg = find_snapshot(cow);

	/* checks lv_segment's status to see if snapshot is merging */
	return (snap_seg && (snap_seg->status & MERGING)) ? 1 : 0;
}
Exemplo n.º 5
0
static percent_t _data_percent(const struct logical_volume *lv)
{
    percent_t perc;

    if (lv_is_cow(lv))
        return _snap_percent(lv);

    if (lv_is_thin_volume(lv))
        return lv_thin_percent(lv, 0, &perc) ? perc : PERCENT_INVALID;

    return lv_thin_pool_percent(lv, 0, &perc) ? perc : PERCENT_INVALID;
}
Exemplo n.º 6
0
int lv_is_visible(const struct logical_volume *lv)
{
	if (lv->status & SNAPSHOT)
		return 0;

	if (lv_is_cow(lv)) {
		if (lv_is_virtual_origin(origin_from_cow(lv)))
			return 1;

		return lv_is_visible(origin_from_cow(lv));
	}

	return lv->status & VISIBLE_LV ? 1 : 0;
}
Exemplo n.º 7
0
static int _lvchange_activate(struct cmd_context *cmd, struct logical_volume *lv)
{
	int activate;

	activate = arg_uint_value(cmd, activate_ARG, 0);

	if (lv_is_cow(lv) && !lv_is_virtual_origin(origin_from_cow(lv)))
		lv = origin_from_cow(lv);

	if (activate == CHANGE_AAY) {
		if (!lv_passes_auto_activation_filter(cmd, lv))
			return 1;
		activate = CHANGE_ALY;
	}

	if (activate == CHANGE_ALN) {
		log_verbose("Deactivating logical volume \"%s\" locally",
			    lv->name);
		if (!deactivate_lv_local(cmd, lv))
			return_0;
	} else if (activate == CHANGE_AN) {
		log_verbose("Deactivating logical volume \"%s\"", lv->name);
		if (!deactivate_lv(cmd, lv))
			return_0;
	} else {
		if ((activate == CHANGE_AE) ||
		    lv_is_origin(lv) ||
		    lv_is_thin_type(lv)) {
			log_verbose("Activating logical volume \"%s\" "
				    "exclusively", lv->name);
			if (!activate_lv_excl(cmd, lv))
				return_0;
		} else if (activate == CHANGE_ALY) {
			log_verbose("Activating logical volume \"%s\" locally",
				    lv->name);
			if (!activate_lv_local(cmd, lv))
				return_0;
		} else {
			log_verbose("Activating logical volume \"%s\"",
				    lv->name);
			if (!activate_lv(cmd, lv))
				return_0;
		}

		if (background_polling())
			lv_spawn_background_polling(cmd, lv);
	}

	return 1;
}
Exemplo n.º 8
0
/* Check if given LV is usable as snapshot origin LV */
int validate_snapshot_origin(const struct logical_volume *origin_lv)
{
	const char *err = NULL; /* For error string */

	if (lv_is_cow(origin_lv))
		err = "snapshots";
	else if (lv_is_locked(origin_lv))
		err = "locked volumes";
	else if (lv_is_pvmove(origin_lv))
		err = "pvmoved volumes";
	else if (!lv_is_visible(origin_lv))
		err = "hidden volumes";
	else if (lv_is_merging_origin(origin_lv))
		err = "an origin that has a merging snapshot";
	else if (lv_is_cache_type(origin_lv) && !lv_is_cache(origin_lv))
		err = "cache type volumes";
	else if (lv_is_thin_type(origin_lv) && !lv_is_thin_volume(origin_lv))
		err = "thin pool type volumes";
	else if (lv_is_mirror_type(origin_lv)) {
		if (!lv_is_mirror(origin_lv))
			err = "mirror subvolumes";
		else {
			log_warn("WARNING: Snapshots of mirrors can deadlock under rare device failures.");
			log_warn("WARNING: Consider using the raid1 mirror type to avoid this.");
			log_warn("WARNING: See global/mirror_segtype_default in lvm.conf.");
		}
	} else if (lv_is_raid_type(origin_lv) && !lv_is_raid(origin_lv))
		err = "raid subvolumes";

	if (err) {
		log_error("Snapshots of %s are not supported.", err);
		return 0;
	}

	if (vg_is_clustered(origin_lv->vg) && lv_is_active(origin_lv) &&
	    !lv_is_active_exclusive_locally(origin_lv)) {
		log_error("Snapshot origin must be active exclusively.");
		return 0;
	}

	return 1;
}
Exemplo n.º 9
0
int lv_is_visible(const struct logical_volume *lv)
{
	if (lv_is_historical(lv))
		return 1;

	if (lv_is_snapshot(lv))
		return 0;

	if (lv_is_cow(lv)) {
		if (lv_is_virtual_origin(origin_from_cow(lv)))
			return 1;

		if (lv_is_merging_cow(lv))
			return 0;

		return lv_is_visible(origin_from_cow(lv));
	}

	return lv->status & VISIBLE_LV ? 1 : 0;
}
Exemplo n.º 10
0
static dm_percent_t _data_percent(const struct logical_volume *lv)
{
	dm_percent_t percent;
	struct lv_status_cache *status;

	if (lv_is_cow(lv))
		return _snap_percent(lv);

	if (lv_is_cache(lv) || lv_is_cache_pool(lv)) {
		if (!lv_cache_status(lv, &status)) {
			stack;
			return DM_PERCENT_INVALID;
		}
		percent = status->dirty_usage;
		dm_pool_destroy(status->mem);
		return percent;
	}

	if (lv_is_thin_volume(lv))
		return lv_thin_percent(lv, 0, &percent) ? percent : DM_PERCENT_INVALID;

	return lv_thin_pool_percent(lv, 0, &percent) ? percent : DM_PERCENT_INVALID;
}
Exemplo n.º 11
0
int lv_is_cow_covering_origin(const struct logical_volume *lv)
{
	return lv_is_cow(lv) &&
		(lv->size >= _cow_max_size(lv->vg->cmd, origin_from_cow(lv)->size,
					   find_snapshot(lv)->chunk_size));
}
Exemplo n.º 12
0
static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
			   void *handle) // __attribute((unused)))
{
	struct volume_group *vg;
	struct lvinfo info;
	struct logical_volume *origin = NULL;

	vg = lv->vg;

	if (!vg_check_status(vg, LVM_WRITE))
		return ECMD_FAILED;

	if (lv_is_origin(lv)) {
		log_error("Can't remove logical volume \"%s\" under snapshot",
			  lv->name);
		return ECMD_FAILED;
	}

	if (lv->status & MIRROR_IMAGE) {
		log_error("Can't remove logical volume %s used by a mirror",
			  lv->name);
		return ECMD_FAILED;
	}

	if (lv->status & MIRROR_LOG) {
		log_error("Can't remove logical volume %s used as mirror log",
			  lv->name);
		return ECMD_FAILED;
	}

	if (lv->status & LOCKED) {
		log_error("Can't remove locked LV %s", lv->name);
		return ECMD_FAILED;
	}

	/* FIXME Ensure not referred to by another existing LVs */

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

		if (info.exists && !arg_count(cmd, force_ARG)) {
			if (yes_no_prompt("Do you really want to remove active "
					  "logical volume \"%s\"? [y/n]: ",
					  lv->name) == 'n') {
				log_print("Logical volume \"%s\" not removed",
					  lv->name);
				return ECMD_FAILED;
			}
		}
	}

	if (!archive(vg))
		return ECMD_FAILED;

	/* If the VG is clustered then make sure no-one else is using the LV
	   we are about to remove */
	if (vg_status(vg) & CLUSTERED) {
		if (!activate_lv_excl(cmd, lv)) {
			log_error("Can't get exclusive access to volume \"%s\"",
				  lv->name);
			return ECMD_FAILED;
		}
	}

	/* FIXME Snapshot commit out of sequence if it fails after here? */
	if (!deactivate_lv(cmd, lv)) {
		log_error("Unable to deactivate logical volume \"%s\"",
			  lv->name);
		return ECMD_FAILED;
	}

	if (lv_is_cow(lv)) {
		origin = origin_from_cow(lv);
		log_verbose("Removing snapshot %s", lv->name);
		if (!vg_remove_snapshot(lv)) {
			stack;
			return ECMD_FAILED;
		}
	}

	log_verbose("Releasing logical volume \"%s\"", lv->name);
	if (!lv_remove(lv)) {
		log_error("Error releasing logical volume \"%s\"", lv->name);
		return ECMD_FAILED;
	}

	/* store it on disks */
	if (!vg_write(vg))
		return ECMD_FAILED;

	backup(vg);

	if (!vg_commit(vg))
		return ECMD_FAILED;

	/* If no snapshots left, reload without -real. */
	if (origin && !lv_is_origin(origin)) {
		if (!suspend_lv(cmd, origin))
			log_error("Failed to refresh %s without snapshot.", origin->name);
		else if (!resume_lv(cmd, origin))
			log_error("Failed to resume %s.", origin->name);
	}

	log_print("Logical volume \"%s\" successfully removed", lv->name);
	return ECMD_PROCESSED;
}