1
0
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:
Jonathan Earl Brassow 2011-04-06 21:32:20 +00:00
parent 968cdc0066
commit fe93c99ad9
4 changed files with 108 additions and 40 deletions

View File

@ -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,
struct logical_volume *lv, const struct segment_type *segtype,
uint32_t extents, uint32_t first_area, uint32_t region_size,
uint32_t stripes, uint32_t stripe_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,
uint32_t extents, uint32_t first_area,
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;
} }

View File

@ -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);

View File

@ -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;

View File

@ -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;
} }