mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
more mirror library functions
This commit is contained in:
parent
a78c760922
commit
1817dbaf60
@ -76,6 +76,10 @@ int lv_add_mirror_segment(struct alloc_handle *ah,
|
|||||||
uint32_t status,
|
uint32_t status,
|
||||||
uint32_t region_size,
|
uint32_t region_size,
|
||||||
struct logical_volume *log_lv);
|
struct logical_volume *log_lv);
|
||||||
|
int lv_add_more_mirrored_areas(struct logical_volume *lv,
|
||||||
|
struct logical_volume **sub_lvs,
|
||||||
|
uint32_t new_area_count,
|
||||||
|
uint32_t status);
|
||||||
|
|
||||||
void alloc_destroy(struct alloc_handle *ah);
|
void alloc_destroy(struct alloc_handle *ah);
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ struct lv_segment *alloc_lv_segment(struct dm_pool *mem,
|
|||||||
|
|
||||||
if (log_lv) {
|
if (log_lv) {
|
||||||
log_lv->status |= MIRROR_LOG;
|
log_lv->status |= MIRROR_LOG;
|
||||||
find_seg_by_le(log_lv, 0)->mirror_seg = seg;
|
first_seg(log_lv)->mirror_seg = seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
return seg;
|
return seg;
|
||||||
@ -232,9 +232,6 @@ void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
|
|||||||
lv->status |= flags;
|
lv->status |= flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _lv_segment_add_areas(struct logical_volume *lv,
|
|
||||||
struct lv_segment *seg,
|
|
||||||
uint32_t new_area_count) __attribute__ ((unused));
|
|
||||||
/*
|
/*
|
||||||
* Prepare for adding parallel areas to an existing segment.
|
* Prepare for adding parallel areas to an existing segment.
|
||||||
*/
|
*/
|
||||||
@ -1063,7 +1060,7 @@ int lv_add_mirror_segment(struct alloc_handle *ah,
|
|||||||
|
|
||||||
for (m = 0; m < mirrors; m++) {
|
for (m = 0; m < mirrors; m++) {
|
||||||
set_lv_segment_area_lv(seg, m, sub_lvs[m], 0, MIRROR_IMAGE);
|
set_lv_segment_area_lv(seg, m, sub_lvs[m], 0, MIRROR_IMAGE);
|
||||||
find_seg_by_le(sub_lvs[m], 0)->mirror_seg = seg;
|
first_seg(sub_lvs[m])->mirror_seg = seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add(&lv->segments, &seg->list);
|
list_add(&lv->segments, &seg->list);
|
||||||
@ -1079,6 +1076,42 @@ int lv_add_mirror_segment(struct alloc_handle *ah,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add parallel areas to an existing mirror
|
||||||
|
*/
|
||||||
|
int lv_add_more_mirrored_areas(struct logical_volume *lv,
|
||||||
|
struct logical_volume **sub_lvs,
|
||||||
|
uint32_t num_extra_areas,
|
||||||
|
uint32_t status)
|
||||||
|
{
|
||||||
|
struct lv_segment *seg;
|
||||||
|
uint32_t old_area_count, new_area_count;
|
||||||
|
uint32_t m;
|
||||||
|
|
||||||
|
if (list_size(&lv->segments) != 1) {
|
||||||
|
log_error("Mirrored LV must only have one segment.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_iterate_items(seg, &lv->segments)
|
||||||
|
break;
|
||||||
|
|
||||||
|
old_area_count = seg->area_count;
|
||||||
|
new_area_count = old_area_count + num_extra_areas;
|
||||||
|
|
||||||
|
if (!_lv_segment_add_areas(lv, seg, new_area_count)) {
|
||||||
|
log_error("Failed to allocate widened LV segment for %s.",
|
||||||
|
lv->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (m = old_area_count; m < new_area_count; m++) {
|
||||||
|
set_lv_segment_area_lv(seg, m, sub_lvs[m - old_area_count], 0, status);
|
||||||
|
first_seg(sub_lvs[m - old_area_count])->mirror_seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry point for single-step LV allocation + extension.
|
* Entry point for single-step LV allocation + extension.
|
||||||
@ -1094,7 +1127,7 @@ int lv_extend(struct logical_volume *lv,
|
|||||||
int r = 1;
|
int r = 1;
|
||||||
uint32_t m;
|
uint32_t m;
|
||||||
struct alloc_handle *ah;
|
struct alloc_handle *ah;
|
||||||
struct lv_segment *first_seg;
|
struct lv_segment *seg;
|
||||||
|
|
||||||
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, status, extents, segtype);
|
||||||
@ -1113,20 +1146,19 @@ int lv_extend(struct logical_volume *lv,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
list_iterate_items(first_seg, &lv->segments)
|
seg = first_seg(lv);
|
||||||
break;
|
|
||||||
for (m = 0; m < mirrors; m++) {
|
for (m = 0; m < mirrors; m++) {
|
||||||
if (!lv_add_segment(ah, m, 1, seg_lv(first_seg, m),
|
if (!lv_add_segment(ah, m, 1, seg_lv(seg, m),
|
||||||
get_segtype_from_string(lv->vg->cmd,
|
get_segtype_from_string(lv->vg->cmd,
|
||||||
"striped"),
|
"striped"),
|
||||||
0, NULL, 0, 0, 0, NULL)) {
|
0, NULL, 0, 0, 0, NULL)) {
|
||||||
log_error("Aborting. Failed to extend %s.",
|
log_error("Aborting. Failed to extend %s.",
|
||||||
seg_lv(first_seg, m)->name);
|
seg_lv(seg, m)->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
first_seg->area_len += extents;
|
seg->area_len += extents;
|
||||||
first_seg->len += extents;
|
seg->len += extents;
|
||||||
lv->le_count += extents;
|
lv->le_count += extents;
|
||||||
lv->size += (uint64_t) extents *lv->vg->extent_size;
|
lv->size += (uint64_t) extents *lv->vg->extent_size;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
|
|||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(seg2 = find_seg_by_le(seg->log_lv, 0)) ||
|
if (!(seg2 = first_seg(seg->log_lv)) ||
|
||||||
seg2->mirror_seg != seg) {
|
seg2->mirror_seg != seg) {
|
||||||
log_error("LV %s: segment %u log LV does not "
|
log_error("LV %s: segment %u log LV does not "
|
||||||
"point back to mirror segment",
|
"point back to mirror segment",
|
||||||
|
@ -675,6 +675,16 @@ struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct lv_segment *first_seg(struct logical_volume *lv)
|
||||||
|
{
|
||||||
|
struct lv_segment *seg = NULL;
|
||||||
|
|
||||||
|
list_iterate_items(seg, &lv->segments)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return seg;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find segment at a given physical extent in a PV */
|
/* Find segment at a given physical extent in a PV */
|
||||||
struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe)
|
struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe)
|
||||||
{
|
{
|
||||||
|
@ -501,6 +501,7 @@ struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
|
|||||||
|
|
||||||
/* Find LV segment containing given LE */
|
/* Find LV segment containing given LE */
|
||||||
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le);
|
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le);
|
||||||
|
struct lv_segment *first_seg(struct logical_volume *lv);
|
||||||
|
|
||||||
/* Find PV segment containing given LE */
|
/* Find PV segment containing given LE */
|
||||||
struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe);
|
struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe);
|
||||||
|
@ -47,6 +47,25 @@ uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
|
|||||||
return region_size;
|
return region_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _move_lv_segments(struct logical_volume *lv_to, struct logical_volume *lv_from)
|
||||||
|
{
|
||||||
|
struct lv_segment *seg;
|
||||||
|
|
||||||
|
lv_to->segments = lv_from->segments;
|
||||||
|
lv_to->segments.n->p = &lv_to->segments;
|
||||||
|
lv_to->segments.p->n = &lv_to->segments;
|
||||||
|
|
||||||
|
list_iterate_items(seg, &lv_to->segments)
|
||||||
|
seg->lv = lv_to;
|
||||||
|
|
||||||
|
/* FIXME set or reset seg->mirror_seg (according to status)? */
|
||||||
|
|
||||||
|
list_init(&lv_from->segments);
|
||||||
|
|
||||||
|
lv_from->le_count = 0;
|
||||||
|
lv_from->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reduce mirrored_seg to num_mirrors images.
|
* Reduce mirrored_seg to num_mirrors images.
|
||||||
*/
|
*/
|
||||||
@ -68,31 +87,25 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors)
|
|||||||
|
|
||||||
int remove_all_mirror_images(struct logical_volume *lv)
|
int remove_all_mirror_images(struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
struct lv_segment *first_seg, *seg;
|
struct lv_segment *seg;
|
||||||
struct logical_volume *lv1;
|
struct logical_volume *lv1;
|
||||||
|
|
||||||
list_iterate_items(first_seg, &lv->segments)
|
seg = first_seg(lv);
|
||||||
break;
|
|
||||||
|
|
||||||
if (!remove_mirror_images(first_seg, 1)) {
|
if (!remove_mirror_images(seg, 1)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lv_remove(first_seg->log_lv)) {
|
if (seg->log_lv && !lv_remove(seg->log_lv)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv1 = seg_lv(first_seg, 0);
|
lv1 = seg_lv(seg, 0);
|
||||||
|
|
||||||
lv->segments = lv1->segments;
|
_move_lv_segments(lv, lv1);
|
||||||
lv->segments.n->p = &lv->segments;
|
|
||||||
lv->segments.p->n = &lv->segments;
|
|
||||||
|
|
||||||
list_init(&lv1->segments);
|
|
||||||
lv1->le_count = 0;
|
|
||||||
lv1->size = 0;
|
|
||||||
if (!lv_remove(lv1)) {
|
if (!lv_remove(lv1)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
@ -100,9 +113,6 @@ int remove_all_mirror_images(struct logical_volume *lv)
|
|||||||
|
|
||||||
lv->status &= ~MIRRORED;
|
lv->status &= ~MIRRORED;
|
||||||
|
|
||||||
list_iterate_items(seg, &lv->segments)
|
|
||||||
seg->lv = lv;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,26 +128,17 @@ int add_mirror_images(struct alloc_handle *ah,
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int create_mirror_layers(struct alloc_handle *ah,
|
static int _create_layers_for_mirror(struct alloc_handle *ah,
|
||||||
uint32_t first_area,
|
uint32_t first_area,
|
||||||
uint32_t num_mirrors,
|
uint32_t num_mirrors,
|
||||||
struct logical_volume *lv,
|
struct logical_volume *lv,
|
||||||
struct segment_type *segtype,
|
struct segment_type *segtype,
|
||||||
uint32_t status,
|
struct logical_volume **img_lvs)
|
||||||
uint32_t region_size,
|
|
||||||
struct logical_volume *log_lv)
|
|
||||||
{
|
{
|
||||||
uint32_t m;
|
uint32_t m;
|
||||||
struct logical_volume **img_lvs;
|
|
||||||
char *img_name;
|
char *img_name;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (!(img_lvs = alloca(sizeof(*img_lvs) * num_mirrors))) {
|
|
||||||
log_error("img_lvs allocation failed. "
|
|
||||||
"Remove new LV and retry.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = strlen(lv->name) + 32;
|
len = strlen(lv->name) + 32;
|
||||||
if (!(img_name = alloca(len))) {
|
if (!(img_name = alloca(len))) {
|
||||||
log_error("img_name allocation failed. "
|
log_error("img_name allocation failed. "
|
||||||
@ -171,6 +172,43 @@ int create_mirror_layers(struct alloc_handle *ah,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_mirror_layers(struct alloc_handle *ah,
|
||||||
|
uint32_t first_area,
|
||||||
|
uint32_t num_mirrors,
|
||||||
|
struct logical_volume *lv,
|
||||||
|
struct segment_type *segtype,
|
||||||
|
uint32_t status,
|
||||||
|
uint32_t region_size,
|
||||||
|
struct logical_volume *log_lv)
|
||||||
|
{
|
||||||
|
struct logical_volume **img_lvs;
|
||||||
|
|
||||||
|
if (!(img_lvs = alloca(sizeof(*img_lvs) * num_mirrors))) {
|
||||||
|
log_error("img_lvs allocation failed. "
|
||||||
|
"Remove new LV and retry.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_create_layers_for_mirror(ah, first_area, num_mirrors, lv,
|
||||||
|
segtype, img_lvs)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Already got the parent mirror segment? */
|
||||||
|
if (lv->status & MIRRORED)
|
||||||
|
return lv_add_more_mirrored_areas(lv, img_lvs, num_mirrors,
|
||||||
|
MIRROR_IMAGE);
|
||||||
|
|
||||||
|
/* Already got a non-mirrored area to be converted? */
|
||||||
|
if (!first_area) {
|
||||||
|
_move_lv_segments(img_lvs[0], lv);
|
||||||
|
lv->status |= MIRRORED;
|
||||||
|
}
|
||||||
|
|
||||||
if (!lv_add_mirror_segment(ah, lv, img_lvs, num_mirrors, segtype,
|
if (!lv_add_mirror_segment(ah, lv, img_lvs, num_mirrors, segtype,
|
||||||
0, region_size, log_lv)) {
|
0, region_size, log_lv)) {
|
||||||
log_error("Aborting. Failed to add mirror segment. "
|
log_error("Aborting. Failed to add mirror segment. "
|
||||||
@ -568,12 +606,14 @@ int fixup_imported_mirrors(struct volume_group *vg)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (seg->log_lv)
|
if (seg->log_lv)
|
||||||
find_seg_by_le(seg->log_lv, 0)->mirror_seg = seg;
|
first_seg(seg->log_lv)->mirror_seg = seg;
|
||||||
for (s = 0; s < seg->area_count; s++)
|
for (s = 0; s < seg->area_count; s++)
|
||||||
if (seg_type(seg, s) == AREA_LV)
|
if (seg_type(seg, s) == AREA_LV)
|
||||||
find_seg_by_le(seg_lv(seg, s), 0)->
|
first_seg(seg_lv(seg, s))->mirror_seg
|
||||||
mirror_seg = seg;
|
= seg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
|
|||||||
static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * lv,
|
static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * lv,
|
||||||
struct lvconvert_params *lp)
|
struct lvconvert_params *lp)
|
||||||
{
|
{
|
||||||
struct lv_segment *first_seg;
|
struct lv_segment *seg;
|
||||||
uint32_t existing_mirrors;
|
uint32_t existing_mirrors;
|
||||||
// struct alloc_handle *ah = NULL;
|
// struct alloc_handle *ah = NULL;
|
||||||
// struct logical_volume *log_lv;
|
// struct logical_volume *log_lv;
|
||||||
@ -82,9 +82,8 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
|||||||
"mirror segments.", lv->name);
|
"mirror segments.", lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
list_iterate_items(first_seg, &lv->segments)
|
seg = first_seg(lv);
|
||||||
break;
|
existing_mirrors = seg->area_count;
|
||||||
existing_mirrors = first_seg->area_count;
|
|
||||||
if (lp->mirrors == existing_mirrors) {
|
if (lp->mirrors == existing_mirrors) {
|
||||||
log_error("Logical volume %s already has %"
|
log_error("Logical volume %s already has %"
|
||||||
PRIu32 " mirror(s).", lv->name,
|
PRIu32 " mirror(s).", lv->name,
|
||||||
@ -101,7 +100,7 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
|||||||
"supported yet.");
|
"supported yet.");
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
if (!remove_mirror_images(first_seg, lp->mirrors)) {
|
if (!remove_mirror_images(seg, lp->mirrors)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user