"Use --virtualsize.");
return NULL;
}
- if (lv_is_cow(origin_lv)) {
- log_error("Snapshots of snapshots are not supported.");
- return NULL;
- }
- if (lv_is_locked(origin_lv)) {
- log_error("Snapshots of locked devices are not supported.");
- return NULL;
- }
- if (lv_is_merging_origin(origin_lv)) {
- log_error("Snapshots of an origin that has a "
- "merging snapshot is not supported");
- return NULL;
- }
-
- if (lv_is_cache_type(origin_lv) && !lv_is_cache(origin_lv)) {
- log_error("Snapshots of cache type volume %s "
- "is not supported.", display_lvname(origin_lv));
- return NULL;
- }
- if (lv_is_thin_type(origin_lv) && !lv_is_thin_volume(origin_lv)) {
- log_error("Snapshots of thin pool %sdevices "
- "are not supported.",
- lv_is_thin_pool_data(origin_lv) ? "data " :
- lv_is_thin_pool_metadata(origin_lv) ?
- "metadata " : "");
- return NULL;
- }
-
- if (lv_is_mirror_type(origin_lv)) {
- if (!lv_is_mirror(origin_lv)) {
- log_error("Snapshots of mirror subvolumes are not supported.");
- return NULL;
- }
- 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.");
- }
-
- if (lv_is_raid_type(origin_lv) && !lv_is_raid(origin_lv)) {
- log_error("Snapshots of raid subvolumes are not supported.");
- return NULL;
- }
-
- if (vg_is_clustered(vg) && lv_is_active(origin_lv) &&
- !lv_is_active_exclusive_locally(origin_lv)) {
- log_error("%s must be active exclusively to"
- " create snapshot", origin_lv->name);
- return NULL;
- }
+ if (!validate_snapshot_origin(origin_lv))
+ return_0;
}
if (!cow_has_min_chunks(vg, lp->extents, lp->chunk_size))
int vg_remove_snapshot(struct logical_volume *cow);
+int validate_snapshot_origin(const struct logical_volume *origin_lv);
+
+
int vg_check_status(const struct volume_group *vg, uint64_t status);
int vg_check_pv_dev_block_sizes(const struct volume_group *vg);
return 1;
}
+
+/* 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;
+}
uint32_t chunk_size;
int zero;
- if (!(org = find_lv(lv->vg, origin_name))) {
- log_error("Couldn't find origin volume %s in Volume group %s.",
- origin_name, lv->vg->name);
- return 0;
- }
-
- if (org == lv) {
+ if (strcmp(lv->name, origin_name) == 0) {
log_error("Unable to use %s as both snapshot and origin.", snap_name);
return 0;
}
log_error("Chunk size must be a power of 2 in the range 4K to 512K.");
return 0;
}
- log_verbose("Setting chunk size to %s.", display_size(cmd, chunk_size));
if (!cow_has_min_chunks(lv->vg, lv->le_count, chunk_size))
return_0;
+ log_verbose("Setting chunk size to %s.", display_size(cmd, chunk_size));
+
+ if (!(org = find_lv(lv->vg, origin_name))) {
+ log_error("Couldn't find origin volume %s in Volume group %s.",
+ origin_name, lv->vg->name);
+ return 0;
+ }
+
/*
* check_lv_rules() checks cannot be done via command definition
* rules because this LV is not processed by process_each_lv.
*/
- if (lv_is_locked(org) || lv_is_pvmove(org)) {
- log_error("Unable to use LV %s as snapshot origin: LV is %s.",
- display_lvname(lv), lv_is_locked(org) ? "locked" : "pvmove");
- return 0;
- }
/*
* check_lv_types() checks cannot be done via command definition
* LV_foo specification because this LV is not processed by process_each_lv.
*/
- if ((lv_is_cache_type(org) && !lv_is_cache(org)) ||
- (lv_is_thin_type(org) && !lv_is_thin_volume(org)) ||
- (lv_is_mirror_type(org) && !lv_is_mirror(org)) ||
- (lv_is_raid_type(org) && !lv_is_raid(org)) ||
- lv_is_cow(org)) {
- log_error("Unable to use LV %s as snapshot origin: invalid LV type.",
- display_lvname(lv));
- return 0;
- }
+ if (!validate_snapshot_origin(org))
+ return_0;
log_warn("WARNING: Converting logical volume %s to snapshot exception store.",
snap_name);