mirror of
git://sourceware.org/git/lvm2.git
synced 2025-02-24 17:57:48 +03:00
This patch adds the ability to extend 0 length layered LVs. This
allows us to allocate all images of a mirror (or RAID array) at one time during create. The current mirror implementation still requires a separate allocation for the log, however.
This commit is contained in:
parent
968cdc0066
commit
fe93c99ad9
@ -2106,29 +2106,87 @@ int lv_add_log_segment(struct alloc_handle *ah, uint32_t first_area,
|
|||||||
0, status, 0);
|
0, status, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _lv_extend_mirror(struct alloc_handle *ah,
|
static int _lv_insert_empty_sublvs(struct logical_volume *lv,
|
||||||
|
const struct segment_type *segtype,
|
||||||
|
uint32_t region_size,
|
||||||
|
uint32_t devices)
|
||||||
|
{
|
||||||
|
struct logical_volume *sub_lv;
|
||||||
|
uint32_t i;
|
||||||
|
uint64_t status = 0;
|
||||||
|
char *img_name;
|
||||||
|
size_t len;
|
||||||
|
struct lv_segment *mapseg;
|
||||||
|
|
||||||
|
if (lv->le_count || first_seg(lv)) {
|
||||||
|
log_error(INTERNAL_ERROR
|
||||||
|
"Non-empty LV passed to _lv_insert_empty_sublv");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!segtype_is_mirrored(segtype))
|
||||||
|
return_0;
|
||||||
|
lv->status |= MIRRORED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, create our top-level segment for our top-level LV
|
||||||
|
*/
|
||||||
|
if (!(mapseg = alloc_lv_segment(lv->vg->cmd->mem, segtype,
|
||||||
|
lv, 0, 0, lv->status, 0, NULL,
|
||||||
|
devices, 0, 0, region_size, 0, NULL))) {
|
||||||
|
log_error("Failed to create mapping segment for %s", lv->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Next, create all of our sub_lv's and link them in.
|
||||||
|
*/
|
||||||
|
len = strlen(lv->name) + 32;
|
||||||
|
if (!(img_name = dm_pool_alloc(lv->vg->cmd->mem, len)))
|
||||||
|
return_0;
|
||||||
|
if (dm_snprintf(img_name, len, "%s%s", lv->name, "_mimage_%d") < 0)
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
for (i = 0; i < devices; i++) {
|
||||||
|
sub_lv = lv_create_empty(img_name, NULL,
|
||||||
|
MIRROR_IMAGE, lv->alloc, lv->vg);
|
||||||
|
if (!sub_lv)
|
||||||
|
return_0;
|
||||||
|
if (!set_lv_segment_area_lv(mapseg, i, sub_lv, 0, status))
|
||||||
|
return_0;
|
||||||
|
}
|
||||||
|
dm_list_add(&lv->segments, &mapseg->list);
|
||||||
|
|
||||||
|
dm_pool_free(lv->vg->cmd->mem, img_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _lv_extend_layered_lv(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)
|
uint32_t stripes, uint32_t stripe_size)
|
||||||
{
|
{
|
||||||
|
struct logical_volume *sub_lv;
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
uint32_t m, s;
|
uint32_t m, s;
|
||||||
|
|
||||||
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, stripes, stripe_size))
|
if (!_lv_extend_layered_lv(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, stripes, seg_lv(seg, s),
|
sub_lv = seg_lv(seg, s);
|
||||||
|
if (!lv_add_segment(ah, m, stripes, sub_lv,
|
||||||
get_segtype_from_string(lv->vg->cmd,
|
get_segtype_from_string(lv->vg->cmd,
|
||||||
"striped"),
|
"striped"),
|
||||||
stripe_size, 0, 0)) {
|
stripe_size, sub_lv->status, 0)) {
|
||||||
log_error("Aborting. Failed to extend %s.",
|
log_error("Aborting. Failed to extend %s in %s.",
|
||||||
seg_lv(seg, s)->name);
|
sub_lv->name, lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
m += stripes;
|
m += stripes;
|
||||||
@ -2147,28 +2205,35 @@ static int _lv_extend_mirror(struct alloc_handle *ah,
|
|||||||
int lv_extend(struct logical_volume *lv,
|
int lv_extend(struct logical_volume *lv,
|
||||||
const struct segment_type *segtype,
|
const struct segment_type *segtype,
|
||||||
uint32_t stripes, uint32_t stripe_size,
|
uint32_t stripes, uint32_t stripe_size,
|
||||||
uint32_t mirrors, uint32_t extents,
|
uint32_t mirrors, uint32_t region_size,
|
||||||
struct physical_volume *mirrored_pv __attribute__((unused)),
|
uint32_t extents,
|
||||||
uint32_t mirrored_pe __attribute__((unused)),
|
struct dm_list *allocatable_pvs, alloc_policy_t alloc)
|
||||||
uint64_t status, struct dm_list *allocatable_pvs,
|
|
||||||
alloc_policy_t alloc)
|
|
||||||
{
|
{
|
||||||
int r = 1;
|
int r = 1;
|
||||||
struct alloc_handle *ah;
|
struct alloc_handle *ah;
|
||||||
|
|
||||||
if (segtype_is_virtual(segtype))
|
if (segtype_is_virtual(segtype))
|
||||||
return lv_add_virtual_segment(lv, status, extents, segtype);
|
return lv_add_virtual_segment(lv, 0u, extents, segtype);
|
||||||
|
|
||||||
if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors, 0, 0,
|
if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors, 0, 0,
|
||||||
extents, allocatable_pvs, alloc, NULL)))
|
extents, allocatable_pvs, alloc, NULL)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
if (mirrors < 2)
|
if (!segtype_is_mirrored(segtype))
|
||||||
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, 0u, 0);
|
||||||
else
|
else {
|
||||||
r = _lv_extend_mirror(ah, lv, extents, 0, stripes, stripe_size);
|
if (!lv->le_count &&
|
||||||
|
!_lv_insert_empty_sublvs(lv, segtype,
|
||||||
|
region_size, mirrors)) {
|
||||||
|
log_error("Failed to insert layer for %s", lv->name);
|
||||||
|
alloc_destroy(ah);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = _lv_extend_layered_lv(ah, lv, extents, 0,
|
||||||
|
stripes, stripe_size);
|
||||||
|
}
|
||||||
alloc_destroy(ah);
|
alloc_destroy(ah);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -3389,7 +3454,7 @@ static struct logical_volume *_create_virtual_origin(struct cmd_context *cmd,
|
|||||||
ALLOC_INHERIT, vg)))
|
ALLOC_INHERIT, vg)))
|
||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
if (!lv_extend(lv, segtype, 1, 0, 1, voriginextents, NULL, 0u, 0u,
|
if (!lv_extend(lv, segtype, 1, 0, 1, 0, voriginextents,
|
||||||
NULL, ALLOC_INHERIT))
|
NULL, ALLOC_INHERIT))
|
||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
@ -3588,6 +3653,10 @@ int lv_create_single(struct volume_group *vg,
|
|||||||
"Don't read what you didn't write!");
|
"Don't read what you didn't write!");
|
||||||
status |= LV_NOTSYNCED;
|
status |= LV_NOTSYNCED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lp->segtype = get_segtype_from_string(cmd, "mirror");
|
||||||
|
if (!lp->segtype)
|
||||||
|
return_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(lv = lv_create_empty(lp->lv_name ? lp->lv_name : "lvol%d", NULL,
|
if (!(lv = lv_create_empty(lp->lv_name ? lp->lv_name : "lvol%d", NULL,
|
||||||
@ -3611,19 +3680,17 @@ int lv_create_single(struct volume_group *vg,
|
|||||||
dm_list_splice(&lv->tags, &lp->tags);
|
dm_list_splice(&lv->tags, &lp->tags);
|
||||||
|
|
||||||
if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size,
|
if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size,
|
||||||
1, lp->extents, NULL, 0u, 0u, lp->pvh, lp->alloc))
|
lp->mirrors,
|
||||||
|
adjusted_mirror_region_size(vg->extent_size,
|
||||||
|
lp->extents,
|
||||||
|
lp->region_size),
|
||||||
|
lp->extents, lp->pvh, lp->alloc))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
if (lp->mirrors > 1) {
|
if ((lp->mirrors > 1) && lp->log_count) {
|
||||||
if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, lp->stripes,
|
if (!add_mirror_log(cmd, lv, lp->log_count,
|
||||||
lp->stripe_size,
|
first_seg(lv)->region_size,
|
||||||
adjusted_mirror_region_size(
|
lp->pvh, lp->alloc)) {
|
||||||
vg->extent_size,
|
|
||||||
lv->le_count,
|
|
||||||
lp->region_size),
|
|
||||||
lp->log_count, lp->pvh, lp->alloc,
|
|
||||||
MIRROR_BY_LV |
|
|
||||||
(lp->nosync ? MIRROR_SKIP_INIT_SYNC : 0))) {
|
|
||||||
stack;
|
stack;
|
||||||
goto revert_new_lv;
|
goto revert_new_lv;
|
||||||
}
|
}
|
||||||
|
@ -500,10 +500,9 @@ int replace_lv_with_error_segment(struct logical_volume *lv);
|
|||||||
int lv_extend(struct logical_volume *lv,
|
int lv_extend(struct logical_volume *lv,
|
||||||
const struct segment_type *segtype,
|
const struct segment_type *segtype,
|
||||||
uint32_t stripes, uint32_t stripe_size,
|
uint32_t stripes, uint32_t stripe_size,
|
||||||
uint32_t mirrors, uint32_t extents,
|
uint32_t mirrors, uint32_t region_size,
|
||||||
struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
|
uint32_t extents,
|
||||||
uint64_t status, struct dm_list *allocatable_pvs,
|
struct dm_list *allocatable_pvs, alloc_policy_t alloc);
|
||||||
alloc_policy_t alloc);
|
|
||||||
|
|
||||||
/* lv must be part of lv->vg->lvs */
|
/* lv must be part of lv->vg->lvs */
|
||||||
int lv_remove(struct logical_volume *lv);
|
int lv_remove(struct logical_volume *lv);
|
||||||
|
@ -1899,8 +1899,9 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check sync status */
|
/* check sync status */
|
||||||
if (lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL) &&
|
if (mirror_in_sync() ||
|
||||||
(sync_percent == PERCENT_100))
|
(lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL) &&
|
||||||
|
(sync_percent == PERCENT_100)))
|
||||||
in_sync = 1;
|
in_sync = 1;
|
||||||
else
|
else
|
||||||
in_sync = 0;
|
in_sync = 0;
|
||||||
|
@ -670,10 +670,11 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
|
|||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
}
|
}
|
||||||
} else if ((lp->extents > lv->le_count) && /* Ensure we extend */
|
} else if ((lp->extents > lv->le_count) && /* Ensure we extend */
|
||||||
!lv_extend(lv, lp->segtype, lp->stripes,
|
!lv_extend(lv, lp->segtype,
|
||||||
lp->stripe_size, lp->mirrors,
|
lp->stripes, lp->stripe_size,
|
||||||
|
lp->mirrors, first_seg(lv)->region_size,
|
||||||
lp->extents - lv->le_count,
|
lp->extents - lv->le_count,
|
||||||
NULL, 0u, 0u, pvh, alloc)) {
|
pvh, alloc)) {
|
||||||
stack;
|
stack;
|
||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user