mirror of
git://sourceware.org/git/lvm2.git
synced 2025-02-24 17:57:48 +03:00
snapshot: relocate common code validation for snapshot origin
Since both lvcreate and lvconvert needs to check for same type of allowed origin for snapshot - move the code into a single function. This way we also fix several inconsitencies where snapshot has been allowed by mistake either through lvcreate or lvconvert path.
This commit is contained in:
parent
0c68c19c32
commit
63c50ced89
@ -7592,56 +7592,9 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
"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))
|
||||
|
@ -1074,6 +1074,9 @@ int vg_add_snapshot(struct logical_volume *origin, struct logical_volume *cow,
|
||||
|
||||
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);
|
||||
|
@ -386,3 +386,47 @@ int vg_remove_snapshot(struct logical_volume *cow)
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1909,13 +1909,7 @@ static int _lvconvert_snapshot(struct cmd_context *cmd,
|
||||
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;
|
||||
}
|
||||
@ -1925,34 +1919,29 @@ static int _lvconvert_snapshot(struct cmd_context *cmd,
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user