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:
parent
fddc256a02
commit
1485ce69c4
@ -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.
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
/* Striped */
|
||||||
|
if (segtype_is_striped(segtype))
|
||||||
return area_count;
|
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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user