1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

o Metadata area struct change.

o Support physical extent restrictions on PV lists for allocations
    e.g. lvcreate -l 200 vg1 /dev/sda1:100-199:300-399
This commit is contained in:
Alasdair Kergon 2003-04-24 22:23:24 +00:00
parent 098102afc0
commit b8c919b402
19 changed files with 700 additions and 269 deletions

View File

@ -42,7 +42,7 @@ static struct {
} _segtypes[] = {
{
SEG_STRIPED, "striped"}, {
SEG_MIRROR, "mirror"}, {
SEG_MIRRORED, "mirror"}, {
SEG_SNAPSHOT, "snapshot"}
};
@ -478,14 +478,28 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
{
uint32_t len = seg->len / seg->stripes;
switch (seg->area[s].type) {
case AREA_PV:
log_print("%sPhysical volume\t%s", pre,
seg->area[s].pv ? dev_name(seg->area[s].pv->dev) : "Missing");
seg->area[s].u.pv.pv ?
dev_name(seg->area[s].u.pv.pv->dev) : "Missing");
if (seg->area[s].pv)
if (seg->area[s].u.pv.pv)
log_print("%sPhysical extents\t%d to %d", pre,
seg->area[s].pe, seg->area[s].pe + len - 1);
seg->area[s].u.pv.pe,
seg->area[s].u.pv.pe + seg->area_len - 1);
break;
case AREA_LV:
log_print("%sLogical volume\t%s", pre,
seg->area[s].u.lv.lv ?
seg->area[s].u.lv.lv->name : "Missing");
if (seg->area[s].u.lv.lv)
log_print("%sLogical extents\t%d to %d", pre,
seg->area[s].u.lv.le,
seg->area[s].u.lv.le + seg->area_len - 1);
}
}
int lvdisplay_segments(struct logical_volume *lv)
@ -502,7 +516,7 @@ int lvdisplay_segments(struct logical_volume *lv)
log_print("Logical extent %u to %u:",
seg->le, seg->le + seg->len - 1);
if (seg->type == SEG_STRIPED && seg->stripes == 1)
if (seg->type == SEG_STRIPED && seg->area_count == 1)
log_print(" Type\t\tlinear");
else
log_print(" Type\t\t%s",
@ -510,14 +524,14 @@ int lvdisplay_segments(struct logical_volume *lv)
switch (seg->type) {
case SEG_STRIPED:
if (seg->stripes == 1)
if (seg->area_count == 1)
_display_stripe(seg, 0, " ");
else {
log_print(" Stripes\t\t%u", seg->stripes);
log_print(" Stripes\t\t%u", seg->area_count);
log_print(" Stripe size\t\t%u KB",
seg->stripe_size / 2);
for (s = 0; s < seg->stripes; s++) {
for (s = 0; s < seg->area_count; s++) {
log_print(" Stripe %d:", s);
_display_stripe(seg, s, " ");
}
@ -525,8 +539,9 @@ int lvdisplay_segments(struct logical_volume *lv)
log_print(" ");
break;
case SEG_SNAPSHOT:
case SEG_MIRROR:
;
break;
case SEG_MIRRORED:
break;
}
}

View File

@ -342,9 +342,10 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
}
lvd->lv_read_ahead = lv->read_ahead;
lvd->lv_stripes = list_item(lv->segments.n, struct lv_segment)->stripes;
lvd->lv_stripesize = list_item(lv->segments.n,
struct lv_segment)->stripe_size;
lvd->lv_stripes =
list_item(lv->segments.n, struct lv_segment)->area_count;
lvd->lv_stripesize =
list_item(lv->segments.n, struct lv_segment)->stripe_size;
lvd->lv_size = lv->size;
lvd->lv_allocated_le = lv->le_count;
@ -367,15 +368,25 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->stripes; s++) {
if (seg->area[s].pv != pv)
for (s = 0; s < seg->area_count; s++) {
if (seg->type != SEG_STRIPED) {
log_error("Non-striped segment type in LV %s: "
"unsupported by format1", lv->name);
return 0;
}
if (seg->area[s].type != AREA_PV) {
log_error("LV stripe found in LV %s: "
"unsupported by format1", lv->name);
return 0;
}
if (seg->area[s].u.pv.pv != pv)
continue; /* not our pv */
for (pe = 0; pe < (seg->len / seg->stripes); pe++) {
ped = &dl->extents[pe + seg->area[s].pe];
for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
ped = &dl->extents[pe + seg->area[s].u.pv.pe];
ped->lv_num = lv_num;
ped->le_num = (seg->le / seg->stripes) + pe +
s * (lv->le_count / seg->stripes);
ped->le_num = (seg->le / seg->area_count) + pe +
s * (lv->le_count / seg->area_count);
}
}
}
@ -396,7 +407,7 @@ int import_pvs(const struct format_type *fmt, struct pool *mem,
dl = list_item(pvdh, struct disk_list);
if (!(pvl = pool_alloc(mem, sizeof(*pvl))) ||
if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = pool_alloc(mem, sizeof(*pvl->pv)))) {
stack;
return 0;

View File

@ -216,18 +216,20 @@ static int _read_linear(struct pool *mem, struct lv_map *lvm)
seg->type = SEG_STRIPED;
seg->le = le;
seg->len = 0;
seg->area_len = 0;
seg->stripe_size = 0;
seg->stripes = 1;
seg->area_count = 1;
seg->area[0].pv = lvm->map[le].pv;
seg->area[0].pe = lvm->map[le].pe;
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = lvm->map[le].pv;
seg->area[0].u.pv.pe = lvm->map[le].pe;
do
do {
seg->len++;
while ((lvm->map[le + seg->len].pv == seg->area[0].pv) &&
(seg->area[0].pv &&
lvm->map[le + seg->len].pe == seg->area[0].pe +
seg->area_len++;
} while ((lvm->map[le + seg->len].pv == seg->area[0].u.pv.pv) &&
(seg->area[0].u.pv.pv &&
lvm->map[le + seg->len].pe == seg->area[0].u.pv.pe +
seg->len));
le += seg->len;
@ -248,10 +250,11 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
/*
* Is the next physical extent in every stripe adjacent to the last?
*/
for (st = 0; st < seg->stripes; st++)
if ((lvm->map[le + st * len].pv != seg->area[st].pv) ||
(seg->area[st].pv &&
lvm->map[le + st * len].pe != seg->area[st].pe + seg->len))
for (st = 0; st < seg->area_count; st++)
if ((lvm->map[le + st * len].pv != seg->area[st].u.pv.pv) ||
(seg->area[st].u.pv.pv &&
lvm->map[le + st * len].pe !=
seg->area[st].u.pv.pe + seg->len))
return 0;
return 1;
@ -281,27 +284,30 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
seg->lv = lvm->lv;
seg->type = SEG_STRIPED;
seg->stripe_size = lvm->stripe_size;
seg->stripes = lvm->stripes;
seg->le = seg->stripes * le;
seg->area_count = lvm->stripes;
seg->le = seg->area_count * le;
seg->len = 1;
seg->area_len = 1;
/*
* Set up start positions of each stripe in this segment
*/
for (st = 0; st < seg->stripes; st++) {
seg->area[st].pv = lvm->map[le + st * len].pv;
seg->area[st].pe = lvm->map[le + st * len].pe;
for (st = 0; st < seg->area_count; st++) {
seg->area[st].u.pv.pv = lvm->map[le + st * len].pv;
seg->area[st].u.pv.pe = lvm->map[le + st * len].pe;
}
/*
* Find how many blocks are contiguous in all stripes
* and so can form part of this segment
*/
while (_check_stripe(lvm, seg, le, len))
while (_check_stripe(lvm, seg, le, len)) {
seg->len++;
seg->area_len++;
}
le += seg->len;
seg->len *= seg->stripes;
seg->len *= seg->area_count;
list_add(&lvm->lv->segments, &seg->list);
}

View File

@ -372,6 +372,7 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
{
unsigned int s;
const char *name;
const char *type;
_outf(f, "segment%u {", count);
_inc_indent(f);
@ -387,40 +388,51 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
_outf(f, "type = \"%s\"", get_segtype_string(seg->type));
switch (seg->type) {
case SEG_STRIPED:
_outf(f, "stripe_count = %u%s", seg->stripes,
(seg->stripes == 1) ? "\t# linear" : "");
if (seg->stripes > 1)
_out_size(f, (uint64_t) seg->stripe_size,
"stripe_size = %u", seg->stripe_size);
f->nl(f);
_outf(f, "stripes = [");
_inc_indent(f);
for (s = 0; s < seg->stripes; s++) {
if (!(name = _get_pv_name(f, seg->area[s].pv))) {
stack;
return 0;
}
_outf(f, "\"%s\", %u%s", name, seg->area[s].pe,
(s == seg->stripes - 1) ? "" : ",");
}
_dec_indent(f);
_outf(f, "]");
break;
case SEG_SNAPSHOT:
_outf(f, "chunk_size = %u", seg->chunk_size);
_outf(f, "origin = \"%s\"", seg->origin->name);
_outf(f, "cow_store = \"%s\"", seg->cow->name);
break;
case SEG_MIRROR:
/* mirrors = [ "lvol1", 10, ... ] */
;
case SEG_MIRRORED:
case SEG_STRIPED:
type = (seg->type == SEG_MIRRORED) ? "mirror" : "stripe";
_outf(f, "%s_count = %u%s", type, seg->area_count,
(seg->area_count == 1) ? "\t# linear" : "");
if ((seg->type == SEG_STRIPED) && (seg->area_count > 1))
_out_size(f, (uint64_t) seg->stripe_size,
"stripe_size = %u", seg->stripe_size);
f->nl(f);
_outf(f, "%ss = [", type);
_inc_indent(f);
for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) {
case AREA_PV:
if (!(name = _get_pv_name(f, seg->
area[s].u.pv.pv))) {
stack;
return 0;
}
_outf(f, "\"%s\", %u%s", name,
seg->area[s].u.pv.pe,
(s == seg->area_count - 1) ? "" : ",");
break;
case AREA_LV:
_outf(f, "\"%s\", %u%s",
seg->area[s].u.lv.lv->name,
seg->area[s].u.lv.le,
(s == seg->area_count - 1) ? "" : ",");
}
}
_dec_indent(f);
_outf(f, "]");
break;
}
_dec_indent(f);
@ -604,6 +616,7 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
/* FIXME But skip if there's already an LV called pv%d ! */
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
stack;
goto bad;

View File

@ -215,7 +215,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
struct hash_table *pv_hash)
{
unsigned int s;
uint32_t stripes = 0;
uint32_t area_count = 0;
struct lv_segment *seg;
struct config_node *cn;
struct config_value *cv;
@ -223,7 +223,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
uint32_t start_extent, extent_count;
uint32_t chunk_size;
const char *org_name, *cow_name;
struct logical_volume *org, *cow;
struct logical_volume *org, *cow, *lv1;
segment_type_t segtype;
if (!(sn = sn->child)) {
@ -254,7 +254,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
}
if (segtype == SEG_STRIPED) {
if (!_read_int32(sn, "stripe_count", &stripes)) {
if (!_read_int32(sn, "stripe_count", &area_count)) {
log_error("Couldn't read 'stripe_count' for "
"segment '%s'.", sn->key);
return 0;
@ -262,7 +262,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
}
if (!(seg = pool_zalloc(mem, sizeof(*seg) +
(sizeof(seg->area[0]) * stripes)))) {
(sizeof(seg->area[0]) * area_count)))) {
stack;
return 0;
}
@ -270,9 +270,10 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
seg->lv = lv;
seg->le = start_extent;
seg->len = extent_count;
seg->area_len = extent_count;
seg->type = segtype;
switch (segtype) {
case SEG_MIRROR:
case SEG_SNAPSHOT:
lv->status |= SNAPSHOT;
@ -316,15 +317,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
break;
case SEG_STRIPED:
seg->stripes = stripes;
if (!seg->stripes) {
log_error("Zero stripes *not* allowed for segment '%s'",
sn->key);
return 0;
}
if ((seg->stripes != 1) &&
if ((area_count != 1) &&
!_read_int32(sn, "stripe_size", &seg->stripe_size)) {
log_error("Couldn't read stripe_size for segment '%s'.",
sn->key);
@ -337,55 +330,71 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
return 0;
}
for (cv = cn->v, s = 0; cv && s < seg->stripes;
seg->area_len /= area_count;
case SEG_MIRRORED:
seg->area_count = area_count;
if (!seg->area_count) {
log_error("Zero areas not allowed for segment '%s'",
sn->key);
return 0;
}
for (cv = cn->v, s = 0; cv && s < seg->area_count;
s++, cv = cv->next) {
/* first we read the pv */
const char *bad = "Badly formed areas array for "
"segment '%s'.";
struct physical_volume *pv;
uint32_t allocated;
if (cv->type != CFG_STRING) {
log_error(bad, sn->key);
return 0;
}
if (!(pv = hash_lookup(pv_hash, cv->v.str))) {
log_error("Couldn't find physical volume '%s' "
if (!cv->next) {
log_error(bad, sn->key);
return 0;
}
if (cv->next->type != CFG_INT) {
log_error(bad, sn->key);
return 0;
}
/* FIXME Cope if LV not yet read in */
if ((pv = hash_lookup(pv_hash, cv->v.str))) {
seg->area[s].type = AREA_PV;
seg->area[s].u.pv.pv = pv;
seg->area[s].u.pv.pe = cv->next->v.i;
/*
* Adjust extent counts in the pv and vg.
*/
pv->pe_alloc_count += seg->area_len;
vg->free_count -= seg->area_len;
} else if ((lv1 = find_lv(vg, cv->v.str))) {
seg->area[s].type = AREA_LV;
seg->area[s].u.lv.lv = lv1;
seg->area[s].u.lv.le = cv->next->v.i;
} else {
log_error("Couldn't find volume '%s' "
"for segment '%s'.",
cv->v.str ? cv->v.str : "NULL",
seg_name);
return 0;
}
seg->area[s].pv = pv;
if (!(cv = cv->next)) {
log_error(bad, sn->key);
return 0;
}
if (cv->type != CFG_INT) {
log_error(bad, sn->key);
return 0;
}
seg->area[s].pe = cv->v.i;
/*
* Adjust the extent counts in the pv and vg.
*/
allocated = seg->len / seg->stripes;
pv->pe_alloc_count += allocated;
vg->free_count -= allocated;
cv = cv->next;
}
/*
* Check we read the correct number of stripes.
*/
if (cv || (s < seg->stripes)) {
log_error("Incorrect number of stripes in 'area' array "
if (cv || (s < seg->area_count)) {
log_error("Incorrect number of areas in area array "
"for segment '%s'.", seg_name);
return 0;
}
@ -456,7 +465,7 @@ static int _read_segments(struct pool *mem, struct volume_group *vg,
return 1;
}
static int _read_lv(struct format_instance *fid, struct pool *mem,
static int _read_lvnames(struct format_instance *fid, struct pool *mem,
struct volume_group *vg, struct config_node *lvn,
struct config_node *vgn, struct hash_table *pv_hash)
{
@ -482,17 +491,6 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
return 0;
}
lv->vg = vg;
/* FIXME: read full lvid */
if (!_read_id(&lv->lvid.id[1], lvn, "id")) {
log_error("Couldn't read uuid for logical volume %s.",
lv->name);
return 0;
}
memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
if (!(cn = find_config_node(lvn, "status", '/'))) {
log_error("Couldn't find status flags for logical volume.");
return 0;
@ -503,12 +501,6 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
return 0;
}
list_init(&lv->segments);
if (!_read_segments(mem, vg, lv, lvn, pv_hash)) {
stack;
return 0;
}
lv->alloc = ALLOC_DEFAULT;
if ((cn = find_config_node(lvn, "allocation_policy", '/'))) {
struct config_value *cv = cn->v;
@ -524,6 +516,48 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
if (!_read_int32(lvn, "read_ahead", &lv->read_ahead))
lv->read_ahead = 0;
list_init(&lv->segments);
lv->vg = vg;
vg->lv_count++;
list_add(&vg->lvs, &lvl->list);
return 1;
}
static int _read_lvsegs(struct format_instance *fid, struct pool *mem,
struct volume_group *vg, struct config_node *lvn,
struct config_node *vgn, struct hash_table *pv_hash)
{
struct logical_volume *lv;
struct lv_list *lvl;
if (!(lvl = find_lv_in_vg(vg, lvn->key))) {
log_error("Lost logical volume reference %s", lvn->key);
return 0;
}
lv = lvl->lv;
if (!(lvn = lvn->child)) {
log_error("Empty logical volume section.");
return 0;
}
/* FIXME: read full lvid */
if (!_read_id(&lv->lvid.id[1], lvn, "id")) {
log_error("Couldn't read uuid for logical volume %s.",
lv->name);
return 0;
}
memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
if (!_read_segments(mem, vg, lv, lvn, pv_hash)) {
stack;
return 0;
}
lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
/* Skip this for now for snapshots */
@ -541,9 +575,9 @@ static int _read_lv(struct format_instance *fid, struct pool *mem,
log_error("Couldn't read major number for logical "
"volume %s.", lv->name);
}
vg->lv_count++;
list_add(&vg->lvs, &lvl->list);
} else {
vg->lv_count--;
list_del(&lvl->list);
}
return 1;
@ -687,13 +721,21 @@ static struct volume_group *_read_vg(struct format_instance *fid,
list_init(&vg->lvs);
list_init(&vg->snapshots);
if (!_read_sections(fid, "logical_volumes", _read_lv, mem, vg,
if (!_read_sections(fid, "logical_volumes", _read_lvnames, mem, vg,
vgn, pv_hash, 1)) {
log_error("Couldn't read all logical volumes for volume "
log_error("Couldn't read all logical volume names for volume "
"group %s.", vg->name);
goto bad;
}
if (!_read_sections(fid, "logical_volumes", _read_lvsegs, mem, vg,
vgn, pv_hash, 1)) {
log_error("Couldn't read all logical volumes for "
"volume group %s.", vg->name);
goto bad;
}
hash_destroy(pv_hash);
if (vg->status & PARTIAL_VG) {

View File

@ -6,6 +6,7 @@
#include "lib.h"
#include "metadata.h"
#include "locking.h"
#include "pv_map.h"
#include "lvm-string.h"
#include "toolcontext.h"
@ -19,9 +20,12 @@ static void _get_extents(struct lv_segment *seg)
unsigned int s, count;
struct physical_volume *pv;
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
count = seg->len / seg->stripes;
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV)
continue;
pv = seg->area[s].u.pv.pv;
count = seg->area_len;
pv->pe_alloc_count += count;
}
}
@ -31,11 +35,14 @@ static void _put_extents(struct lv_segment *seg)
unsigned int s, count;
struct physical_volume *pv;
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV)
continue;
pv = seg->area[s].u.pv.pv;
if (pv) {
count = seg->len / seg->stripes;
count = seg->area_len;
assert(pv->pe_alloc_count >= count);
pv->pe_alloc_count -= count;
}
@ -60,13 +67,13 @@ static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
struct pv_area **areas, uint32_t *ix)
{
uint32_t count = lv->le_count - *ix;
uint32_t per_area = count / stripes;
uint32_t area_len = count / stripes;
uint32_t smallest = areas[stripes - 1]->count;
uint32_t s;
struct lv_segment *seg;
if (smallest < per_area)
per_area = smallest;
if (smallest < area_len)
area_len = smallest;
if (!(seg = _alloc_segment(lv->vg->cmd->mem, stripes))) {
log_err("Couldn't allocate new stripe segment.");
@ -76,15 +83,17 @@ static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
seg->lv = lv;
seg->type = SEG_STRIPED;
seg->le = *ix;
seg->len = per_area * stripes;
seg->stripes = stripes;
seg->len = area_len * stripes;
seg->area_len = area_len;
seg->area_count = stripes;
seg->stripe_size = stripe_size;
for (s = 0; s < stripes; s++) {
struct pv_area *pva = areas[s];
seg->area[s].pv = pva->map->pv;
seg->area[s].pe = pva->start;
consume_pv_area(pva, per_area);
seg->area[s].type = AREA_PV;
seg->area[s].u.pv.pv = pva->map->pvl->pv;
seg->area[s].u.pv.pe = pva->start;
consume_pv_area(pva, area_len);
}
list_add(&lv->segments, &seg->list);
@ -188,10 +197,12 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
seg->type = SEG_STRIPED;
seg->le = *ix;
seg->len = count;
seg->area_len = count;
seg->stripe_size = 0;
seg->stripes = 1;
seg->area[0].pv = map->pv;
seg->area[0].pe = pva->start;
seg->area_count = 1;
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = map->pvl->pv;
seg->area[0].u.pv.pe = pva->start;
list_add(&lv->segments, &seg->list);
@ -281,7 +292,7 @@ static int _alloc_next_free(struct logical_volume *lv,
* Chooses a correct allocation policy.
*/
static int _allocate(struct volume_group *vg, struct logical_volume *lv,
struct list *acceptable_pvs, uint32_t allocated,
struct list *allocatable_pvs, uint32_t allocated,
uint32_t stripes, uint32_t stripe_size)
{
int r = 0;
@ -296,7 +307,7 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
/*
* Build the sets of available areas on the pv's.
*/
if (!(pvms = create_pv_maps(scratch, vg, acceptable_pvs)))
if (!(pvms = create_pv_maps(scratch, vg, allocatable_pvs)))
goto out;
if (stripes > 1)
@ -359,46 +370,23 @@ static char *_generate_lv_name(struct volume_group *vg,
return buffer;
}
struct logical_volume *lv_create(struct format_instance *fi,
struct logical_volume *lv_create_empty(struct format_instance *fi,
const char *name,
uint32_t status,
alloc_policy_t alloc,
uint32_t stripes,
uint32_t stripe_size,
uint32_t extents,
struct volume_group *vg,
struct list *acceptable_pvs)
struct volume_group *vg)
{
struct cmd_context *cmd = vg->cmd;
struct lv_list *ll = NULL;
struct logical_volume *lv;
char dname[32];
if (!extents) {
log_error("Unable to create logical volume %s with no extents",
name);
return NULL;
}
if (vg->free_count < extents) {
log_error("Insufficient free extents (%u) in volume group %s: "
"%u required", vg->free_count, vg->name, extents);
return NULL;
}
if (vg->max_lv == vg->lv_count) {
log_error("Maximum number of logical volumes (%u) reached "
"in volume group %s", vg->max_lv, vg->name);
return NULL;
}
if (stripes > list_size(acceptable_pvs)) {
log_error("Number of stripes (%u) must not exceed "
"number of physical volumes (%d)", stripes,
list_size(acceptable_pvs));
return NULL;
}
if (!name && !(name = _generate_lv_name(vg, dname, sizeof(dname)))) {
log_error("Failed to generate unique name for the new "
"logical volume");
@ -409,17 +397,20 @@ struct logical_volume *lv_create(struct format_instance *fi,
if (!(ll = pool_zalloc(cmd->mem, sizeof(*ll))) ||
!(ll->lv = pool_zalloc(cmd->mem, sizeof(*ll->lv)))) {
stack;
log_error("lv_list allocation failed");
if (ll)
pool_free(cmd->mem, ll);
return NULL;
}
lv = ll->lv;
lv->vg = vg;
if (!(lv->name = pool_strdup(cmd->mem, name))) {
stack;
goto bad;
log_error("lv name strdup failed");
if (ll)
pool_free(cmd->mem, ll);
return NULL;
}
lv->status = status;
@ -427,30 +418,73 @@ struct logical_volume *lv_create(struct format_instance *fi,
lv->read_ahead = 0;
lv->major = -1;
lv->minor = -1;
lv->size = (uint64_t) extents *vg->extent_size;
lv->le_count = extents;
lv->size = UINT64_C(0);
lv->le_count = 0;
list_init(&lv->segments);
if (!_allocate(vg, lv, acceptable_pvs, 0u, stripes, stripe_size)) {
stack;
goto bad;
}
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;
goto bad;
if (ll)
pool_free(cmd->mem, ll);
return NULL;
}
vg->lv_count++;
list_add(&vg->lvs, &ll->list);
return lv;
}
bad:
if (ll)
pool_free(cmd->mem, ll);
struct logical_volume *lv_create(struct format_instance *fi,
const char *name,
uint32_t status,
alloc_policy_t alloc,
uint32_t stripes,
uint32_t stripe_size,
uint32_t extents,
struct volume_group *vg,
struct list *allocatable_pvs)
{
struct logical_volume *lv;
if (!extents) {
log_error("Unable to create logical volume %s with no extents",
name);
return NULL;
}
if (vg->free_count < extents) {
log_error("Insufficient free extents (%u) in volume group %s: "
"%u required", vg->free_count, vg->name, extents);
return NULL;
}
if (stripes > list_size(allocatable_pvs)) {
log_error("Number of stripes (%u) must not exceed "
"number of physical volumes (%d)", stripes,
list_size(allocatable_pvs));
return NULL;
}
if (!(lv = lv_create_empty(fi, name, status, alloc, vg))) {
stack;
return NULL;
}
lv->size = (uint64_t) extents *vg->extent_size;
lv->le_count = extents;
if (!_allocate(vg, lv, allocatable_pvs, 0u, stripes, stripe_size)) {
stack;
return NULL;
}
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;
return NULL;
}
return lv;
}
int lv_reduce(struct format_instance *fi,
@ -493,7 +527,7 @@ int lv_reduce(struct format_instance *fi,
int lv_extend(struct format_instance *fi,
struct logical_volume *lv,
uint32_t stripes, uint32_t stripe_size,
uint32_t extents, struct list *acceptable_pvs)
uint32_t extents, struct list *allocatable_pvs)
{
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
@ -501,10 +535,11 @@ int lv_extend(struct format_instance *fi,
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, acceptable_pvs, old_le_count,
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
stripes, stripe_size)) {
lv->le_count = old_le_count;
lv->size = old_size;
stack;
return 0;
}
@ -544,3 +579,34 @@ int lv_remove(struct volume_group *vg, struct logical_volume *lv)
return 1;
}
/* Lock a list of LVs */
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags)
{
struct list *lvh;
struct logical_volume *lv;
list_iterate(lvh, lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (!lock_vol(cmd, lv->lvid.s, flags)) {
log_error("Failed to lock %s", lv->name);
return 0;
}
}
return 1;
}
/* Unlock list of LVs */
int unlock_lvs(struct cmd_context *cmd, struct list *lvs)
{
struct list *lvh;
struct logical_volume *lv;
list_iterate(lvh, lvs) {
lv = list_item(lvh, struct lv_list)->lv;
unlock_lv(cmd, lv->lvid.s);
}
return 1;
}

View File

@ -20,15 +20,20 @@ static int _merge(struct lv_segment *first, struct lv_segment *second)
if (!first ||
(first->type != SEG_STRIPED) ||
(first->type != second->type) ||
(first->stripes != second->stripes) ||
(first->area_count != second->area_count) ||
(first->stripe_size != second->stripe_size))
return 0;
for (s = 0; s < first->stripes; s++) {
width = first->len / first->stripes;
for (s = 0; s < first->area_count; s++) {
width = first->area_len;
if ((first->area[s].pv != second->area[s].pv) ||
(first->area[s].pe + width != second->area[s].pe))
/* FIXME Relax this to first type != second type ? */
if (first->area[s].type != AREA_PV ||
second->area[s].type != AREA_PV)
return 0;
if ((first->area[s].u.pv.pv != second->area[s].u.pv.pv) ||
(first->area[s].u.pv.pe + width != second->area[s].u.pv.pe))
return 0;
}

View File

@ -23,7 +23,7 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
log_verbose("Adding physical volume '%s' to volume group '%s'",
pv_name, vg->name);
if (!(pvl = pool_alloc(mem, sizeof(*pvl)))) {
if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
log_error("pv_list allocation for '%s' failed", pv_name);
return 0;
}
@ -401,6 +401,21 @@ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
return NULL;
}
/* Find segment at a given logical extent in an LV */
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
{
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (le >= seg->le && le < seg->le + seg->len)
return seg;
}
return NULL;
}
int vg_remove(struct volume_group *vg)
{
struct list *mdah;
@ -707,7 +722,7 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
*label_sector = label->sector;
if (!(pv = pool_zalloc(cmd->mem, sizeof(*pv)))) {
log_error("pv_list allocation for '%s' failed", pv_name);
log_error("pv allocation for '%s' failed", pv_name);
return 0;
}

View File

@ -58,9 +58,14 @@ typedef enum {
typedef enum {
SEG_STRIPED,
SEG_SNAPSHOT,
SEG_MIRROR
SEG_MIRRORED
} segment_type_t;
typedef enum {
AREA_PV,
AREA_LV
} area_type_t;
struct cmd_context;
struct format_handler;
struct labeller;
@ -175,15 +180,25 @@ struct lv_segment {
/* FIXME Fields depend on segment type */
uint32_t stripe_size;
uint32_t stripes;
uint32_t area_count;
uint32_t area_len;
struct logical_volume *origin;
struct logical_volume *cow;
uint32_t chunk_size;
/* There will be one area for each stripe */
struct {
area_type_t type;
union {
struct {
struct physical_volume *pv;
uint32_t pe;
} pv;
struct {
struct logical_volume *lv;
uint32_t le;
} lv;
} u;
} area[0];
};
@ -220,10 +235,17 @@ struct name_list {
char *name;
};
struct alloc_area {
struct list list;
uint32_t start; /* PEs */
uint32_t count; /* PEs */
};
struct pv_list {
struct list list;
struct physical_volume *pv;
struct list *mdas;
struct list *mdas; /* Metadata areas */
struct list *alloc_areas; /* Areas we may allocate from */
};
struct lv_list {
@ -357,8 +379,15 @@ struct logical_volume *lv_create(struct format_instance *fi,
uint32_t stripe_size,
uint32_t extents,
struct volume_group *vg,
struct list *acceptable_pvs);
struct list *allocatable_pvs);
struct logical_volume *lv_create_empty(struct format_instance *fi,
const char *name,
uint32_t status,
alloc_policy_t alloc,
struct volume_group *vg);
/* Manipulate LVs */
int lv_reduce(struct format_instance *fi,
struct logical_volume *lv, uint32_t extents);
@ -368,6 +397,10 @@ int lv_extend(struct format_instance *fi,
uint32_t stripe_size,
uint32_t extents, struct list *allocatable_pvs);
/* Lock list of LVs */
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags);
int unlock_lvs(struct cmd_context *cmd, struct list *lvs);
/* lv must be part of vg->lvs */
int lv_remove(struct volume_group *vg, struct logical_volume *lv);
@ -398,6 +431,9 @@ struct logical_volume *lv_from_lvid(struct cmd_context *cmd,
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name);
/* Find LV segment containing given LE */
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le);
/*
* Remove a dev_dir if present.
*/

View File

@ -11,13 +11,13 @@
static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
{
struct list *tmp;
struct physical_volume *pv;
struct pv_map *pvm;
struct pv_list *pvl;
list_iterate(tmp, pvs) {
pv = list_item(tmp, struct pv_list)->pv;
pvl = list_item(tmp, struct pv_list);
if (!(pv->status & ALLOCATABLE_PV))
if (!(pvl->pv->status & ALLOCATABLE_PV))
continue;
if (!(pvm = pool_zalloc(mem, sizeof(*pvm)))) {
@ -25,9 +25,9 @@ static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
return 0;
}
pvm->pv = pv;
pvm->pvl = pvl;
if (!(pvm->allocated_extents =
bitset_create(mem, pv->pe_count))) {
bitset_create(mem, pvl->pv->pe_count))) {
stack;
return 0;
}
@ -39,7 +39,7 @@ static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
return 1;
}
static int _set_allocated(struct hash_table *hash,
static int _set_allocd(struct hash_table *hash,
struct physical_volume *pv, uint32_t pe)
{
struct pv_map *pvm;
@ -82,7 +82,7 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
/* populate the hash table */
list_iterate(pvmh, maps) {
pvm = list_item(pvmh, struct pv_map);
if (!hash_insert(hash, dev_name(pvm->pv->dev), pvm)) {
if (!hash_insert(hash, dev_name(pvm->pvl->pv->dev), pvm)) {
stack;
goto out;
}
@ -95,12 +95,13 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->stripes; s++) {
for (pe = 0; pe < (seg->len / seg->stripes);
pe++) {
if (!_set_allocated(hash,
seg->area[s].pv,
seg->area[s].pe
for (s = 0u; s < seg->area_count; s++) {
for (pe = 0u; pe < seg->area_len; pe++) {
if (seg->area[s].type != AREA_PV)
continue;
if (!_set_allocd(hash,
seg->area[s].u.pv.pv,
seg->area[s].u.pv.pe
+ pe)) {
stack;
goto out;
@ -140,22 +141,22 @@ static void _insert_area(struct list *head, struct pv_area *a)
}
static int _create_single_area(struct pool *mem, struct pv_map *pvm,
uint32_t *extent)
uint32_t end, uint32_t *extent)
{
uint32_t e = *extent, b, count = pvm->pv->pe_count;
uint32_t e = *extent, b;
struct pv_area *pva;
while (e < count && bit(pvm->allocated_extents, e))
while (e <= end && bit(pvm->allocated_extents, e))
e++;
if (e == count) {
if (e > end) {
*extent = e;
return 1;
}
b = e++;
while (e < count && !bit(pvm->allocated_extents, e))
while (e <= end && !bit(pvm->allocated_extents, e))
e++;
if (!(pva = pool_zalloc(mem, sizeof(*pva)))) {
@ -163,6 +164,8 @@ static int _create_single_area(struct pool *mem, struct pv_map *pvm,
return 0;
}
log_debug("Allowing allocation on %s start PE %" PRIu32 " length %"
PRIu32, dev_name(pvm->pvl->pv->dev), b, e - b);
pva->map = pvm;
pva->start = b;
pva->count = e - b;
@ -172,12 +175,18 @@ static int _create_single_area(struct pool *mem, struct pv_map *pvm,
return 1;
}
static int _create_areas(struct pool *mem, struct pv_map *pvm)
static int _create_areas(struct pool *mem, struct pv_map *pvm, uint32_t start,
uint32_t count)
{
uint32_t pe = 0;
uint32_t pe, end;
while (pe < pvm->pv->pe_count)
if (!_create_single_area(mem, pvm, &pe)) {
end = start + count - 1;
if (end > pvm->pvl->pv->pe_count - 1)
end = pvm->pvl->pv->pe_count - 1;
pe = start;
while (pe <= end)
if (!_create_single_area(mem, pvm, end, &pe)) {
stack;
return 0;
}
@ -185,7 +194,36 @@ static int _create_areas(struct pool *mem, struct pv_map *pvm)
return 1;
}
static int _create_all_areas(struct pool *mem, struct list *maps)
static int _create_allocatable_areas(struct pool *mem, struct pv_map *pvm)
{
struct list *alloc_areas, *aah;
struct alloc_area *aa;
alloc_areas = pvm->pvl->alloc_areas;
if (alloc_areas) {
list_iterate(aah, alloc_areas) {
aa = list_item(aah, struct alloc_area);
if (!_create_areas(mem, pvm, aa->start, aa->count)) {
stack;
return 0;
}
}
} else {
/* Use whole PV */
if (!_create_areas(mem, pvm, UINT32_C(0),
pvm->pvl->pv->pe_count)) {
stack;
return 0;
}
}
return 1;
}
static int _create_all_areas(struct pool *mem, struct list *maps,
struct list *pvs)
{
struct list *tmp;
struct pv_map *pvm;
@ -193,7 +231,7 @@ static int _create_all_areas(struct pool *mem, struct list *maps)
list_iterate(tmp, maps) {
pvm = list_item(tmp, struct pv_map);
if (!_create_areas(mem, pvm)) {
if (!_create_allocatable_areas(mem, pvm)) {
stack;
return 0;
}
@ -226,7 +264,7 @@ struct list *create_pv_maps(struct pool *mem, struct volume_group *vg,
goto bad;
}
if (!_create_all_areas(mem, maps)) {
if (!_create_all_areas(mem, maps, pvs)) {
log_error("Couldn't create area maps in %s", vg->name);
goto bad;
}

View File

@ -28,7 +28,7 @@ struct pv_area {
};
struct pv_map {
struct physical_volume *pv;
struct pv_list *pvl;
bitset_t allocated_extents;
struct list areas;

View File

@ -47,7 +47,7 @@ FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count")
FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno")
FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype")
FIELD(SEGS, seg, NUM, "#Str", stripes, 4, uint32, "stripes")
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes")
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize")
FIELD(SEGS, seg, NUM, "Chunk", chunk_size, 5, size32, "chunksize")
FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start")

View File

@ -289,7 +289,7 @@ static int _segtype_disp(struct report_handle *rh, struct field *field,
{
const struct lv_segment *seg = (const struct lv_segment *) data;
if (seg->stripes == 1)
if (seg->area_count == 1)
field->report_string = "linear";
else
field->report_string = get_segtype_string(seg->type);

View File

@ -107,21 +107,23 @@ static int _read_name_params(struct lvcreate_params *lp,
}
}
if (lp->lv_name && (ptr = strrchr(lp->lv_name, '/')))
if (lp->lv_name) {
if ((ptr = strrchr(lp->lv_name, '/')))
lp->lv_name = ptr + 1;
/* FIXME Remove this restriction eventually */
if (lp->lv_name && !strncmp(lp->lv_name, "snapshot", 8)) {
if (!strncmp(lp->lv_name, "snapshot", 8)) {
log_error("Names starting \"snapshot\" are reserved. "
"Please choose a different LV name.");
return 0;
}
if (!validate_name(lp->lv_name)) {
log_error("Logical volume name \"%s\" has invalid characters",
lp->lv_name);
log_error("Logical volume name \"%s\" has invalid "
"characters", lp->lv_name);
return 0;
}
}
return 1;
}
@ -276,8 +278,8 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
}
} else {
if ((lp->minor != -1) || (lp->major != -1)) {
log_error
("--major and --minor incompatible with -Mn");
log_error("--major and --minor incompatible "
"with -Mn");
return 0;
}
}

View File

@ -192,8 +192,12 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
uint32_t sz, str;
seg = list_item(segh, struct lv_segment);
if (seg->type != SEG_STRIPED)
continue;
sz = seg->stripe_size;
str = seg->stripes;
str = seg->area_count;
if ((seg_stripesize && seg_stripesize != sz
&& !ssize) ||
@ -239,10 +243,13 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
uint32_t seg_extents;
seg = list_item(segh, struct lv_segment);
seg_extents = seg->len;
if (seg->type == SEG_STRIPED) {
seg_stripesize = seg->stripe_size;
seg_stripes = seg->stripes;
seg_stripes = seg->area_count;
}
if (extents <= extents_used + seg_extents)
break;

View File

@ -437,11 +437,120 @@ char *default_vgname(struct cmd_context *cmd)
return pool_strdup(cmd->mem, vg_path);
}
static int _add_alloc_area(struct pool *mem, struct list *alloc_areas,
uint32_t start, uint32_t count)
{
struct alloc_area *aa;
struct list *aah;
log_debug("Adding alloc area: start PE %" PRIu32 " length %" PRIu32,
start, count);
/* Ensure no overlap with existing areas */
list_iterate(aah, alloc_areas) {
aa = list_item(aah, struct alloc_area);
if (((start < aa->start) && (start + count - 1 >= aa->start)) ||
((start >= aa->start) &&
(aa->start + aa->count - 1) >= start)) {
log_error("Overlapping PE ranges detected (%" PRIu32
"-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")",
start, start + count - 1, aa->start,
aa->start + aa->count - 1);
return 0;
}
}
if (!(aa = pool_alloc(mem, sizeof(*aa)))) {
log_error("Allocation of list failed");
return 0;
}
aa->start = start;
aa->count = count;
list_add(alloc_areas, &aa->list);
return 1;
}
static int _parse_pes(struct pool *mem, char *c, struct list *alloc_areas,
uint32_t size)
{
char *endptr;
uint32_t start, end;
/* Default to whole PV */
if (!c) {
if (!_add_alloc_area(mem, alloc_areas, UINT32_C(0), size)) {
stack;
return 0;
}
return 1;
}
while (*c) {
if (*c != ':')
goto error;
c++;
/* Disallow :: and :\0 */
if (*c == ':' || !*c)
goto error;
/* Default to whole range */
start = UINT32_C(0);
end = size - 1;
/* Start extent given? */
if (isdigit(*c)) {
start = (uint32_t) strtoul(c, &endptr, 10);
if (endptr == c)
goto error;
c = endptr;
/* Just one number given? */
if (!*c || *c == ':')
end = start;
}
/* Range? */
if (*c == '-') {
c++;
if (isdigit(*c)) {
end = (uint32_t) strtoul(c, &endptr, 10);
if (endptr == c)
goto error;
c = endptr;
}
}
if (*c && *c != ':')
goto error;
if ((start > end) || (end > size - 1)) {
log_error("PE range error: start extent %" PRIu32 " to "
"end extent %" PRIu32, start, end);
return 0;
}
if (!_add_alloc_area(mem, alloc_areas, start, end - start + 1)) {
stack;
return 0;
}
}
return 1;
error:
log_error("Physical extent parsing error at %s", c);
return 0;
}
struct list *create_pv_list(struct pool *mem,
struct volume_group *vg, int argc, char **argv)
{
struct list *r;
struct list *alloc_areas;
struct pv_list *pvl, *new_pvl;
char *pvname = NULL, *colon;
int i;
/* Build up list of PVs */
@ -452,16 +561,29 @@ struct list *create_pv_list(struct pool *mem,
list_init(r);
for (i = 0; i < argc; i++) {
if (!(pvl = find_pv_in_vg(vg, argv[i]))) {
log_err("Physical Volume \"%s\" not found in "
"Volume Group \"%s\"", argv[i], vg->name);
if ((colon = strchr(argv[i], ':'))) {
if (!(pvname = pool_strndup(mem, argv[i],
colon - argv[i]))) {
log_error("Failed to clone PV name");
return NULL;
}
} else
pvname = argv[i];
if (!(pvl = find_pv_in_vg(vg, pvname))) {
log_err("Physical Volume \"%s\" not found in "
"Volume Group \"%s\"", pvname, vg->name);
return NULL;
}
if (!(pvl->pv->status & ALLOCATABLE_PV)) {
log_error("Physical volume %s not allocatable", pvname);
continue;
}
if (pvl->pv->pe_count == pvl->pv->pe_alloc_count) {
log_err("No free extents on physical volume \"%s\"",
argv[i]);
pvname);
continue;
}
@ -472,7 +594,47 @@ struct list *create_pv_list(struct pool *mem,
memcpy(new_pvl, pvl, sizeof(*new_pvl));
list_add(r, &new_pvl->list);
if (!(alloc_areas = pool_alloc(mem, sizeof(*alloc_areas)))) {
log_error("Allocation of alloc_areas list failed");
return NULL;
}
list_init(alloc_areas);
/* Specify which physical extents may be used for allocation */
if (!_parse_pes(mem, colon, alloc_areas, pvl->pv->pe_count)) {
stack;
return NULL;
}
new_pvl->alloc_areas = alloc_areas;
}
return list_empty(r) ? NULL : r;
}
struct list *clone_pv_list(struct pool *mem, struct list *pvsl)
{
struct list *r, *pvh;
struct pv_list *pvl, *new_pvl;
/* Build up list of PVs */
if (!(r = pool_alloc(mem, sizeof(*r)))) {
log_error("Allocation of list failed");
return NULL;
}
list_init(r);
list_iterate(pvh, pvsl) {
pvl = list_item(pvh, struct pv_list);
if (!(new_pvl = pool_zalloc(mem, sizeof(*new_pvl)))) {
log_error("Unable to allocate physical volume list.");
return NULL;
}
memcpy(new_pvl, pvl, sizeof(*new_pvl));
list_add(r, &new_pvl->list);
}
return r;
}

View File

@ -81,4 +81,6 @@ const char *extract_vgname(struct cmd_context *cmd, const char *lv_name);
struct list *create_pv_list(struct pool *mem,
struct volume_group *vg, int argc, char **argv);
struct list *clone_pv_list(struct pool *mem, struct list *pvs);
#endif

View File

@ -138,8 +138,13 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
/* Are any segments of this LV on missing PVs? */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV)
continue;
/* FIXME Also check for segs on deleted LVs */
pv = seg->area[s].u.pv.pv;
if (!pv || !pv->dev) {
if (!_remove_lv(cmd, lv, &list_unsafe)) {
stack;

View File

@ -66,8 +66,12 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
vg_with = NULL;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
for (s = 0; s < seg->area_count; s++) {
/* FIXME Check AREA_LV too */
if (seg->area[s].type != AREA_PV)
continue;
pv = seg->area[s].u.pv.pv;
if (vg_with) {
if (!pv_is_in_vg(vg_with, pv)) {
log_error("Logical Volume %s "
@ -104,6 +108,8 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
vg_to->lv_count++;
}
/* FIXME Ensure no LVs contain segs pointing at LVs in the other VG */
return 1;
}