===================================================================
@@ -1363,8 +1363,11 @@ int lv_add_segment(struct alloc_handle *
const struct segment_type *segtype,
uint32_t stripe_size,
uint64_t status,
- uint32_t region_size)
+ uint32_t region_size,
+ int reverse)
{
+ uint32_t fa = first_area;
+
if (!segtype) {
log_error("Missing segtype in lv_add_segment().");
return 0;
@@ -1380,7 +1383,14 @@ int lv_add_segment(struct alloc_handle *
return 0;
}
- if (!_setup_alloced_segments(lv, &ah->alloced_areas[first_area],
+ if (reverse)
+ fa = (ah->area_count + ah->log_area_count - 1) - first_area;
+
+ /* 'fa' is unsigned, so check if too large (invalid). */
+ if (fa >= (ah->area_count + ah->log_area_count))
+ return 0;
+
+ if (!_setup_alloced_segments(lv, &ah->alloced_areas[fa],
num_areas, status,
stripe_size, segtype,
region_size))
@@ -1559,11 +1569,16 @@ int lv_add_mirror_lvs(struct logical_vol
*/
int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
{
- const char *segtype_name = ah->log_area_count > 1 ? "mirror" : "striped";
+ int r;
- return lv_add_segment(ah, ah->area_count, ah->log_area_count, log_lv,
- get_segtype_from_string(log_lv->vg->cmd, segtype_name),
- 0, MIRROR_LOG, 0);
+ /*
+ * We specify the first area as starting after the areas
+ * allocated for the mirror.
+ */
+ return lv_add_segment(ah, ah->area_count, 1, log_lv,
+ get_segtype_from_string(log_lv->vg->cmd,
+ "striped"),
+ 0, MIRROR_LOG, 0, 0);
}
static int _lv_extend_mirror(struct alloc_handle *ah,
@@ -1585,7 +1600,7 @@ static int _lv_extend_mirror(struct allo
if (!lv_add_segment(ah, m++, 1, seg_lv(seg, s),
get_segtype_from_string(lv->vg->cmd,
"striped"),
- 0, 0, 0)) {
+ 0, 0, 0, 0)) {
log_error("Aborting. Failed to extend %s.",
seg_lv(seg, s)->name);
return 0;
@@ -1623,7 +1638,7 @@ int lv_extend(struct logical_volume *lv,
if (mirrors < 2)
r = lv_add_segment(ah, 0, ah->area_count, lv, segtype,
- stripe_size, status, 0);
+ stripe_size, status, 0, 0);
else
r = _lv_extend_mirror(ah, lv, extents, 0);
===================================================================
@@ -58,7 +58,8 @@ int lv_add_segment(struct alloc_handle *
const struct segment_type *segtype,
uint32_t stripe_size,
uint64_t status,
- uint32_t region_size);
+ uint32_t region_size,
+ int reverse);
int lv_add_mirror_areas(struct alloc_handle *ah,
struct logical_volume *lv, uint32_t le,
===================================================================
@@ -1171,7 +1171,8 @@ int reconfigure_mirror_images(struct lv_
static int _create_mimage_lvs(struct alloc_handle *ah,
uint32_t num_mirrors,
struct logical_volume *lv,
- struct logical_volume **img_lvs)
+ struct logical_volume **img_lvs,
+ int log)
{
uint32_t m;
char *img_name;
@@ -1202,7 +1203,7 @@ static int _create_mimage_lvs(struct all
if (!lv_add_segment(ah, m, 1, img_lvs[m],
get_segtype_from_string(lv->vg->cmd,
"striped"),
- 0, 0, 0)) {
+ 0, 0, 0, log)) {
log_error("Aborting. Failed to add mirror image segment "
"to %s. Remove new LV and retry.",
img_lvs[m]->name);
@@ -1552,7 +1553,7 @@ static struct logical_volume *_create_mi
*/
static int _form_mirror(struct cmd_context *cmd, struct alloc_handle *ah,
struct logical_volume *lv,
- uint32_t mirrors, uint32_t region_size)
+ uint32_t mirrors, uint32_t region_size, int log)
{
struct logical_volume **img_lvs;
@@ -1573,7 +1574,7 @@ static int _form_mirror(struct cmd_conte
return 0;
}
- if (!_create_mimage_lvs(ah, mirrors, lv, img_lvs))
+ if (!_create_mimage_lvs(ah, mirrors, lv, img_lvs, log))
return 0;
if (!lv_add_mirror_lvs(lv, img_lvs, mirrors,
@@ -1636,7 +1637,7 @@ static struct logical_volume *_set_up_mi
}
if ((log_count > 1) &&
- !_form_mirror(cmd, ah, log_lv, log_count-1, region_size)) {
+ !_form_mirror(cmd, ah, log_lv, log_count-1, region_size, 1)) {
log_error("Failed to form mirrored log.");
return NULL;
}
@@ -1781,7 +1782,7 @@ int add_mirror_images(struct cmd_context
So from here on, if failure occurs, the log must be explicitly
removed and the updated vg metadata should be committed. */
- if (!_form_mirror(cmd, ah, lv, mirrors, region_size))
+ if (!_form_mirror(cmd, ah, lv, mirrors, region_size, 0))
goto out_remove_log;
if (log_count && !attach_mirror_log(first_seg(lv), log_lv))