1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

raid0: Add raid0_meta segment type.

This commit is contained in:
Alasdair G Kergon 2016-07-01 22:20:54 +01:00
parent 1df9822224
commit d8c2677ab9
10 changed files with 565 additions and 266 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.159 - Version 2.02.159 -
================================= =================================
Add raid0_meta segment type that provides metadata space for raid conversions.
Fix created link for a used pool for vgmknode. Fix created link for a used pool for vgmknode.
Introduce and use is_power_of_2 macro. Introduce and use is_power_of_2 macro.
Support conversions between striped and raid0 segment types. Support conversions between striped and raid0 segment types.

View File

@ -115,6 +115,7 @@ enum {
LV_TYPE_SPARE, LV_TYPE_SPARE,
LV_TYPE_VIRTUAL, LV_TYPE_VIRTUAL,
LV_TYPE_RAID0, LV_TYPE_RAID0,
LV_TYPE_RAID0_META,
LV_TYPE_RAID1, LV_TYPE_RAID1,
LV_TYPE_RAID10, LV_TYPE_RAID10,
LV_TYPE_RAID4, LV_TYPE_RAID4,
@ -164,6 +165,7 @@ static const char *_lv_type_names[] = {
[LV_TYPE_SPARE] = "spare", [LV_TYPE_SPARE] = "spare",
[LV_TYPE_VIRTUAL] = "virtual", [LV_TYPE_VIRTUAL] = "virtual",
[LV_TYPE_RAID0] = SEG_TYPE_NAME_RAID0, [LV_TYPE_RAID0] = SEG_TYPE_NAME_RAID0,
[LV_TYPE_RAID0_META] = SEG_TYPE_NAME_RAID0_META,
[LV_TYPE_RAID1] = SEG_TYPE_NAME_RAID1, [LV_TYPE_RAID1] = SEG_TYPE_NAME_RAID1,
[LV_TYPE_RAID10] = SEG_TYPE_NAME_RAID10, [LV_TYPE_RAID10] = SEG_TYPE_NAME_RAID10,
[LV_TYPE_RAID4] = SEG_TYPE_NAME_RAID4, [LV_TYPE_RAID4] = SEG_TYPE_NAME_RAID4,
@ -929,6 +931,7 @@ struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
} }
if (segtype_is_raid(segtype) && if (segtype_is_raid(segtype) &&
!segtype_is_raid0(segtype) &&
!(seg->meta_areas = dm_pool_zalloc(mem, areas_sz))) { !(seg->meta_areas = dm_pool_zalloc(mem, areas_sz))) {
dm_pool_free(mem, seg); /* frees everything alloced since seg */ dm_pool_free(mem, seg); /* frees everything alloced since seg */
return_NULL; return_NULL;
@ -3809,7 +3812,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
if (seg_is_raid(seg)) { if (seg_is_raid(seg)) {
stripes = 1; stripes = 1;
stripe_size = 0; stripe_size = 0;
if (seg_is_raid0(seg)) if (seg_is_any_raid0(seg))
area_multiple = seg->area_count; area_multiple = seg->area_count;
} }
@ -3960,14 +3963,19 @@ int lv_extend(struct logical_volume *lv,
if (segtype_is_virtual(segtype)) if (segtype_is_virtual(segtype))
return lv_add_virtual_segment(lv, 0u, extents, segtype); return lv_add_virtual_segment(lv, 0u, extents, segtype);
if (!lv->le_count && segtype_is_pool(segtype)) { if (!lv->le_count) {
/* if (segtype_is_pool(segtype))
* Pool allocations treat the metadata device like a mirror log. /*
*/ * Pool allocations treat the metadata device like a mirror log.
/* FIXME Support striped metadata pool */ */
log_count = 1; /* FIXME Support striped metadata pool */
} else if (segtype_is_raid(segtype) && !segtype_is_raid0(segtype) && !lv->le_count) log_count = 1;
log_count = mirrors * stripes; else if (segtype_is_raid0_meta(segtype))
/* Extend raid0 metadata LVs too */
log_count = stripes;
else if (segtype_is_raid(segtype) && !segtype_is_raid0(segtype))
log_count = mirrors * stripes;
}
/* FIXME log_count should be 1 for mirrors */ /* FIXME log_count should be 1 for mirrors */
if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors, if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors,
@ -4961,7 +4969,7 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
seg_size /= seg_mirrors; seg_size /= seg_mirrors;
lp->extents = logical_extents_used + seg_size; lp->extents = logical_extents_used + seg_size;
break; break;
} }
} else if (new_extents <= logical_extents_used + seg_logical_extents) { } else if (new_extents <= logical_extents_used + seg_logical_extents) {
seg_size = new_extents - logical_extents_used; seg_size = new_extents - logical_extents_used;
lp->extents = new_extents; lp->extents = new_extents;

View File

@ -22,6 +22,17 @@
#include "lv_alloc.h" #include "lv_alloc.h"
#include "lvm-string.h" #include "lvm-string.h"
static int _check_restriping(uint32_t new_stripes, struct logical_volume *lv)
{
if (new_stripes && new_stripes != first_seg(lv)->area_count) {
log_error("Cannot restripe LV %s from %" PRIu32 " to %u stripes during conversion.",
display_lvname(lv), first_seg(lv)->area_count, new_stripes);
return 0;
}
return 1;
}
static int _lv_is_raid_with_tracking(const struct logical_volume *lv, static int _lv_is_raid_with_tracking(const struct logical_volume *lv,
struct logical_volume **tracking) struct logical_volume **tracking)
{ {
@ -88,6 +99,9 @@ static int _raid_in_sync(struct logical_volume *lv)
{ {
dm_percent_t sync_percent; dm_percent_t sync_percent;
if (seg_is_striped(first_seg(lv)))
return 1;
if (!lv_raid_percent(lv, &sync_percent)) { if (!lv_raid_percent(lv, &sync_percent)) {
log_error("Unable to determine sync status of %s/%s.", log_error("Unable to determine sync status of %s/%s.",
lv->vg->name, lv->name); lv->vg->name, lv->name);
@ -517,7 +531,8 @@ static int _alloc_image_components(struct logical_volume *lv,
* be allocated from the same PV(s) as the data device. * be allocated from the same PV(s) as the data device.
*/ */
static int _alloc_rmeta_for_lv(struct logical_volume *data_lv, static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
struct logical_volume **meta_lv) struct logical_volume **meta_lv,
struct dm_list *allocate_pvs)
{ {
struct dm_list allocatable_pvs; struct dm_list allocatable_pvs;
struct alloc_handle *ah; struct alloc_handle *ah;
@ -526,6 +541,9 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
dm_list_init(&allocatable_pvs); dm_list_init(&allocatable_pvs);
if (!allocate_pvs)
allocate_pvs = &allocatable_pvs;
if (!seg_is_linear(seg)) { if (!seg_is_linear(seg)) {
log_error(INTERNAL_ERROR "Unable to allocate RAID metadata " log_error(INTERNAL_ERROR "Unable to allocate RAID metadata "
"area for non-linear LV, %s", data_lv->name); "area for non-linear LV, %s", data_lv->name);
@ -603,7 +621,7 @@ static int _raid_add_images(struct logical_volume *lv,
return 0; return 0;
} }
if (!_alloc_rmeta_for_lv(lv, &lvl->lv)) if (!_alloc_rmeta_for_lv(lv, &lvl->lv, NULL))
return_0; return_0;
dm_list_add(&meta_lvs, &lvl->list); dm_list_add(&meta_lvs, &lvl->list);
@ -845,7 +863,7 @@ static int _extract_image_components(struct lv_segment *seg, uint32_t idx,
* Otherwise, leave the [meta_]areas as AREA_UNASSIGNED and * Otherwise, leave the [meta_]areas as AREA_UNASSIGNED and
* seg->area_count unchanged. * seg->area_count unchanged.
* @extracted_[meta|data]_lvs: The LVs removed from the array. If 'shift' * @extracted_[meta|data]_lvs: The LVs removed from the array. If 'shift'
* is set, then there will likely be name conflicts. * is set, then there will likely be name conflicts.
* *
* This function extracts _both_ portions of the indexed image. It * This function extracts _both_ portions of the indexed image. It
* does /not/ commit the results. (IOW, erroring-out requires no unwinding * does /not/ commit the results. (IOW, erroring-out requires no unwinding
@ -1401,7 +1419,7 @@ static int _convert_mirror_to_raid1(struct logical_volume *lv,
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
log_debug_metadata("Allocating new metadata LV for %s", log_debug_metadata("Allocating new metadata LV for %s",
seg_lv(seg, s)->name); seg_lv(seg, s)->name);
if (!_alloc_rmeta_for_lv(seg_lv(seg, s), &(lvl_array[s].lv))) { if (!_alloc_rmeta_for_lv(seg_lv(seg, s), &(lvl_array[s].lv), NULL)) {
log_error("Failed to allocate metadata LV for %s in %s", log_error("Failed to allocate metadata LV for %s in %s",
seg_lv(seg, s)->name, lv->name); seg_lv(seg, s)->name, lv->name);
return 0; return 0;
@ -1813,6 +1831,205 @@ static int _eliminate_extracted_lvs(struct volume_group *vg, struct dm_list *rem
{ {
return _eliminate_extracted_lvs_optional_write_vg(vg, removal_lvs, 1); return _eliminate_extracted_lvs_optional_write_vg(vg, removal_lvs, 1);
} }
static int _avoid_pvs_of_lv(struct logical_volume *lv, void *data)
{
struct dm_list *allocate_pvs = (struct dm_list *) data;
struct pv_list *pvl;
dm_list_iterate_items(pvl, allocate_pvs)
if (!lv_is_partial(lv) && lv_is_on_pv(lv, pvl->pv))
pvl->pv->status |= PV_ALLOCATION_PROHIBITED;
return 1;
}
/*
* Prevent any PVs holding other image components of @lv from being used for allocation
* by setting the internal PV_ALLOCATION_PROHIBITED flag to use it to avoid generating
* pv maps for those PVs.
*/
static int _avoid_pvs_with_other_images_of_lv(struct logical_volume *lv, struct dm_list *allocate_pvs)
{
return for_each_sub_lv(lv, _avoid_pvs_of_lv, allocate_pvs);
}
static void _clear_allocation_prohibited(struct dm_list *pvs)
{
struct pv_list *pvl;
if (pvs)
dm_list_iterate_items(pvl, pvs)
pvl->pv->status &= ~PV_ALLOCATION_PROHIBITED;
}
/*
* Allocate metadata devs for all @new_data_devs and link them to list @new_meta_lvs
*/
static int _alloc_rmeta_devs_for_rimage_devs(struct logical_volume *lv,
struct dm_list *new_data_lvs,
struct dm_list *new_meta_lvs,
struct dm_list *allocate_pvs)
{
uint32_t a = 0, raid_devs = dm_list_size(new_data_lvs);
struct lv_list *lvl, *lvl1, *lvl_array;
if (!raid_devs)
return_0;
if (!(lvl_array = dm_pool_zalloc(lv->vg->vgmem, raid_devs * sizeof(*lvl_array))))
return_0;
dm_list_iterate_items(lvl, new_data_lvs) {
log_debug_metadata("Allocating new metadata LV for %s", lvl->lv->name);
if (!_alloc_rmeta_for_lv(lvl->lv, &lvl_array[a].lv, allocate_pvs)) {
log_error("Failed to allocate metadata LV for %s in %s",
lvl->lv->name, lv->vg->name);
return 0;
}
dm_list_add(new_meta_lvs, &lvl_array[a++].list);
dm_list_iterate_items(lvl1, new_meta_lvs)
if (!_avoid_pvs_with_other_images_of_lv(lvl1->lv, allocate_pvs))
return_0;
}
_clear_allocation_prohibited(allocate_pvs);
return 1;
}
/*
* Allocate metadata devs for all data devs of an LV
*/
static int _alloc_rmeta_devs_for_lv(struct logical_volume *lv,
struct dm_list *meta_lvs,
struct dm_list *allocate_pvs)
{
uint32_t s;
struct lv_list *lvl_array;
struct dm_list data_lvs;
struct lv_segment *seg = first_seg(lv);
dm_list_init(&data_lvs);
if (!(seg->meta_areas = dm_pool_zalloc(lv->vg->vgmem, seg->area_count * sizeof(*seg->meta_areas))))
return 0;
if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, seg->area_count * sizeof(*lvl_array))))
return_0;
for (s = 0; s < seg->area_count; s++) {
lvl_array[s].lv = seg_lv(seg, s);
dm_list_add(&data_lvs, &lvl_array[s].list);
}
if (!_alloc_rmeta_devs_for_rimage_devs(lv, &data_lvs, meta_lvs, allocate_pvs)) {
log_error("Failed to allocate metadata LVs for %s", lv->name);
return 0;
}
return 1;
}
/*
* Add metadata areas to raid0
*/
static int _alloc_and_add_rmeta_devs_for_lv(struct logical_volume *lv, struct dm_list *allocate_pvs)
{
struct lv_segment *seg = first_seg(lv);
struct dm_list meta_lvs;
dm_list_init(&meta_lvs);
log_debug_metadata("Allocating metadata LVs for %s", display_lvname(lv));
if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs, allocate_pvs)) {
log_error("Failed to allocate metadata LVs for %s", display_lvname(lv));
return_0;
}
/* Metadata LVs must be cleared before being added to the array */
log_debug_metadata("Clearing newly allocated metadata LVs for %s", display_lvname(lv));
if (!_clear_lvs(&meta_lvs)) {
log_error("Failed to initialize metadata LVs for %s", display_lvname(lv));
return_0;
}
/* Set segment areas for metadata sub_lvs */
log_debug_metadata("Adding newly allocated metadata LVs to %s", display_lvname(lv));
if (!_add_image_component_list(seg, 1, 0, &meta_lvs, 0)) {
log_error("Failed to add newly allocated metadata LVs to %s", display_lvname(lv));
return_0;
}
return 1;
}
/*
* Add/remove metadata areas to/from raid0
*/
static int _raid0_add_or_remove_metadata_lvs(struct logical_volume *lv,
int update_and_reload,
struct dm_list *allocate_pvs,
struct dm_list *removal_lvs)
{
uint64_t new_raid_type_flag;
struct lv_segment *seg = first_seg(lv);
if (removal_lvs) {
if (seg->meta_areas) {
if (!_extract_image_component_list(seg, RAID_META, 0, removal_lvs))
return_0;
seg->meta_areas = NULL;
}
new_raid_type_flag = SEG_RAID0;
} else {
if (!_alloc_and_add_rmeta_devs_for_lv(lv, allocate_pvs))
return 0;
new_raid_type_flag = SEG_RAID0_META;
}
if (!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, new_raid_type_flag)))
return_0;
if (update_and_reload) {
if (!lv_update_and_reload_origin(lv))
return_0;
/* If any residual LVs, eliminate them, write VG, commit it and take a backup */
return _eliminate_extracted_lvs(lv->vg, removal_lvs);
}
return 1;
}
static int _raid0_meta_change_wrapper(struct logical_volume *lv,
const struct segment_type *new_segtype,
uint32_t new_stripes,
int yes, int force, int alloc_metadata_devs,
struct dm_list *allocate_pvs)
{
struct dm_list removal_lvs;
dm_list_init(&removal_lvs);
if (!_check_restriping(new_stripes, lv))
return_0;
if (!archive(lv->vg))
return_0;
if (alloc_metadata_devs)
return _raid0_add_or_remove_metadata_lvs(lv, 1, allocate_pvs, NULL);
else
return _raid0_add_or_remove_metadata_lvs(lv, 1, allocate_pvs, &removal_lvs);
}
/* /*
* Convert a RAID0 set to striped * Convert a RAID0 set to striped
*/ */
@ -1822,6 +2039,11 @@ static int _convert_raid0_to_striped(struct logical_volume *lv,
{ {
struct lv_segment *seg = first_seg(lv); struct lv_segment *seg = first_seg(lv);
/* Remove metadata devices */
if (seg_is_raid0_meta(seg) &&
!_raid0_add_or_remove_metadata_lvs(lv, 0 /* update_and_reload */, NULL, removal_lvs))
return_0;
/* Move the AREA_PV areas across to new top-level segments of type "striped" */ /* Move the AREA_PV areas across to new top-level segments of type "striped" */
if (!_raid0_to_striped_retrieve_segments_and_lvs(lv, removal_lvs)) { if (!_raid0_to_striped_retrieve_segments_and_lvs(lv, removal_lvs)) {
log_error("Failed to retrieve raid0 segments from %s.", lv->name); log_error("Failed to retrieve raid0 segments from %s.", lv->name);
@ -1851,6 +2073,7 @@ static int _convert_raid0_to_striped(struct logical_volume *lv,
* Optionally updates metadata and reloads mappings. * Optionally updates metadata and reloads mappings.
*/ */
static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv, static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
int alloc_metadata_devs,
int update_and_reload, int update_and_reload,
struct dm_list *allocate_pvs) struct dm_list *allocate_pvs)
{ {
@ -1924,12 +2147,18 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
lv->status |= RAID; lv->status |= RAID;
/* Allocate metadata LVs if requested */
if (alloc_metadata_devs && !_raid0_add_or_remove_metadata_lvs(lv, 0, allocate_pvs, NULL))
return NULL;
if (update_and_reload && !lv_update_and_reload(lv)) if (update_and_reload && !lv_update_and_reload(lv))
return NULL; return NULL;
return raid0_seg; return raid0_seg;
} }
/************************************************/
/* /*
* Individual takeover functions. * Individual takeover functions.
*/ */
@ -1959,7 +2188,9 @@ static int _takeover_noop(TAKEOVER_FN_ARGS)
static int _takeover_unsupported(TAKEOVER_FN_ARGS) static int _takeover_unsupported(TAKEOVER_FN_ARGS)
{ {
log_error("Converting the segment type for %s from %s to %s is not supported.", log_error("Converting the segment type for %s from %s to %s is not supported.",
display_lvname(lv), lvseg_name(first_seg(lv)), new_segtype->name); display_lvname(lv), lvseg_name(first_seg(lv)),
(segtype_is_striped(new_segtype) && !segtype_is_any_raid0(new_segtype) &&
(new_stripes == 1)) ? SEG_TYPE_NAME_LINEAR : new_segtype->name);
return 0; return 0;
} }
@ -1975,10 +2206,12 @@ static int _takeover_not_possible(takeover_fn_t takeover_fn)
return 0; return 0;
} }
static int _takeover_unsupported_yet(const struct logical_volume *lv, const struct segment_type *new_segtype) static int _takeover_unsupported_yet(const struct logical_volume *lv, const unsigned new_stripes, const struct segment_type *new_segtype)
{ {
log_error("Converting the segment type for %s from %s to %s is not supported yet.", log_error("Converting the segment type for %s from %s to %s is not supported yet.",
display_lvname(lv), lvseg_name(first_seg(lv)), new_segtype->name); display_lvname(lv), lvseg_name(first_seg(lv)),
(segtype_is_striped(new_segtype) && !segtype_is_any_raid0(new_segtype) &&
(new_stripes == 1)) ? SEG_TYPE_NAME_LINEAR : new_segtype->name);
return 0; return 0;
} }
@ -1988,32 +2221,32 @@ static int _takeover_unsupported_yet(const struct logical_volume *lv, const stru
*/ */
static int _takeover_from_linear_to_raid0(TAKEOVER_FN_ARGS) static int _takeover_from_linear_to_raid0(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_linear_to_raid1(TAKEOVER_FN_ARGS) static int _takeover_from_linear_to_raid1(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_linear_to_raid10(TAKEOVER_FN_ARGS) static int _takeover_from_linear_to_raid10(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_linear_to_raid45(TAKEOVER_FN_ARGS) static int _takeover_from_linear_to_raid45(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_mirrored_to_raid0(TAKEOVER_FN_ARGS) static int _takeover_from_mirrored_to_raid0(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_mirrored_to_raid0_meta(TAKEOVER_FN_ARGS) static int _takeover_from_mirrored_to_raid0_meta(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_mirrored_to_raid1(TAKEOVER_FN_ARGS) static int _takeover_from_mirrored_to_raid1(TAKEOVER_FN_ARGS)
@ -2023,217 +2256,246 @@ static int _takeover_from_mirrored_to_raid1(TAKEOVER_FN_ARGS)
static int _takeover_from_mirrored_to_raid10(TAKEOVER_FN_ARGS) static int _takeover_from_mirrored_to_raid10(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_mirrored_to_raid45(TAKEOVER_FN_ARGS) static int _takeover_from_mirrored_to_raid45(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid0_to_linear(TAKEOVER_FN_ARGS) static int _takeover_from_raid0_to_linear(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid0_to_mirrored(TAKEOVER_FN_ARGS) static int _takeover_from_raid0_to_mirrored(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid0_to_raid0_meta(TAKEOVER_FN_ARGS) static int _takeover_from_raid0_to_raid0_meta(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); if (!_raid0_meta_change_wrapper(lv, new_segtype, new_stripes, yes, force, 1, allocate_pvs))
return_0;
return 1;
} }
static int _takeover_from_raid0_to_raid1(TAKEOVER_FN_ARGS) static int _takeover_from_raid0_to_raid1(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid0_to_raid10(TAKEOVER_FN_ARGS) static int _takeover_from_raid0_to_raid10(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid0_to_raid45(TAKEOVER_FN_ARGS) static int _takeover_from_raid0_to_raid45(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid0_to_raid6(TAKEOVER_FN_ARGS) static int _takeover_from_raid0_to_raid6(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid0_to_striped(TAKEOVER_FN_ARGS) static int _raid0_to_striped_wrapper(struct logical_volume *lv,
const struct segment_type *new_segtype,
uint32_t new_stripes,
int yes, int force,
struct dm_list *allocate_pvs)
{ {
struct dm_list removal_lvs; struct dm_list removal_lvs;
dm_list_init(&removal_lvs); dm_list_init(&removal_lvs);
/* Archive metadata */ if (!_check_restriping(new_stripes, lv))
if (!archive(lv->vg))
return_0; return_0;
/* FIXME update_and_reload is only needed if the LV is already active */
return _convert_raid0_to_striped(lv, 1, &removal_lvs);
}
/*
static int _takeover_from_raid0_meta_to_linear(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid0_meta_to_mirrored(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid0(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid1(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid10(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid45(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid6(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid0_meta_to_striped(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
*/
static int _takeover_from_raid1_to_linear(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid1_to_mirrored(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid1_to_raid0(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid1_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid1_to_raid1(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid1_to_raid10(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid1_to_raid45(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid1_to_striped(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid45_to_linear(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid45_to_mirrored(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid45_to_raid0(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid45_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid45_to_raid1(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid45_to_raid54(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid45_to_raid6(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid45_to_striped(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid6_to_raid0(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid6_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid6_to_raid45(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _takeover_from_raid6_to_striped(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_segtype);
}
static int _striped_to_raid0_wrapper(struct logical_volume *lv,
const struct segment_type *new_segtype,
int yes, int force, int alloc_metadata_devs,
struct dm_list *allocate_pvs)
{
/* Archive metadata */ /* Archive metadata */
if (!archive(lv->vg)) if (!archive(lv->vg))
return_0; return_0;
/* FIXME update_and_reload is only needed if the LV is already active */ /* FIXME update_and_reload is only needed if the LV is already active */
/* FIXME Some of the validation in here needs moving before the archiving */ /* FIXME Some of the validation in here needs moving before the archiving */
if (!_convert_striped_to_raid0(lv, 1 /* update_and_reload */, allocate_pvs)) if (!_convert_raid0_to_striped(lv, 1 /* update_and_reload */, &removal_lvs))
return_0;
return 1;
}
static int _takeover_from_raid0_to_striped(TAKEOVER_FN_ARGS)
{
if (!_raid0_to_striped_wrapper(lv, new_segtype, new_stripes, yes, force, allocate_pvs))
return_0;
return 1;
}
static int _takeover_from_raid0_meta_to_linear(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid0_meta_to_mirrored(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid0(TAKEOVER_FN_ARGS)
{
if (!_raid0_meta_change_wrapper(lv, new_segtype, new_stripes, yes, force, 0, allocate_pvs))
return_0;
return 1;
}
static int _takeover_from_raid0_meta_to_raid1(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid10(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid45(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid0_meta_to_raid6(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid0_meta_to_striped(TAKEOVER_FN_ARGS)
{
if (!_raid0_to_striped_wrapper(lv, new_segtype, new_stripes, yes, force, allocate_pvs))
return_0;
return 1;
}
static int _takeover_from_raid1_to_linear(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid1_to_mirrored(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid1_to_raid0(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid1_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid1_to_raid1(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid1_to_raid10(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid1_to_raid45(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid1_to_striped(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid45_to_linear(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid45_to_mirrored(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid45_to_raid0(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid45_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid45_to_raid1(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid45_to_raid54(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid45_to_raid6(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid45_to_striped(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid6_to_raid0(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid6_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid6_to_raid45(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _takeover_from_raid6_to_striped(TAKEOVER_FN_ARGS)
{
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
}
static int _striped_to_raid0_wrapper(struct logical_volume *lv,
const struct segment_type *new_segtype,
uint32_t new_stripes,
int yes, int force, int alloc_metadata_devs,
struct dm_list *allocate_pvs)
{
if (!_check_restriping(new_stripes, lv))
return_0;
/* Archive metadata */
if (!archive(lv->vg))
return_0;
/* FIXME update_and_reload is only needed if the LV is already active */
/* FIXME Some of the validation in here needs moving before the archiving */
if (!_convert_striped_to_raid0(lv, alloc_metadata_devs, 1 /* update_and_reload */, allocate_pvs))
return_0; return_0;
return 1; return 1;
@ -2241,88 +2503,94 @@ static int _striped_to_raid0_wrapper(struct logical_volume *lv,
static int _takeover_from_striped_to_raid0(TAKEOVER_FN_ARGS) static int _takeover_from_striped_to_raid0(TAKEOVER_FN_ARGS)
{ {
return _striped_to_raid0_wrapper(lv, new_segtype, yes, force, 0, allocate_pvs); if (!_striped_to_raid0_wrapper(lv, new_segtype, new_stripes, yes, force, 0, allocate_pvs))
return_0;
return 1;
} }
static int _takeover_from_striped_to_raid01(TAKEOVER_FN_ARGS) static int _takeover_from_striped_to_raid01(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_striped_to_raid0_meta(TAKEOVER_FN_ARGS) static int _takeover_from_striped_to_raid0_meta(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); if (!_striped_to_raid0_wrapper(lv, new_segtype, new_stripes, yes, force, 1, allocate_pvs))
return_0;
return 1;
} }
static int _takeover_from_striped_to_raid10(TAKEOVER_FN_ARGS) static int _takeover_from_striped_to_raid10(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_striped_to_raid45(TAKEOVER_FN_ARGS) static int _takeover_from_striped_to_raid45(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_striped_to_raid6(TAKEOVER_FN_ARGS) static int _takeover_from_striped_to_raid6(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
/* /*
static int _takeover_from_raid01_to_raid01(TAKEOVER_FN_ARGS) static int _takeover_from_raid01_to_raid01(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid01_to_raid10(TAKEOVER_FN_ARGS) static int _takeover_from_raid01_to_raid10(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid01_to_striped(TAKEOVER_FN_ARGS) static int _takeover_from_raid01_to_striped(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid10_to_linear(TAKEOVER_FN_ARGS) static int _takeover_from_raid10_to_linear(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid10_to_mirrored(TAKEOVER_FN_ARGS) static int _takeover_from_raid10_to_mirrored(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid10_to_raid0(TAKEOVER_FN_ARGS) static int _takeover_from_raid10_to_raid0(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid10_to_raid01(TAKEOVER_FN_ARGS) static int _takeover_from_raid10_to_raid01(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid10_to_raid0_meta(TAKEOVER_FN_ARGS) static int _takeover_from_raid10_to_raid0_meta(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid10_to_raid1(TAKEOVER_FN_ARGS) static int _takeover_from_raid10_to_raid1(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid10_to_raid10(TAKEOVER_FN_ARGS) static int _takeover_from_raid10_to_raid10(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
static int _takeover_from_raid10_to_striped(TAKEOVER_FN_ARGS) static int _takeover_from_raid10_to_striped(TAKEOVER_FN_ARGS)
{ {
return _takeover_unsupported_yet(lv, new_segtype); return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
} }
*/ */
@ -2336,11 +2604,10 @@ static unsigned _segtype_ix(const struct segment_type *segtype, uint32_t area_co
int i = 2, j; int i = 2, j;
/* Linear special case */ /* Linear special case */
if (segtype_is_striped(segtype)) { if (segtype_is_striped(segtype) && !segtype_is_any_raid0(segtype)) {
if (area_count == 1) if (area_count == 1)
return 0; /* linear */ return 0; /* linear */
if (!segtype_is_raid0(segtype)) return 1; /* striped */
return 1; /* striped */
} }
while ((j = _segtype_index[i++])) while ((j = _segtype_index[i++]))
@ -2401,11 +2668,14 @@ int lv_raid_convert(struct logical_volume *lv,
return 0; return 0;
} }
if (!_check_max_raid_devices(new_image_count))
return_0;
stripes = new_stripes ?: _data_rimages_count(seg, seg->area_count); stripes = new_stripes ?: _data_rimages_count(seg, seg->area_count);
if (segtype_is_striped(new_segtype))
new_image_count = stripes;
if (segtype_is_raid(new_segtype) && !_check_max_raid_devices(new_image_count))
return_0;
/* FIXME Ensure caller does *not* set wrong default value! */ /* FIXME Ensure caller does *not* set wrong default value! */
/* Define new stripe size if not passed in */ /* Define new stripe size if not passed in */
stripe_size = new_stripe_size ?: seg->stripe_size; stripe_size = new_stripe_size ?: seg->stripe_size;
@ -2414,7 +2684,12 @@ int lv_raid_convert(struct logical_volume *lv,
/* Exit without doing activation checks if the combination isn't possible */ /* Exit without doing activation checks if the combination isn't possible */
if (_takeover_not_possible(takeover_fn)) if (_takeover_not_possible(takeover_fn))
return takeover_fn(lv, new_segtype, yes, force, new_image_count, new_stripes, new_stripe_size, allocate_pvs); return takeover_fn(lv, new_segtype, yes, force, new_image_count, new_stripes, stripe_size, allocate_pvs);
log_verbose("Converting %s from %s to %s.",
display_lvname(lv), lvseg_name(first_seg(lv)),
(segtype_is_striped(new_segtype) && !segtype_is_any_raid0(new_segtype) &&
(new_stripes == 1)) ? SEG_TYPE_NAME_LINEAR : new_segtype->name);
/* FIXME If not active, prompt and activate */ /* FIXME If not active, prompt and activate */
/* FIXME Some operations do not require the LV to be active */ /* FIXME Some operations do not require the LV to be active */
@ -2439,7 +2714,7 @@ int lv_raid_convert(struct logical_volume *lv,
return 0; return 0;
} }
return takeover_fn(lv, new_segtype, yes, force, new_image_count, new_stripes, new_stripe_size, allocate_pvs); return takeover_fn(lv, new_segtype, yes, force, new_image_count, new_stripes, stripe_size, allocate_pvs);
} }
static int _remove_partial_multi_segment_image(struct logical_volume *lv, static int _remove_partial_multi_segment_image(struct logical_volume *lv,
@ -2520,28 +2795,6 @@ has_enough_space:
return 1; return 1;
} }
static int _avoid_pvs_of_lv(struct logical_volume *lv, void *data)
{
struct dm_list *allocate_pvs = (struct dm_list *) data;
struct pv_list *pvl;
dm_list_iterate_items(pvl, allocate_pvs)
if (!lv_is_partial(lv) && lv_is_on_pv(lv, pvl->pv))
pvl->pv->status |= PV_ALLOCATION_PROHIBITED;
return 1;
}
/*
* Prevent any PVs holding other image components of @lv from being used for allocation
* by setting the internal PV_ALLOCATION_PROHIBITED flag to use it to avoid generating
* pv maps for those PVs.
*/
static int _avoid_pvs_with_other_images_of_lv(struct logical_volume *lv, struct dm_list *allocate_pvs)
{
return for_each_sub_lv(lv, _avoid_pvs_of_lv, allocate_pvs);
}
/* /*
* lv_raid_replace * lv_raid_replace
* @lv * @lv

View File

@ -22,6 +22,10 @@ struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
{ {
struct segment_type *segtype; struct segment_type *segtype;
/* FIXME Register this properly within striped.c */
if (!strcmp(str, SEG_TYPE_NAME_LINEAR))
str = SEG_TYPE_NAME_STRIPED;
dm_list_iterate_items(segtype, &cmd->segtypes) dm_list_iterate_items(segtype, &cmd->segtypes)
if (!strcmp(segtype->name, str)) if (!strcmp(segtype->name, str))
return segtype; return segtype;

View File

@ -48,6 +48,7 @@ struct dev_manager;
#define SEG_CAN_ERROR_WHEN_FULL 0x0000000000020000ULL #define SEG_CAN_ERROR_WHEN_FULL 0x0000000000020000ULL
#define SEG_RAID0 0x0000000000040000ULL #define SEG_RAID0 0x0000000000040000ULL
#define SEG_RAID0_META 0x0000000000080000ULL
#define SEG_RAID1 0x0000000000100000ULL #define SEG_RAID1 0x0000000000100000ULL
#define SEG_RAID10 0x0000000000200000ULL #define SEG_RAID10 0x0000000000200000ULL
#define SEG_RAID4 0x0000000000400000ULL #define SEG_RAID4 0x0000000000400000ULL
@ -82,6 +83,7 @@ struct dev_manager;
#define SEG_TYPE_NAME_ZERO "zero" #define SEG_TYPE_NAME_ZERO "zero"
#define SEG_TYPE_NAME_RAID "raid" #define SEG_TYPE_NAME_RAID "raid"
#define SEG_TYPE_NAME_RAID0 "raid0" #define SEG_TYPE_NAME_RAID0 "raid0"
#define SEG_TYPE_NAME_RAID0_META "raid0_meta"
#define SEG_TYPE_NAME_RAID1 "raid1" #define SEG_TYPE_NAME_RAID1 "raid1"
#define SEG_TYPE_NAME_RAID10 "raid10" #define SEG_TYPE_NAME_RAID10 "raid10"
#define SEG_TYPE_NAME_RAID4 "raid4" #define SEG_TYPE_NAME_RAID4 "raid4"
@ -102,7 +104,8 @@ struct dev_manager;
#define segtype_is_mirror(segtype) ((segtype)->flags & SEG_MIRROR ? 1 : 0) #define segtype_is_mirror(segtype) ((segtype)->flags & SEG_MIRROR ? 1 : 0)
#define segtype_is_pool(segtype) ((segtype)->flags & (SEG_CACHE_POOL | SEG_THIN_POOL) ? 1 : 0) #define segtype_is_pool(segtype) ((segtype)->flags & (SEG_CACHE_POOL | SEG_THIN_POOL) ? 1 : 0)
#define segtype_is_raid0(segtype) ((segtype)->flags & SEG_RAID0 ? 1 : 0) #define segtype_is_raid0(segtype) ((segtype)->flags & SEG_RAID0 ? 1 : 0)
#define segtype_is_any_raid0(segtype) ((segtype)->flags & SEG_RAID0 ? 1 : 0) #define segtype_is_raid0_meta(segtype) ((segtype)->flags & SEG_RAID0_META ? 1 : 0)
#define segtype_is_any_raid0(segtype) ((segtype)->flags & (SEG_RAID0 | SEG_RAID0_META) ? 1 : 0)
#define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0) #define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0)
#define segtype_is_raid1(segtype) ((segtype)->flags & SEG_RAID1 ? 1 : 0) #define segtype_is_raid1(segtype) ((segtype)->flags & SEG_RAID1 ? 1 : 0)
#define segtype_is_raid4(segtype) ((segtype)->flags & SEG_RAID4 ? 1 : 0) #define segtype_is_raid4(segtype) ((segtype)->flags & SEG_RAID4 ? 1 : 0)
@ -135,6 +138,7 @@ struct dev_manager;
#define seg_is_mirrored(seg) segtype_is_mirrored((seg)->segtype) #define seg_is_mirrored(seg) segtype_is_mirrored((seg)->segtype)
#define seg_is_pool(seg) segtype_is_pool((seg)->segtype) #define seg_is_pool(seg) segtype_is_pool((seg)->segtype)
#define seg_is_raid0(seg) segtype_is_raid0((seg)->segtype) #define seg_is_raid0(seg) segtype_is_raid0((seg)->segtype)
#define seg_is_raid0_meta(seg) segtype_is_raid0_meta((seg)->segtype)
#define seg_is_any_raid0(seg) segtype_is_any_raid0((seg)->segtype) #define seg_is_any_raid0(seg) segtype_is_any_raid0((seg)->segtype)
#define seg_is_raid(seg) segtype_is_raid((seg)->segtype) #define seg_is_raid(seg) segtype_is_raid((seg)->segtype)
#define seg_is_raid1(seg) segtype_is_raid1((seg)->segtype) #define seg_is_raid1(seg) segtype_is_raid1((seg)->segtype)

View File

@ -84,7 +84,7 @@ static uint64_t _segtype_index[] = {
1, /* striped */ 1, /* striped */
SEG_MIRROR, SEG_MIRROR,
SEG_RAID0, SEG_RAID0,
// SEG_RAID0_META, SEG_RAID0_META,
SEG_RAID1, SEG_RAID1,
SEG_RAID4 | SEG_RAID5_LS | SEG_RAID5_LA | SEG_RAID5_LS | SEG_RAID5_RS | SEG_RAID5_RA | SEG_RAID5_N, SEG_RAID4 | SEG_RAID5_LS | SEG_RAID5_LA | SEG_RAID5_LS | SEG_RAID5_RS | SEG_RAID5_RA | SEG_RAID5_N,
SEG_RAID6_LS_6 | SEG_RAID6_LA_6 | SEG_RAID6_RS_6 | SEG_RAID6_RA_6 | SEG_RAID6_NC | SEG_RAID6_NR | SEG_RAID6_ZR | SEG_RAID6_N_6, SEG_RAID6_LS_6 | SEG_RAID6_LA_6 | SEG_RAID6_RS_6 | SEG_RAID6_RA_6 | SEG_RAID6_NC | SEG_RAID6_NR | SEG_RAID6_ZR | SEG_RAID6_N_6,
@ -108,7 +108,7 @@ static takeover_fn_t _takeover_fns[][11] = {
/* striped */ { X , N , X , str_r0, str_r0m, lin_r1, str_r45, str_r6, str_r10, str_r01, X }, /* striped */ { X , N , X , str_r0, str_r0m, lin_r1, str_r45, str_r6, str_r10, str_r01, X },
/* mirror */ { X , X , N , mir_r0, mir_r0m, mir_r1, mir_r45, X , mir_r10, X , X }, /* mirror */ { X , X , N , mir_r0, mir_r0m, mir_r1, mir_r45, X , mir_r10, X , X },
/* raid0 */ { r0__lin, r0__str, r0__mir, N , r0__r0m, r0__r1, r0__r45, r0__r6, r0__r10, X , X }, /* raid0 */ { r0__lin, r0__str, r0__mir, N , r0__r0m, r0__r1, r0__r45, r0__r6, r0__r10, X , X },
/* raid0_meta */ // { r0m_lin, r0m_str, r0m_mir, r0m_r0, N , r0m_r1, r0m_r45, r0m_r6, r0m_r10, X , X }, /* raid0_meta */ { r0m_lin, r0m_str, r0m_mir, r0m_r0, N , r0m_r1, r0m_r45, r0m_r6, r0m_r10, X , X },
/* raid1 */ { r1__lin, r1__str, r1__mir, r1__r0, r1__r0m, r1__r1, r1__r45, X , r1__r10, X , X }, /* raid1 */ { r1__lin, r1__str, r1__mir, r1__r0, r1__r0m, r1__r1, r1__r45, X , r1__r10, X , X },
/* raid4/5 */ { r45_lin, r45_str, r45_mir, r45_r0, r45_r0m, r45_r1, r45_r54, r45_r6, X , X , X }, /* raid4/5 */ { r45_lin, r45_str, r45_mir, r45_r0, r45_r0m, r45_r1, r45_r54, r45_r6, X , X , X },
/* raid6 */ { X , r6__str, X , r6__r0, r6__r0m, X , r6__r45, X , X , X , X }, /* raid6 */ { X , r6__str, X , r6__r0, r6__r0m, X , r6__r45, X , X , X , X },

View File

@ -153,7 +153,7 @@ static int _raid_text_import(struct lv_segment *seg,
} }
} }
if (!dm_config_get_list(sn, seg_is_any_raid0(seg) ? "raid0_lvs" : "raids", &cv)) { if (!dm_config_get_list(sn, seg_is_raid0(seg) ? "raid0_lvs" : "raids", &cv)) {
log_error("Couldn't find RAID array for " log_error("Couldn't find RAID array for "
"segment %s of logical volume %s.", "segment %s of logical volume %s.",
dm_config_parent_name(sn), seg->lv->name); dm_config_parent_name(sn), seg->lv->name);
@ -179,7 +179,7 @@ static int _raid_text_export_raid0(const struct lv_segment *seg, struct formatte
if (seg->stripe_size) if (seg->stripe_size)
outf(f, "stripe_size = %" PRIu32, seg->stripe_size); outf(f, "stripe_size = %" PRIu32, seg->stripe_size);
return out_areas(f, seg, "raid0_lv"); return out_areas(f, seg, seg_is_raid0(seg) ? "raid0_lv" : "raid");
} }
static int _raid_text_export_raid(const struct lv_segment *seg, struct formatter *f) static int _raid_text_export_raid(const struct lv_segment *seg, struct formatter *f)
@ -469,19 +469,20 @@ static const struct raid_type {
unsigned parity; unsigned parity;
uint64_t extra_flags; uint64_t extra_flags;
} _raid_types[] = { } _raid_types[] = {
{ SEG_TYPE_NAME_RAID0, 0, SEG_RAID0 | SEG_AREAS_STRIPED }, { SEG_TYPE_NAME_RAID0, 0, SEG_RAID0 | SEG_AREAS_STRIPED },
{ SEG_TYPE_NAME_RAID1, 0, SEG_RAID1 | SEG_AREAS_MIRRORED }, { SEG_TYPE_NAME_RAID0_META, 0, SEG_RAID0_META | SEG_AREAS_STRIPED },
{ SEG_TYPE_NAME_RAID10, 0, SEG_RAID10 | SEG_AREAS_MIRRORED }, { SEG_TYPE_NAME_RAID1, 0, SEG_RAID1 | SEG_AREAS_MIRRORED },
{ SEG_TYPE_NAME_RAID4, 1, SEG_RAID4 }, { SEG_TYPE_NAME_RAID10, 0, SEG_RAID10 | SEG_AREAS_MIRRORED },
{ SEG_TYPE_NAME_RAID5, 1, SEG_RAID5 }, { SEG_TYPE_NAME_RAID4, 1, SEG_RAID4 },
{ SEG_TYPE_NAME_RAID5_LA, 1, SEG_RAID5_LA }, { SEG_TYPE_NAME_RAID5, 1, SEG_RAID5 },
{ SEG_TYPE_NAME_RAID5_LS, 1, SEG_RAID5_LS }, { SEG_TYPE_NAME_RAID5_LA, 1, SEG_RAID5_LA },
{ SEG_TYPE_NAME_RAID5_RA, 1, SEG_RAID5_RA }, { SEG_TYPE_NAME_RAID5_LS, 1, SEG_RAID5_LS },
{ SEG_TYPE_NAME_RAID5_RS, 1, SEG_RAID5_RS }, { SEG_TYPE_NAME_RAID5_RA, 1, SEG_RAID5_RA },
{ SEG_TYPE_NAME_RAID6, 2, SEG_RAID6 }, { SEG_TYPE_NAME_RAID5_RS, 1, SEG_RAID5_RS },
{ SEG_TYPE_NAME_RAID6_NC, 2, SEG_RAID6_NC }, { SEG_TYPE_NAME_RAID6, 2, SEG_RAID6 },
{ SEG_TYPE_NAME_RAID6_NR, 2, SEG_RAID6_NR }, { SEG_TYPE_NAME_RAID6_NC, 2, SEG_RAID6_NC },
{ SEG_TYPE_NAME_RAID6_ZR, 2, SEG_RAID6_ZR } { SEG_TYPE_NAME_RAID6_NR, 2, SEG_RAID6_NR },
{ SEG_TYPE_NAME_RAID6_ZR, 2, SEG_RAID6_ZR }
}; };
static struct segment_type *_init_raid_segtype(struct cmd_context *cmd, static struct segment_type *_init_raid_segtype(struct cmd_context *cmd,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved. * Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved.
* *
* This file is part of the device-mapper userspace tools. * This file is part of the device-mapper userspace tools.
* *
@ -43,6 +43,7 @@ enum {
SEG_THIN_POOL, SEG_THIN_POOL,
SEG_THIN, SEG_THIN,
SEG_RAID0, SEG_RAID0,
SEG_RAID0_META,
SEG_RAID1, SEG_RAID1,
SEG_RAID10, SEG_RAID10,
SEG_RAID4, SEG_RAID4,
@ -76,6 +77,7 @@ static const struct {
{ SEG_THIN_POOL, "thin-pool"}, { SEG_THIN_POOL, "thin-pool"},
{ SEG_THIN, "thin"}, { SEG_THIN, "thin"},
{ SEG_RAID0, "raid0"}, { SEG_RAID0, "raid0"},
{ SEG_RAID0_META, "raid0_meta"},
{ SEG_RAID1, "raid1"}, { SEG_RAID1, "raid1"},
{ SEG_RAID10, "raid10"}, { SEG_RAID10, "raid10"},
{ SEG_RAID4, "raid4"}, { SEG_RAID4, "raid4"},
@ -2134,6 +2136,7 @@ static int _emit_areas_line(struct dm_task *dmt __attribute__((unused)),
} }
break; break;
case SEG_RAID0: case SEG_RAID0:
case SEG_RAID0_META:
case SEG_RAID1: case SEG_RAID1:
case SEG_RAID10: case SEG_RAID10:
case SEG_RAID4: case SEG_RAID4:
@ -2353,6 +2356,7 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
uint32_t i; uint32_t i;
int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */ int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */
int pos = 0; int pos = 0;
unsigned type = seg->type;
if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC)) if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC))
param_count++; param_count++;
@ -2366,10 +2370,14 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
param_count += _get_params_count(seg->rebuilds); param_count += _get_params_count(seg->rebuilds);
param_count += _get_params_count(seg->writemostly); param_count += _get_params_count(seg->writemostly);
if ((seg->type == SEG_RAID1) && seg->stripe_size) if ((type == SEG_RAID1) && seg->stripe_size)
log_error("WARNING: Ignoring RAID1 stripe size"); log_error("WARNING: Ignoring RAID1 stripe size");
EMIT_PARAMS(pos, "%s %d %u", _dm_segtypes[seg->type].target, /* Kernel only expects "raid0", not "raid0_meta" */
if (type == SEG_RAID0_META)
type = SEG_RAID0;
EMIT_PARAMS(pos, "%s %d %u", _dm_segtypes[type].target,
param_count, seg->stripe_size); param_count, seg->stripe_size);
if (seg->flags & DM_NOSYNC) if (seg->flags & DM_NOSYNC)
@ -2576,6 +2584,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
seg->iv_offset : *seg_start); seg->iv_offset : *seg_start);
break; break;
case SEG_RAID0: case SEG_RAID0:
case SEG_RAID0_META:
case SEG_RAID1: case SEG_RAID1:
case SEG_RAID10: case SEG_RAID10:
case SEG_RAID4: case SEG_RAID4:
@ -3853,6 +3862,7 @@ int dm_tree_node_add_null_area(struct dm_tree_node *node, uint64_t offset)
switch (seg->type) { switch (seg->type) {
case SEG_RAID0: case SEG_RAID0:
case SEG_RAID0_META:
case SEG_RAID1: case SEG_RAID1:
case SEG_RAID4: case SEG_RAID4:
case SEG_RAID5_LA: case SEG_RAID5_LA:

View File

@ -285,7 +285,7 @@ static int _check_conversion_type(struct cmd_context *cmd, const char *type_str)
} }
/* FIXME: Check thin-pool and thin more thoroughly! */ /* FIXME: Check thin-pool and thin more thoroughly! */
if (!strcmp(type_str, "snapshot") || if (!strcmp(type_str, "snapshot") || !strcmp(type_str, "linear") ||
!strcmp(type_str, "striped") || !strcmp(type_str, "striped") ||
!strncmp(type_str, "raid", 4) || !strncmp(type_str, "raid", 4) ||
!strcmp(type_str, "cache-pool") || !strcmp(type_str, "cache") || !strcmp(type_str, "cache-pool") || !strcmp(type_str, "cache") ||
@ -304,7 +304,7 @@ static int _snapshot_type_requested(struct cmd_context *cmd, const char *type_st
static int _raid0_type_requested(struct cmd_context *cmd, const char *type_str) static int _raid0_type_requested(struct cmd_context *cmd, const char *type_str)
{ {
return (!strcmp(type_str, "raid0")); return (!strcmp(type_str, "raid0") || !strcmp(type_str, "raid0_meta"));
} }
/* mirror/raid* (1,10,4,5,6 and their variants) reshape */ /* mirror/raid* (1,10,4,5,6 and their variants) reshape */
@ -316,7 +316,12 @@ static int _mirror_or_raid_type_requested(struct cmd_context *cmd, const char *t
static int _striped_type_requested(struct cmd_context *cmd, const char *type_str) static int _striped_type_requested(struct cmd_context *cmd, const char *type_str)
{ {
return (!strcmp(type_str, "striped")); return (!strcmp(type_str, SEG_TYPE_NAME_STRIPED) || !strcmp(type_str, SEG_TYPE_NAME_LINEAR));
}
static int _linear_type_requested(const char *type_str)
{
return (!strcmp(type_str, SEG_TYPE_NAME_LINEAR));
} }
static int _read_pool_params(struct cmd_context *cmd, int *pargc, char ***pargv, static int _read_pool_params(struct cmd_context *cmd, int *pargc, char ***pargv,
@ -584,7 +589,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->repair || arg_is_set(cmd, thinpool_ARG) || _raid0_type_requested(cmd, lp->type_str) || lp->repair || arg_is_set(cmd, thinpool_ARG) || _raid0_type_requested(cmd, lp->type_str) ||
_striped_type_requested(cmd, lp->type_str))) { _striped_type_requested(cmd, lp->type_str))) {
log_error("--snapshot/--type snapshot or --merge argument " log_error("--snapshot/--type snapshot or --merge argument "
"cannot be mixed with --mirrors/--type mirror/--type raid*/--stripes/--type striped, " "cannot be mixed with --mirrors/--type mirror/--type raid*/--stripes/--type striped/--type linear, "
"--mirrorlog, --repair or --thinpool."); "--mirrorlog, --repair or --thinpool.");
return 0; return 0;
} }
@ -593,7 +598,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
!(_mirror_or_raid_type_requested(cmd, lp->type_str) || _striped_type_requested(cmd, lp->type_str) || !(_mirror_or_raid_type_requested(cmd, lp->type_str) || _striped_type_requested(cmd, lp->type_str) ||
_raid0_type_requested(cmd, lp->type_str) || lp->repair || arg_is_set(cmd, thinpool_ARG))) { _raid0_type_requested(cmd, lp->type_str) || lp->repair || arg_is_set(cmd, thinpool_ARG))) {
log_error("--stripes or --stripesize argument is only valid " log_error("--stripes or --stripesize argument is only valid "
"with --mirrors/--type mirror/--type raid*/--type striped, --repair and --thinpool"); "with --mirrors/--type mirror/--type raid*/--type striped/--type linear, --repair and --thinpool");
return 0; return 0;
} }
@ -769,8 +774,8 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
if (!(lp->segtype = get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG, find_config_tree_str(cmd, global_mirror_segtype_default_CFG, NULL))))) if (!(lp->segtype = get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG, find_config_tree_str(cmd, global_mirror_segtype_default_CFG, NULL)))))
return_0; return_0;
} }
} else if (_raid0_type_requested(cmd, lp->type_str) || _striped_type_requested(cmd, lp->type_str)) { /* striped or raid0 */ } else if (_raid0_type_requested(cmd, lp->type_str) || _striped_type_requested(cmd, lp->type_str)) { /* striped or linear or raid0 */
if (arg_from_list_is_set(cmd, "cannot be used with --type raid0 or --type striped", if (arg_from_list_is_set(cmd, "cannot be used with --type raid0 or --type striped or --type linear",
chunksize_ARG, corelog_ARG, mirrors_ARG, mirrorlog_ARG, regionsize_ARG, zero_ARG, chunksize_ARG, corelog_ARG, mirrors_ARG, mirrorlog_ARG, regionsize_ARG, zero_ARG,
-1)) -1))
return_0; return_0;
@ -778,6 +783,11 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
if (!get_stripe_params(cmd, &lp->stripes, &lp->stripe_size)) if (!get_stripe_params(cmd, &lp->stripes, &lp->stripe_size))
return_0; return_0;
/* FIXME Shouldn't need to override get_stripe_params which defaults to 1 stripe (i.e. linear)! */
/* The default keeps existing number of stripes, handled inside the library code */
if (!arg_is_set(cmd, stripes_long_ARG) && !_linear_type_requested(lp->type_str))
lp->stripes = 0;
if (!(lp->segtype = get_segtype_from_string(cmd, lp->type_str))) if (!(lp->segtype = get_segtype_from_string(cmd, lp->type_str)))
return_0; return_0;
} /* else segtype will default to current type */ } /* else segtype will default to current type */

View File

@ -547,6 +547,13 @@ static int _read_mirror_and_raid_params(struct cmd_context *cmd,
/* Default to 2 mirrored areas if '--type mirror|raid1|raid10' */ /* Default to 2 mirrored areas if '--type mirror|raid1|raid10' */
lp->mirrors = seg_is_mirrored(lp) ? 2 : 1; lp->mirrors = seg_is_mirrored(lp) ? 2 : 1;
if (lp->stripes < 2 && segtype_is_any_raid0(lp->segtype))
if (arg_count(cmd, stripes_ARG)) {
/* User supplied the bad argument */
log_error("Segment type %s requires 2 or more stripes.", lp->segtype->name);
return 0;
}
lp->nosync = arg_is_set(cmd, nosync_ARG); lp->nosync = arg_is_set(cmd, nosync_ARG);
if (!(lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0)) && if (!(lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0)) &&
@ -1238,12 +1245,13 @@ static int _check_raid_parameters(struct volume_group *vg,
lp->segtype->name); lp->segtype->name);
return 0; return 0;
} }
} else if (segtype_is_raid10(lp->segtype)) { } else if (segtype_is_any_raid0(lp->segtype) ||
segtype_is_raid10(lp->segtype)) {
if (!arg_is_set(cmd, stripes_ARG)) if (!arg_is_set(cmd, stripes_ARG))
lp->stripes = devs / lp->mirrors; lp->stripes = devs / lp->mirrors;
if (lp->stripes < 2) { if (lp->stripes < 2) {
log_error("Unable to create RAID10 LV," log_error("Unable to create RAID(1)0 LV: "
" insufficient number of devices."); "insufficient number of devices.");
return 0; return 0;
} }
} }