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

Permit mimage LVs to be striped in lvcreate and lvresize.

This commit is contained in:
Alasdair Kergon 2010-04-09 01:00:10 +00:00
parent fddc256a02
commit 1485ce69c4
9 changed files with 126 additions and 101 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.63 - Version 2.02.63 -
================================ ================================
Permit mimage LVs to be striped in lvcreate and lvresize.
Fix pvmove allocation to take existing parallel stripes into account. Fix pvmove allocation to take existing parallel stripes into account.
Add pvmove_source_seg to struct lv_segment. Add pvmove_source_seg to struct lv_segment.
Fix incorrect removal of symlinks after LV deactivation fails. Fix incorrect removal of symlinks after LV deactivation fails.

View File

@ -526,13 +526,22 @@ struct alloc_handle {
struct dm_list alloced_areas[0]; struct dm_list alloced_areas[0];
}; };
static uint32_t calc_area_multiple(const struct segment_type *segtype, static uint32_t _calc_area_multiple(const struct segment_type *segtype,
const uint32_t area_count) const uint32_t area_count, const uint32_t stripes)
{ {
if (!segtype_is_striped(segtype) || !area_count) if (!area_count)
return 1; return 1;
return area_count; /* Striped */
if (segtype_is_striped(segtype))
return area_count;
/* Mirrored stripes */
if (stripes)
return stripes;
/* Mirrored */
return 1;
} }
/* /*
@ -559,6 +568,8 @@ static uint32_t mirror_log_extents(uint32_t region_size, uint32_t pe_size, uint3
/* /*
* Preparation for a specific allocation attempt * Preparation for a specific allocation attempt
* stripes and mirrors refer to the parallel areas used for data.
* If log_area_count > 1 it is always mirrored (not striped).
*/ */
static struct alloc_handle *_alloc_init(struct cmd_context *cmd, static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
struct dm_pool *mem, struct dm_pool *mem,
@ -575,20 +586,14 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
struct alloc_handle *ah; struct alloc_handle *ah;
uint32_t s, area_count; uint32_t s, area_count;
if (stripes > 1 && mirrors > 1) { /* FIXME Caller should ensure this */
log_error("Striped mirrors are not supported yet"); if (mirrors && !stripes)
return NULL; stripes = 1;
}
if (log_area_count && stripes > 1) {
log_error("Can't mix striping with a mirror log yet.");
return NULL;
}
if (segtype_is_virtual(segtype)) if (segtype_is_virtual(segtype))
area_count = 0; area_count = 0;
else if (mirrors > 1) else if (mirrors > 1)
area_count = mirrors; area_count = mirrors * stripes;
else else
area_count = stripes; area_count = stripes;
@ -617,7 +622,7 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
ah->log_area_count = log_area_count; ah->log_area_count = log_area_count;
ah->region_size = region_size; ah->region_size = region_size;
ah->alloc = alloc; ah->alloc = alloc;
ah->area_multiple = calc_area_multiple(segtype, area_count); ah->area_multiple = _calc_area_multiple(segtype, area_count, stripes);
ah->log_len = log_area_count ? mirror_log_extents(ah->region_size, extent_size, ah->new_extents / ah->area_multiple) : 0; ah->log_len = log_area_count ? mirror_log_extents(ah->region_size, extent_size, ah->new_extents / ah->area_multiple) : 0;
@ -688,7 +693,7 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
uint32_t s, extents, area_multiple; uint32_t s, extents, area_multiple;
struct lv_segment *seg; struct lv_segment *seg;
area_multiple = calc_area_multiple(segtype, area_count); area_multiple = _calc_area_multiple(segtype, area_count, 0);
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, segtype, lv, if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, segtype, lv,
lv->le_count, lv->le_count,
@ -801,6 +806,20 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t needed,
return 1; return 1;
} }
/* For striped mirrors, all the areas are counted, through the mirror layer */
static uint32_t _stripes_per_mimage(struct lv_segment *seg)
{
struct lv_segment *last_lvseg;
if (seg_is_mirrored(seg) && seg->area_count && seg_type(seg, 0) == AREA_LV) {
last_lvseg = dm_list_item(dm_list_last(&seg_lv(seg, 0)->segments), struct lv_segment);
if (seg_is_striped(last_lvseg))
return last_lvseg->area_count;
}
return 1;
}
/* /*
* Call fn for each AREA_PV used by the LV segment at lv:le of length *max_seg_len. * Call fn for each AREA_PV used by the LV segment at lv:le of length *max_seg_len.
* If any constituent area contains more than one segment, max_seg_len is * If any constituent area contains more than one segment, max_seg_len is
@ -821,6 +840,7 @@ static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
{ {
uint32_t s; uint32_t s;
uint32_t remaining_seg_len, area_len, area_multiple; uint32_t remaining_seg_len, area_len, area_multiple;
uint32_t stripes_per_mimage = 1;
int r = 1; int r = 1;
if (!seg && !(seg = find_seg_by_le(lv, le))) { if (!seg && !(seg = find_seg_by_le(lv, le))) {
@ -838,9 +858,13 @@ static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
if (max_seg_len && *max_seg_len > remaining_seg_len) if (max_seg_len && *max_seg_len > remaining_seg_len)
*max_seg_len = remaining_seg_len; *max_seg_len = remaining_seg_len;
area_multiple = calc_area_multiple(seg->segtype, seg->area_count); area_multiple = _calc_area_multiple(seg->segtype, seg->area_count, 0);
area_len = remaining_seg_len / area_multiple ? : 1; area_len = remaining_seg_len / area_multiple ? : 1;
/* For striped mirrors, all the areas are counted, through the mirror layer */
if (top_level_area_index == -1)
stripes_per_mimage = _stripes_per_mimage(seg);
for (s = first_area; for (s = first_area;
s < seg->area_count && (!max_areas || s <= max_areas); s < seg->area_count && (!max_areas || s <= max_areas);
s++) { s++) {
@ -848,15 +872,14 @@ static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
if (!(r = _for_each_pv(cmd, seg_lv(seg, s), if (!(r = _for_each_pv(cmd, seg_lv(seg, s),
seg_le(seg, s) + seg_le(seg, s) +
(le - seg->le) / area_multiple, (le - seg->le) / area_multiple,
area_len, NULL, max_seg_len, area_len, NULL, max_seg_len, 0,
only_single_area_segments ? 0 : 0, (stripes_per_mimage == 1) && only_single_area_segments ? 1U : 0U,
only_single_area_segments ? 1U : 0U, top_level_area_index != -1 ? top_level_area_index : (int) s * stripes_per_mimage,
top_level_area_index != -1 ? top_level_area_index : (int) s,
only_single_area_segments, fn, only_single_area_segments, fn,
data))) data)))
stack; stack;
} else if (seg_type(seg, s) == AREA_PV) } else if (seg_type(seg, s) == AREA_PV)
if (!(r = fn(cmd, seg_pvseg(seg, s), top_level_area_index != -1 ? (uint32_t) top_level_area_index : s, data))) if (!(r = fn(cmd, seg_pvseg(seg, s), top_level_area_index != -1 ? (uint32_t) top_level_area_index + s : s, data)))
stack; stack;
if (r != 1) if (r != 1)
return r; return r;
@ -947,6 +970,11 @@ static int _is_condition(struct cmd_context *cmd __attribute((unused)),
pvmatch->areas[s].pva = pvmatch->pva; pvmatch->areas[s].pva = pvmatch->pva;
pvmatch->areas[s].used = pvmatch->pva->count; pvmatch->areas[s].used = pvmatch->pva->count;
log_debug("Trying allocation area %" PRIu32 " on %s start PE %" PRIu32
" length %" PRIu32 ".",
s, dev_name(pvmatch->pva->map->pv->dev), pvmatch->pva->start,
pvmatch->pva->count);
return 2; /* Finished */ return 2; /* Finished */
} }
@ -1032,13 +1060,14 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
uint32_t free_pes; uint32_t free_pes;
struct alloced_area *aa; struct alloced_area *aa;
uint32_t s; uint32_t s;
uint32_t total_extents_needed = (needed - *allocated) * ah->area_count / ah->area_multiple;
/* Is there enough total space? */ /* Is there enough total space? */
free_pes = pv_maps_size(pvms); free_pes = pv_maps_size(pvms);
if (needed - *allocated > free_pes) { if (total_extents_needed > free_pes) {
log_error("Insufficient free space: %" PRIu32 " extents needed," log_error("Insufficient free space: %" PRIu32 " extents needed,"
" but only %" PRIu32 " available", " but only %" PRIu32 " available",
needed - *allocated, free_pes); total_extents_needed, free_pes);
return 0; return 0;
} }
@ -1046,7 +1075,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
/* Are there any preceding segments we must follow on from? */ /* Are there any preceding segments we must follow on from? */
if (prev_lvseg) { if (prev_lvseg) {
ix_offset = prev_lvseg->area_count; ix_offset = _stripes_per_mimage(prev_lvseg) * prev_lvseg->area_count;
if ((alloc == ALLOC_CONTIGUOUS)) if ((alloc == ALLOC_CONTIGUOUS))
contiguous = 1; contiguous = 1;
else if ((alloc == ALLOC_CLING)) else if ((alloc == ALLOC_CLING))
@ -1201,20 +1230,25 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
(alloc == ALLOC_ANYWHERE) ? pva->unreserved : pva->count - required); (alloc == ALLOC_ANYWHERE) ? pva->unreserved : pva->count - required);
} }
next_pv: next_pv:
if (alloc == ALLOC_ANYWHERE && /* With ALLOC_ANYWHERE we ignore further PVs once we have at least enough areas */
ix + ix_offset >= ah->area_count + (*log_needs_allocating ? ah->log_area_count : 0)) /* With cling and contiguous we stop if we found a match for *all* the areas */
/* FIXME Rename these variables! */
if ((alloc == ALLOC_ANYWHERE &&
ix + ix_offset >= ah->area_count + (*log_needs_allocating ? ah->log_area_count : 0)) ||
(preferred_count == ix_offset &&
(ix_offset == ah->area_count + (*log_needs_allocating ? ah->log_area_count : 0))))
break; break;
} }
} while (alloc == ALLOC_ANYWHERE && last_ix != ix && ix < ah->area_count + (*log_needs_allocating ? ah->log_area_count : 0)); } while (alloc == ALLOC_ANYWHERE && last_ix != ix && ix < ah->area_count + (*log_needs_allocating ? ah->log_area_count : 0));
if ((contiguous || cling) && (preferred_count < ix_offset)) if (preferred_count < ix_offset)
break; break;
if (ix + ix_offset < ah->area_count + if (ix + ix_offset < ah->area_count +
(*log_needs_allocating ? ah->log_area_count : 0)) (*log_needs_allocating ? ah->log_area_count : 0))
break; break;
/* sort the areas so we allocate from the biggest */ /* Sort the areas so we allocate from the biggest */
if (ix > 1) if (ix > 1)
qsort((*areas_ptr) + ix_offset, ix, sizeof(**areas_ptr), qsort((*areas_ptr) + ix_offset, ix, sizeof(**areas_ptr),
_comp_area); _comp_area);
@ -1310,7 +1344,7 @@ static int _allocate(struct alloc_handle *ah,
/* Upper bound if none of the PVs in prev_lvseg is in pvms */ /* Upper bound if none of the PVs in prev_lvseg is in pvms */
/* FIXME Work size out properly */ /* FIXME Work size out properly */
if (prev_lvseg) if (prev_lvseg)
areas_size += prev_lvseg->area_count; areas_size += _stripes_per_mimage(prev_lvseg) * prev_lvseg->area_count;
/* Allocate an array of pv_areas to hold the largest space on each PV */ /* Allocate an array of pv_areas to hold the largest space on each PV */
if (!(areas = dm_malloc(sizeof(*areas) * areas_size))) { if (!(areas = dm_malloc(sizeof(*areas) * areas_size))) {
@ -1322,10 +1356,14 @@ static int _allocate(struct alloc_handle *ah,
for (alloc = ALLOC_CONTIGUOUS; alloc < ALLOC_INHERIT; alloc++) { for (alloc = ALLOC_CONTIGUOUS; alloc < ALLOC_INHERIT; alloc++) {
old_allocated = allocated; old_allocated = allocated;
log_debug("Trying allocation using %s policy. " log_debug("Trying allocation using %s policy. "
"Need %" PRIu32 " extents for %" PRIu32 " parallel areas and %" PRIu32 " log extents.", "Need %" PRIu32 " extents for %" PRIu32 " parallel areas and %" PRIu32 " log areas of %" PRIu32 " extents. "
"(Total %" PRIu32 " extents.)",
get_alloc_string(alloc), get_alloc_string(alloc),
(ah->new_extents - allocated) / ah->area_multiple, (ah->new_extents - allocated) / ah->area_multiple,
ah->area_count, log_needs_allocating ? ah->log_area_count : 0); ah->area_count, log_needs_allocating ? ah->log_area_count : 0,
log_needs_allocating ? ah->log_len : 0,
(ah->new_extents - allocated) * ah->area_count / ah->area_multiple +
(log_needs_allocating ? ah->log_area_count * ah->log_len : 0));
if (!_find_parallel_space(ah, alloc, pvms, &areas, if (!_find_parallel_space(ah, alloc, pvms, &areas,
&areas_size, can_split, &areas_size, can_split,
prev_lvseg, &allocated, &log_needs_allocating, ah->new_extents)) prev_lvseg, &allocated, &log_needs_allocating, ah->new_extents))
@ -1665,7 +1703,8 @@ int lv_add_log_segment(struct alloc_handle *ah, uint32_t first_area,
static int _lv_extend_mirror(struct alloc_handle *ah, static int _lv_extend_mirror(struct alloc_handle *ah,
struct logical_volume *lv, struct logical_volume *lv,
uint32_t extents, uint32_t first_area) uint32_t extents, uint32_t first_area,
uint32_t stripes, uint32_t stripe_size)
{ {
struct lv_segment *seg; struct lv_segment *seg;
uint32_t m, s; uint32_t m, s;
@ -1673,20 +1712,21 @@ static int _lv_extend_mirror(struct alloc_handle *ah,
seg = first_seg(lv); seg = first_seg(lv);
for (m = first_area, s = 0; s < seg->area_count; s++) { for (m = first_area, s = 0; s < seg->area_count; s++) {
if (is_temporary_mirror_layer(seg_lv(seg, s))) { if (is_temporary_mirror_layer(seg_lv(seg, s))) {
if (!_lv_extend_mirror(ah, seg_lv(seg, s), extents, m)) if (!_lv_extend_mirror(ah, seg_lv(seg, s), extents, m, stripes, stripe_size))
return_0; return_0;
m += lv_mirror_count(seg_lv(seg, s)); m += lv_mirror_count(seg_lv(seg, s));
continue; continue;
} }
if (!lv_add_segment(ah, m++, 1, seg_lv(seg, s), if (!lv_add_segment(ah, m, stripes, seg_lv(seg, s),
get_segtype_from_string(lv->vg->cmd, get_segtype_from_string(lv->vg->cmd,
"striped"), "striped"),
0, 0, 0)) { stripe_size, 0, 0)) {
log_error("Aborting. Failed to extend %s.", log_error("Aborting. Failed to extend %s.",
seg_lv(seg, s)->name); seg_lv(seg, s)->name);
return 0; return 0;
} }
m += stripes;
} }
seg->area_len += extents; seg->area_len += extents;
seg->len += extents; seg->len += extents;
@ -1722,7 +1762,7 @@ int lv_extend(struct logical_volume *lv,
r = lv_add_segment(ah, 0, ah->area_count, lv, segtype, r = lv_add_segment(ah, 0, ah->area_count, lv, segtype,
stripe_size, status, 0); stripe_size, status, 0);
else else
r = _lv_extend_mirror(ah, lv, extents, 0); r = _lv_extend_mirror(ah, lv, extents, 0, stripes, stripe_size);
alloc_destroy(ah); alloc_destroy(ah);
return r; return r;
@ -2095,7 +2135,7 @@ struct dm_list *build_parallel_areas_from_lv(struct cmd_context *cmd,
/* FIXME Unnecessary nesting! */ /* FIXME Unnecessary nesting! */
if (!_for_each_pv(cmd, use_pvmove_parent_lv ? seg->pvmove_source_seg->lv : lv, if (!_for_each_pv(cmd, use_pvmove_parent_lv ? seg->pvmove_source_seg->lv : lv,
use_pvmove_parent_lv ? seg->pvmove_source_seg->le : current_le, use_pvmove_parent_lv ? seg->pvmove_source_seg->le : current_le,
use_pvmove_parent_lv ? spvs->len * calc_area_multiple(seg->pvmove_source_seg->segtype, seg->pvmove_source_seg->area_count) : spvs->len, use_pvmove_parent_lv ? spvs->len * _calc_area_multiple(seg->pvmove_source_seg->segtype, seg->pvmove_source_seg->area_count, 0) : spvs->len,
use_pvmove_parent_lv ? seg->pvmove_source_seg : NULL, use_pvmove_parent_lv ? seg->pvmove_source_seg : NULL,
&spvs->len, &spvs->len,
0, 0, -1, 0, _add_pvs, (void *) spvs)) 0, 0, -1, 0, _add_pvs, (void *) spvs))
@ -3148,6 +3188,7 @@ int lv_create_single(struct volume_group *vg,
if (lp->mirrors > 1) { if (lp->mirrors > 1) {
if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, lp->stripes, if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, lp->stripes,
lp->stripe_size,
adjusted_mirror_region_size( adjusted_mirror_region_size(
vg->extent_size, vg->extent_size,
lv->le_count, lv->le_count,

View File

@ -30,7 +30,8 @@
static int _merge(struct lv_segment *first, struct lv_segment *second) static int _merge(struct lv_segment *first, struct lv_segment *second)
{ {
if (!first || !second || first->segtype != second->segtype || if (!first || !second || first->segtype != second->segtype ||
!first->segtype->ops->merge_segments) return 0; !first->segtype->ops->merge_segments)
return 0;
return first->segtype->ops->merge_segments(first, second); return first->segtype->ops->merge_segments(first, second);
} }

View File

@ -665,7 +665,7 @@ int vg_max_lv_reached(struct volume_group *vg);
*/ */
struct lv_segment *find_mirror_seg(struct lv_segment *seg); struct lv_segment *find_mirror_seg(struct lv_segment *seg);
int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv, int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
uint32_t mirrors, uint32_t stripes, uint32_t mirrors, uint32_t stripes, uint32_t stripe_size,
uint32_t region_size, uint32_t log_count, uint32_t region_size, uint32_t log_count,
struct dm_list *pvs, alloc_policy_t alloc, uint32_t flags); struct dm_list *pvs, alloc_policy_t alloc, uint32_t flags);
int lv_split_mirror_images(struct logical_volume *lv, const char *split_lv_name, int lv_split_mirror_images(struct logical_volume *lv, const char *split_lv_name,
@ -688,7 +688,7 @@ int add_mirrors_to_segments(struct cmd_context *cmd, struct logical_volume *lv,
int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors, int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
struct dm_list *removable_pvs, unsigned remove_log); struct dm_list *removable_pvs, unsigned remove_log);
int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv, int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
uint32_t mirrors, uint32_t stripes, uint32_t region_size, uint32_t mirrors, uint32_t stripes, uint32_t stripe_size, uint32_t region_size,
struct dm_list *allocatable_pvs, alloc_policy_t alloc, struct dm_list *allocatable_pvs, alloc_policy_t alloc,
uint32_t log_count); uint32_t log_count);
struct logical_volume *detach_mirror_log(struct lv_segment *seg); struct logical_volume *detach_mirror_log(struct lv_segment *seg);

View File

@ -1174,6 +1174,8 @@ int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirr
static int _create_mimage_lvs(struct alloc_handle *ah, static int _create_mimage_lvs(struct alloc_handle *ah,
uint32_t num_mirrors, uint32_t num_mirrors,
uint32_t stripes,
uint32_t stripe_size,
struct logical_volume *lv, struct logical_volume *lv,
struct logical_volume **img_lvs, struct logical_volume **img_lvs,
int log) int log)
@ -1205,17 +1207,17 @@ static int _create_mimage_lvs(struct alloc_handle *ah,
} }
if (log) { if (log) {
if (!lv_add_log_segment(ah, m + 1, img_lvs[m], 0)) { if (!lv_add_log_segment(ah, m * stripes + 1, img_lvs[m], 0)) {
log_error("Aborting. Failed to add mirror image segment " log_error("Aborting. Failed to add mirror image segment "
"to %s. Remove new LV and retry.", "to %s. Remove new LV and retry.",
img_lvs[m]->name); img_lvs[m]->name);
return 0; return 0;
} }
} else { } else {
if (!lv_add_segment(ah, m, 1, img_lvs[m], if (!lv_add_segment(ah, m * stripes, stripes, img_lvs[m],
get_segtype_from_string(lv->vg->cmd, get_segtype_from_string(lv->vg->cmd,
"striped"), "striped"),
0, 0, 0)) { stripe_size, 0, 0)) {
log_error("Aborting. Failed to add mirror image segment " log_error("Aborting. Failed to add mirror image segment "
"to %s. Remove new LV and retry.", "to %s. Remove new LV and retry.",
img_lvs[m]->name); img_lvs[m]->name);
@ -1566,7 +1568,8 @@ static struct logical_volume *_create_mirror_log(struct logical_volume *lv,
*/ */
static int _form_mirror(struct cmd_context *cmd, struct alloc_handle *ah, static int _form_mirror(struct cmd_context *cmd, struct alloc_handle *ah,
struct logical_volume *lv, struct logical_volume *lv,
uint32_t mirrors, uint32_t region_size, int log) uint32_t mirrors, uint32_t stripes,
uint32_t stripe_size, uint32_t region_size, int log)
{ {
struct logical_volume **img_lvs; struct logical_volume **img_lvs;
@ -1587,7 +1590,7 @@ static int _form_mirror(struct cmd_context *cmd, struct alloc_handle *ah,
return 0; return 0;
} }
if (!_create_mimage_lvs(ah, mirrors, lv, img_lvs, log)) if (!_create_mimage_lvs(ah, mirrors, stripes, stripe_size, lv, img_lvs, log))
return 0; return 0;
if (!lv_add_mirror_lvs(lv, img_lvs, mirrors, if (!lv_add_mirror_lvs(lv, img_lvs, mirrors,
@ -1650,7 +1653,7 @@ static struct logical_volume *_set_up_mirror_log(struct cmd_context *cmd,
} }
if ((log_count > 1) && if ((log_count > 1) &&
!_form_mirror(cmd, ah, log_lv, log_count-1, region_size, 1)) { !_form_mirror(cmd, ah, log_lv, log_count-1, 1, 0, region_size, 1)) {
log_error("Failed to form mirrored log."); log_error("Failed to form mirrored log.");
return NULL; return NULL;
} }
@ -1749,7 +1752,8 @@ out:
* Convert "linear" LV to "mirror". * Convert "linear" LV to "mirror".
*/ */
int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv, int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
uint32_t mirrors, uint32_t stripes, uint32_t region_size, uint32_t mirrors, uint32_t stripes,
uint32_t stripe_size, uint32_t region_size,
struct dm_list *allocatable_pvs, alloc_policy_t alloc, struct dm_list *allocatable_pvs, alloc_policy_t alloc,
uint32_t log_count) uint32_t log_count)
{ {
@ -1758,11 +1762,6 @@ int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
struct dm_list *parallel_areas; struct dm_list *parallel_areas;
struct logical_volume *log_lv = NULL; struct logical_volume *log_lv = NULL;
if (stripes > 1) {
log_error("stripes > 1 is not supported");
return 0;
}
/* /*
* allocate destination extents * allocate destination extents
*/ */
@ -1795,7 +1794,7 @@ int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
So from here on, if failure occurs, the log must be explicitly So from here on, if failure occurs, the log must be explicitly
removed and the updated vg metadata should be committed. */ removed and the updated vg metadata should be committed. */
if (!_form_mirror(cmd, ah, lv, mirrors, region_size, 0)) if (!_form_mirror(cmd, ah, lv, mirrors, stripes, stripe_size, region_size, 0))
goto out_remove_log; goto out_remove_log;
if (log_count && !attach_mirror_log(first_seg(lv), log_lv)) if (log_count && !attach_mirror_log(first_seg(lv), log_lv))
@ -1825,7 +1824,7 @@ int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
* 'pvs' is either allocatable pvs. * 'pvs' is either allocatable pvs.
*/ */
int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv, int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
uint32_t mirrors, uint32_t stripes, uint32_t mirrors, uint32_t stripes, uint32_t stripe_size,
uint32_t region_size, uint32_t log_count, uint32_t region_size, uint32_t log_count,
struct dm_list *pvs, alloc_policy_t alloc, uint32_t flags) struct dm_list *pvs, alloc_policy_t alloc, uint32_t flags)
{ {
@ -1863,7 +1862,7 @@ int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
return add_mirror_log(cmd, lv, log_count, return add_mirror_log(cmd, lv, log_count,
region_size, pvs, alloc); region_size, pvs, alloc);
return add_mirror_images(cmd, lv, mirrors, return add_mirror_images(cmd, lv, mirrors,
stripes, region_size, stripes, stripe_size, region_size,
pvs, alloc, log_count); pvs, alloc, log_count);
} }

View File

@ -945,21 +945,13 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
if (!(lv->status & MIRRORED)) { if (!(lv->status & MIRRORED)) {
/* FIXME Share code with lvcreate */ /* FIXME Share code with lvcreate */
/* FIXME Why is this restriction here? Fix it! */
dm_list_iterate_items(seg, &lv->segments) {
if (seg_is_striped(seg) && seg->area_count > 1) {
log_error("Mirrors of striped volumes are not yet supported.");
return 0;
}
}
/* /*
* FIXME should we give not only lp->pvh, but also all PVs * FIXME should we give not only lp->pvh, but also all PVs
* currently taken by the mirror? Would make more sense from * currently taken by the mirror? Would make more sense from
* user perspective. * user perspective.
*/ */
if (!lv_add_mirrors(cmd, lv, new_mimage_count - 1, 1, if (!lv_add_mirrors(cmd, lv, new_mimage_count - 1, 1,
region_size, new_log_count, operable_pvs, 0, region_size, new_log_count, operable_pvs,
lp->alloc, MIRROR_BY_LV)) { lp->alloc, MIRROR_BY_LV)) {
stack; stack;
return failure_code; return failure_code;
@ -1013,7 +1005,7 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
/* FIXME: can't have multiple mlogs. force corelog. */ /* FIXME: can't have multiple mlogs. force corelog. */
if (!lv_add_mirrors(cmd, lv, if (!lv_add_mirrors(cmd, lv,
new_mimage_count - old_mimage_count, 1, new_mimage_count - old_mimage_count, 1, 0,
region_size, 0U, operable_pvs, lp->alloc, region_size, 0U, operable_pvs, lp->alloc,
MIRROR_BY_LV)) { MIRROR_BY_LV)) {
layer_lv = seg_lv(first_seg(lv), 0); layer_lv = seg_lv(first_seg(lv), 0);

View File

@ -457,12 +457,6 @@ static int _lvcreate_params(struct lvcreate_params *lp,
return 0; return 0;
} }
if (lp->stripes > 1) {
log_error("mirrors and stripes are currently "
"incompatible");
return 0;
}
if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) if (!(lp->segtype = get_segtype_from_string(cmd, "striped")))
return_0; return_0;
} else { } else {

View File

@ -73,10 +73,6 @@ static int _validate_stripesize(struct cmd_context *cmd,
} else } else
lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0); lp->stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
if (lp->mirrors) {
log_error("Mirrors and striping cannot be combined yet.");
return 0;
}
if (lp->stripe_size & (lp->stripe_size - 1)) { if (lp->stripe_size & (lp->stripe_size - 1)) {
log_error("Stripe size must be power of 2"); log_error("Stripe size must be power of 2");
return 0; return 0;
@ -287,7 +283,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
alloc_policy_t alloc; alloc_policy_t alloc;
struct logical_volume *lock_lv; struct logical_volume *lock_lv;
struct lv_list *lvl; struct lv_list *lvl;
struct lv_segment *seg; struct lv_segment *seg, *uninitialized_var(mirr_seg);
uint32_t seg_extents; uint32_t seg_extents;
uint32_t sz, str; uint32_t sz, str;
struct dm_list *pvh = NULL; struct dm_list *pvh = NULL;
@ -429,10 +425,32 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
return EINVALID_CMD_LINE; return EINVALID_CMD_LINE;
} }
/* If extending, find mirrors of last segment */
if ((lp->extents > lv->le_count)) {
dm_list_iterate_back_items(mirr_seg, &lv->segments) {
if (seg_is_mirrored(mirr_seg))
seg_mirrors = lv_mirror_count(mirr_seg->lv);
else
seg_mirrors = 0;
break;
}
if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) {
log_print("Extending %" PRIu32 " mirror images.",
seg_mirrors);
lp->mirrors = seg_mirrors;
}
if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) &&
(lp->mirrors != seg_mirrors)) {
log_error("Cannot vary number of mirrors in LV yet.");
return EINVALID_CMD_LINE;
}
}
/* If extending, find stripes, stripesize & size of last segment */ /* If extending, find stripes, stripesize & size of last segment */
if ((lp->extents > lv->le_count) && if ((lp->extents > lv->le_count) &&
!(lp->stripes == 1 || (lp->stripes > 1 && lp->stripe_size))) { !(lp->stripes == 1 || (lp->stripes > 1 && lp->stripe_size))) {
dm_list_iterate_items(seg, &lv->segments) { /* FIXME Don't assume mirror seg will always be AREA_LV */
dm_list_iterate_items(seg, seg_mirrors ? &seg_lv(mirr_seg, 0)->segments : &lv->segments) {
if (!seg_is_striped(seg)) if (!seg_is_striped(seg))
continue; continue;
@ -440,7 +458,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
str = seg->area_count; str = seg->area_count;
if ((seg_stripesize && seg_stripesize != sz && if ((seg_stripesize && seg_stripesize != sz &&
!lp->stripe_size) || sz && !lp->stripe_size) ||
(seg_stripes && seg_stripes != str && !lp->stripes)) { (seg_stripes && seg_stripes != str && !lp->stripes)) {
log_error("Please specify number of " log_error("Please specify number of "
"stripes (-i) and stripesize (-I)"); "stripes (-i) and stripesize (-I)");
@ -470,27 +488,6 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
} }
} }
/* If extending, find mirrors of last segment */
if ((lp->extents > lv->le_count)) {
dm_list_iterate_back_items(seg, &lv->segments) {
if (seg_is_mirrored(seg))
seg_mirrors = lv_mirror_count(seg->lv);
else
seg_mirrors = 0;
break;
}
if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) {
log_print("Extending %" PRIu32 " mirror images.",
seg_mirrors);
lp->mirrors = seg_mirrors;
}
if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) &&
(lp->mirrors != seg_mirrors)) {
log_error("Cannot vary number of mirrors in LV yet.");
return EINVALID_CMD_LINE;
}
}
/* If reducing, find stripes, stripesize & size of last segment */ /* If reducing, find stripes, stripesize & size of last segment */
if (lp->extents < lv->le_count) { if (lp->extents < lv->le_count) {
extents_used = 0; extents_used = 0;

View File

@ -254,7 +254,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
return NULL; return NULL;
} }
if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, 0, log_count, if (!lv_add_mirrors(cmd, lv_mirr, 1, 1, 0, 0, log_count,
allocatable_pvs, alloc, MIRROR_BY_SEG)) { allocatable_pvs, alloc, MIRROR_BY_SEG)) {
log_error("Failed to convert pvmove LV to mirrored"); log_error("Failed to convert pvmove LV to mirrored");
return_NULL; return_NULL;