[lvm-devel] master - vgsplit: temporary list pointer may be invalid
Heinz Mauelshagen
mauelsha at fedoraproject.org
Tue Jul 12 14:16:45 UTC 2016
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=4ca55192e0347c0c5124f7f2d8c1c30aa4d57a43
Commit: 4ca55192e0347c0c5124f7f2d8c1c30aa4d57a43
Parent: d5be748341ec88e35c826b70152bf1e757653a3a
Author: Heinz Mauelshagen <heinzm at redhat.com>
AuthorDate: Tue Jul 12 16:15:32 2016 +0200
Committer: Heinz Mauelshagen <heinzm at redhat.com>
CommitterDate: Tue Jul 12 16:15:32 2016 +0200
vgsplit: temporary list pointer may be invalid
4420d41fea8 introduced recursive split of lvs which
splits a top-level LV together with it's sub LVs.
This lead to invalid temporary list pointers
causing hangs/OOM situations.
Patch updates the temporary list pointer
referencing a moved sub LV.
- resolves rhbz1354686
---
tools/vgsplit.c | 26 ++++++++++++++++----------
1 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index 221600e..806dafe 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -35,6 +35,7 @@ static struct dm_list *_lvh_in_vg(struct logical_volume *lv, struct volume_group
}
static int _lv_tree_move(struct dm_list *lvh,
+ struct dm_list **lvht,
struct volume_group *vg_from,
struct volume_group *vg_to)
{
@@ -43,6 +44,10 @@ static int _lv_tree_move(struct dm_list *lvh,
struct lv_segment *seg = first_seg(lv);
struct dm_list *lvh1;
+ /* Update the list pointer refering to the item moving to @vg_to. */
+ if (lvh == *lvht)
+ *lvht = lvh->n;
+
dm_list_move(&vg_to->lvs, lvh);
lv->vg = vg_to;
lv->lvid.id[0] = lv->vg->id;
@@ -51,7 +56,7 @@ static int _lv_tree_move(struct dm_list *lvh,
for (s = 0; s < seg->area_count; s++)
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
if ((lvh1 = _lvh_in_vg(seg_lv(seg, s), vg_from))) {
- if (!_lv_tree_move(lvh1, vg_from, vg_to))
+ if (!_lv_tree_move(lvh1, lvht, vg_from, vg_to))
return 0;
} else if (!_lvh_in_vg(seg_lv(seg, s), vg_to))
return 0;
@@ -62,7 +67,8 @@ static int _lv_tree_move(struct dm_list *lvh,
static int _move_one_lv(struct volume_group *vg_from,
struct volume_group *vg_to,
- struct dm_list *lvh)
+ struct dm_list *lvh,
+ struct dm_list **lvht)
{
struct logical_volume *lv = dm_list_item(lvh, struct lv_list)->lv;
struct logical_volume *parent_lv;
@@ -82,7 +88,7 @@ static int _move_one_lv(struct volume_group *vg_from,
return 0;
}
- if (!_lv_tree_move(lvh, vg_from, vg_to))
+ if (!_lv_tree_move(lvh, lvht, vg_from, vg_to))
return 0;
/* Moved pool metadata spare LV */
@@ -163,7 +169,7 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
continue;
/* Move this LV */
- if (!_move_one_lv(vg_from, vg_to, lvh))
+ if (!_move_one_lv(vg_from, vg_to, lvh, &lvht))
return_0;
}
@@ -209,7 +215,7 @@ static int _move_snapshots(struct volume_group *vg_from,
*/
if (_lv_is_in_vg(vg_to, seg->cow) &&
_lv_is_in_vg(vg_to, seg->origin)) {
- if (!_move_one_lv(vg_from, vg_to, lvh))
+ if (!_move_one_lv(vg_from, vg_to, lvh, &lvht))
return_0;
}
}
@@ -271,7 +277,7 @@ static int _move_mirrors(struct volume_group *vg_from,
}
if (seg_in == seg->area_count && log_in) {
- if (!_move_one_lv(vg_from, vg_to, lvh))
+ if (!_move_one_lv(vg_from, vg_to, lvh, &lvht))
return_0;
}
}
@@ -303,7 +309,7 @@ static int _move_raids(struct volume_group *vg_from,
continue;
/* If allocations are on PVs of @vg_to -> move RAID LV stack across */
- if (!_move_one_lv(vg_from, vg_to, lvh))
+ if (!_move_one_lv(vg_from, vg_to, lvh, &lvht))
return_0;
}
@@ -338,7 +344,7 @@ static int _move_thins(struct volume_group *vg_from,
seg->pool_lv->name);
return 0;
}
- if (!_move_one_lv(vg_from, vg_to, lvh))
+ if (!_move_one_lv(vg_from, vg_to, lvh, &lvht))
return_0;
}
} else if (lv_is_thin_pool(lv)) {
@@ -358,7 +364,7 @@ static int _move_thins(struct volume_group *vg_from,
lv->name);
return 0;
}
- if (!_move_one_lv(vg_from, vg_to, lvh))
+ if (!_move_one_lv(vg_from, vg_to, lvh, &lvht))
return_0;
}
}
@@ -439,7 +445,7 @@ static int _move_cache(struct volume_group *vg_from,
lv->name, meta->name);
return 0;
}
- if (!_move_one_lv(vg_from, vg_to, lvh))
+ if (!_move_one_lv(vg_from, vg_to, lvh, &lvht))
return_0;
}
More information about the lvm-devel
mailing list