1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-08-04 12:22:00 +03:00

Basic support for mirrors.

This commit is contained in:
Alasdair Kergon
2005-06-01 16:51:55 +00:00
parent 8e6230ddd9
commit 60f13f01d2
54 changed files with 1752 additions and 1164 deletions

View File

@ -1,5 +1,16 @@
Version 2.01.11 - Version 2.01.11 -
============================== ==============================
Allow the creation of mirrors with contiguous extents.
Always perform sanity checks against metadata before committing it to disk.
Split lv_extend into two steps: choosing extents + allocation to LV(s).
Add mirror log region size to metadata.
Use list_iterate_items throughout and add list*back macros.
Introduce seg_ macros to access areas.
Add segtype_is_ macros.
Support tiny metadata areas for pool conversions.
Mirror activation handles disk log as well as core.
Activation code recognises mirror log dependency.
Add mirror_log and regionsize fields to report.
Fix non-orphan pvchange -u. Fix non-orphan pvchange -u.
Fix vgmerge to handle duplicate LVIDs. Fix vgmerge to handle duplicate LVIDs.
Move archiver code from tools into library. Move archiver code from tools into library.

View File

@ -517,17 +517,15 @@ static int _lv_suspend_lv(struct logical_volume *lv)
*/ */
int lvs_in_vg_activated(struct volume_group *vg) int lvs_in_vg_activated(struct volume_group *vg)
{ {
struct list *lvh; struct lv_list *lvl;
struct logical_volume *lv;
int count = 0; int count = 0;
if (!activation()) if (!activation())
return 0; return 0;
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv; if (lvl->lv->status & VISIBLE_LV)
if (lv->status & VISIBLE_LV) count += (_lv_active(lvl->lv) == 1);
count += (_lv_active(lv) == 1);
} }
return count; return count;
@ -535,17 +533,16 @@ int lvs_in_vg_activated(struct volume_group *vg)
int lvs_in_vg_opened(struct volume_group *vg) int lvs_in_vg_opened(struct volume_group *vg)
{ {
struct list *lvh; struct lv_list *lvl;
struct logical_volume *lv; struct logical_volume *lv;
int count = 0; int count = 0;
if (!activation()) if (!activation())
return 0; return 0;
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv; if (lvl->lv->status & VISIBLE_LV)
if (lv->status & VISIBLE_LV) count += (_lv_open_count(lvl->lv) > 0);
count += (_lv_open_count(lv) > 0);
} }
return count; return count;

View File

@ -732,9 +732,38 @@ int compose_log_line(struct dev_manager *dm, struct lv_segment *seg,
uint32_t region_size) uint32_t region_size)
{ {
int tw; int tw;
char devbuf[10];
char *name;
struct dev_layer *dl;
if (!seg->log_lv)
tw = lvm_snprintf(params, paramsize, "core 1 %u %u ", tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
region_size, areas); region_size, areas);
else {
if (!(name = build_dm_name(dm->mem, seg->log_lv->vg->name,
seg->log_lv->name, NULL))) {
stack;
return 0;
}
if (!(dl = hash_lookup(dm->layers, seg->log_lv->lvid.s))) {
log_error("device layer %s missing from hash",
seg->log_lv->lvid.s);
return 0;
}
if (!dm_format_dev(devbuf, sizeof(devbuf), dl->info.major,
dl->info.minor)) {
log_error("Failed to format device number as dm "
"target (%u,%u)",
dl->info.major, dl->info.minor);
return 0;
}
/* FIXME add sync parm? */
tw = lvm_snprintf(params, paramsize, "disk 2 %s %u %u ",
devbuf, region_size, areas);
}
if (tw < 0) { if (tw < 0) {
stack; stack;
@ -759,29 +788,26 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
for (s = start_area; s < areas; s++, *pos += tw) { for (s = start_area; s < areas; s++, *pos += tw) {
trailing_space = (areas - s - 1) ? " " : ""; trailing_space = (areas - s - 1) ? " " : "";
if ((seg->area[s].type == AREA_PV && if ((seg_type(seg, s) == AREA_PV &&
(!seg->area[s].u.pv.pvseg || (!seg_pvseg(seg, s) ||
!seg->area[s].u.pv.pvseg->pv || !seg_pv(seg, s) ||
!seg->area[s].u.pv.pvseg->pv->dev)) || !seg_dev(seg, s))) ||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv)) (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
tw = lvm_snprintf(params + *pos, paramsize - *pos, tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s 0%s", dm->stripe_filler, "%s 0%s", dm->stripe_filler,
trailing_space); trailing_space);
else if (seg->area[s].type == AREA_PV) else if (seg_type(seg, s) == AREA_PV)
tw = lvm_snprintf(params + *pos, paramsize - *pos, tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s %" PRIu64 "%s", "%s %" PRIu64 "%s",
dev_name(seg->area[s].u.pv.pvseg-> dev_name(seg_dev(seg, s)),
pv->dev), (seg_pv(seg, s)->pe_start +
(seg->area[s].u.pv.pvseg->pv-> (esize * seg_pe(seg, s))),
pe_start +
(esize * seg->area[s].u.pv.pvseg->
pe)),
trailing_space); trailing_space);
else { else {
if (!(dl = hash_lookup(dm->layers, if (!(dl = hash_lookup(dm->layers,
seg->area[s].u.lv.lv->lvid.s))) { seg_lv(seg, s)->lvid.s))) {
log_error("device layer %s missing from hash", log_error("device layer %s missing from hash",
seg->area[s].u.lv.lv->lvid.s); seg_lv(seg, s)->lvid.s);
return 0; return 0;
} }
if (!dm_format_dev if (!dm_format_dev
@ -794,7 +820,7 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
} }
tw = lvm_snprintf(params + *pos, paramsize - *pos, tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s %" PRIu64 "%s", devbuf, "%s %" PRIu64 "%s", devbuf,
esize * seg->area[s].u.lv.le, esize * seg_le(seg, s),
trailing_space); trailing_space);
} }
@ -842,14 +868,12 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
static int _populate_vanilla(struct dev_manager *dm, static int _populate_vanilla(struct dev_manager *dm,
struct dm_task *dmt, struct dev_layer *dl) struct dm_task *dmt, struct dev_layer *dl)
{ {
struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
struct logical_volume *lv = dl->lv; struct logical_volume *lv = dl->lv;
dm->pvmove_mirror_count = 0u; dm->pvmove_mirror_count = 0u;
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (!_emit_target(dm, dmt, seg)) { if (!_emit_target(dm, dmt, seg)) {
log_error("Unable to build table for '%s'", lv->name); log_error("Unable to build table for '%s'", lv->name);
return 0; return 0;
@ -1201,7 +1225,6 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
* only one layer. * only one layer.
*/ */
struct dev_layer *dl, *dlr; struct dev_layer *dl, *dlr;
struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
uint32_t s; uint32_t s;
@ -1219,14 +1242,22 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
_set_flag(dl, TOPLEVEL); _set_flag(dl, TOPLEVEL);
/* Add dependencies for any LVs that segments refer to */ /* Add dependencies for any LVs that segments refer to */
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment); if (seg->log_lv &&
!str_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem, seg->log_lv->lvid.s,
NULL))) {
stack;
return 0;
}
// FIXME Check we don't want NOPROPAGATE here
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV) if (seg_type(seg, s) != AREA_LV)
continue; continue;
if (!str_list_add(dm->mem, &dl->pre_create, if (!str_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem, _build_dlid(dm->mem,
seg->area[s].u.lv.lv-> seg_lv(seg, s)->
lvid.s, NULL))) { lvid.s, NULL))) {
stack; stack;
return 0; return 0;
@ -1300,14 +1331,14 @@ static int _expand_origin(struct dev_manager *dm, struct logical_volume *lv)
{ {
struct logical_volume *active; struct logical_volume *active;
struct lv_segment *snap_seg; struct lv_segment *snap_seg;
struct list *sh; struct lv_list *lvl;
/* /*
* We only need to create an origin layer if one of our * We only need to create an origin layer if one of our
* snapshots is in the active list * snapshots is in the active list
*/ */
list_iterate(sh, &dm->active_list) { list_iterate_items(lvl, &dm->active_list) {
active = list_item(sh, struct lv_list)->lv; active = lvl->lv;
if ((snap_seg = find_cow(active)) && (snap_seg->origin == lv)) if ((snap_seg = find_cow(active)) && (snap_seg->origin == lv))
return _expand_origin_real(dm, lv); return _expand_origin_real(dm, lv);
} }
@ -1411,12 +1442,12 @@ static void _clear_marks(struct dev_manager *dm, int flag)
static int _trace_layer_marks(struct dev_manager *dm, struct dev_layer *dl, static int _trace_layer_marks(struct dev_manager *dm, struct dev_layer *dl,
int flag) int flag)
{ {
struct list *sh; struct str_list *strl;
const char *dlid; const char *dlid;
struct dev_layer *dep; struct dev_layer *dep;
list_iterate(sh, &dl->pre_create) { list_iterate_items(strl, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str; dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) { if (!(dep = hash_lookup(dm->layers, dlid))) {
log_error("Couldn't find device layer '%s'.", dlid); log_error("Couldn't find device layer '%s'.", dlid);
@ -1466,16 +1497,14 @@ static int _trace_all_marks(struct dev_manager *dm, int flag)
*/ */
static int _mark_lvs(struct dev_manager *dm, struct list *lvs, int flag) static int _mark_lvs(struct dev_manager *dm, struct list *lvs, int flag)
{ {
struct list *lvh; struct lv_list *lvl;
struct logical_volume *lv;
struct dev_layer *dl; struct dev_layer *dl;
list_iterate(lvh, lvs) { list_iterate_items(lvl, lvs) {
lv = list_item(lvh, struct lv_list)->lv; if (lvl->lv->status & SNAPSHOT)
if (lv->status & SNAPSHOT)
continue; continue;
if (!(dl = _lookup(dm, lv->lvid.s, NULL))) { if (!(dl = _lookup(dm, lvl->lv->lvid.s, NULL))) {
stack; stack;
return 0; return 0;
} }
@ -1493,12 +1522,12 @@ static int _mark_lvs(struct dev_manager *dm, struct list *lvs, int flag)
static int _suspend_parents(struct dev_manager *dm, struct dev_layer *dl) static int _suspend_parents(struct dev_manager *dm, struct dev_layer *dl)
{ {
struct list *sh; struct str_list *strl;
struct dev_layer *dep; struct dev_layer *dep;
const char *dlid; const char *dlid;
list_iterate(sh, &dl->pre_suspend) { list_iterate_items(strl, &dl->pre_suspend) {
dlid = list_item(sh, struct str_list)->str; dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) { if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_suspend_parents couldn't find device " log_debug("_suspend_parents couldn't find device "
@ -1527,12 +1556,12 @@ static int _suspend_parents(struct dev_manager *dm, struct dev_layer *dl)
static int _resume_with_deps(struct dev_manager *dm, struct dev_layer *dl) static int _resume_with_deps(struct dev_manager *dm, struct dev_layer *dl)
{ {
struct list *sh; struct str_list *strl;
struct dev_layer *dep; struct dev_layer *dep;
const char *dlid; const char *dlid;
list_iterate(sh, &dl->pre_create) { list_iterate_items(strl, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str; dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) { if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_resume_with_deps couldn't find device " log_debug("_resume_with_deps couldn't find device "
@ -1565,7 +1594,7 @@ static int _resume_with_deps(struct dev_manager *dm, struct dev_layer *dl)
*/ */
static int _create_rec(struct dev_manager *dm, struct dev_layer *dl) static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
{ {
struct list *sh; struct str_list *strl;
struct dev_layer *dep; struct dev_layer *dep;
const char *dlid; const char *dlid;
char *newname, *suffix; char *newname, *suffix;
@ -1577,8 +1606,8 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
return 0; return 0;
} }
list_iterate(sh, &dl->pre_create) { list_iterate_items(strl, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str; dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) { if (!(dep = hash_lookup(dm->layers, dlid))) {
log_error("Couldn't find device layer '%s'.", dlid); log_error("Couldn't find device layer '%s'.", dlid);
@ -1634,17 +1663,15 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg) static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg)
{ {
struct list *lvh; struct lv_list *lvl;
struct logical_volume *lv;
/* /*
* Build layers for complete vg. * Build layers for complete vg.
*/ */
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv; if (lvl->lv->status & SNAPSHOT)
if (lv->status & SNAPSHOT)
continue; continue;
if (!_expand_lv(dm, lv)) { if (!_expand_lv(dm, lvl->lv)) {
stack; stack;
return 0; return 0;
} }
@ -1684,15 +1711,15 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
{ {
struct hash_node *hn; struct hash_node *hn;
struct dev_layer *dl; struct dev_layer *dl;
struct list *sh; struct str_list *strl;
const char *dlid; const char *dlid;
struct dev_layer *dep; struct dev_layer *dep;
hash_iterate(hn, dm->layers) { hash_iterate(hn, dm->layers) {
dl = hash_get_data(dm->layers, hn); dl = hash_get_data(dm->layers, hn);
list_iterate(sh, &dl->pre_suspend) { list_iterate_items(strl, &dl->pre_suspend) {
dlid = list_item(sh, struct str_list)->str; dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) { if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_populate_pre_suspend_lists: " log_debug("_populate_pre_suspend_lists: "
@ -1707,8 +1734,8 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
} }
} }
list_iterate(sh, &dl->pre_create) { list_iterate_items(strl, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str; dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) { if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_populate_pre_suspend_lists: " log_debug("_populate_pre_suspend_lists: "
@ -1733,6 +1760,7 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
static int _remove_old_layers(struct dev_manager *dm) static int _remove_old_layers(struct dev_manager *dm)
{ {
int change; int change;
struct dl_list *dll;
struct list *rh, *n; struct list *rh, *n;
struct dev_layer *dl; struct dev_layer *dl;
@ -1755,10 +1783,8 @@ static int _remove_old_layers(struct dev_manager *dm)
} while (change); } while (change);
if (!list_empty(&dm->remove_list)) { if (!list_empty(&dm->remove_list)) {
list_iterate(rh, &dm->remove_list) { list_iterate_items(dll, &dm->remove_list)
dl = list_item(rh, struct dl_list)->dl; log_error("Couldn't deactivate device %s", dll->dl->name);
log_error("Couldn't deactivate device %s", dl->name);
}
return 0; return 0;
} }
@ -1945,16 +1971,14 @@ static int _add_lv(struct pool *mem,
static int _add_lvs(struct pool *mem, static int _add_lvs(struct pool *mem,
struct list *head, struct logical_volume *origin) struct list *head, struct logical_volume *origin)
{ {
struct logical_volume *lv;
struct lv_segment *snap_seg; struct lv_segment *snap_seg;
struct list *lvh; struct lv_list *lvl;
list_iterate(lvh, &origin->vg->lvs) { list_iterate_items(lvl, &origin->vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv; if (lvl->lv->status & SNAPSHOT)
if (lv->status & SNAPSHOT)
continue; continue;
if ((snap_seg = find_cow(lv)) && snap_seg->origin == origin) if ((snap_seg = find_cow(lvl->lv)) && snap_seg->origin == origin)
if (!_add_lv(mem, head, lv)) if (!_add_lv(mem, head, lvl->lv))
return 0; return 0;
} }
@ -1963,13 +1987,11 @@ static int _add_lvs(struct pool *mem,
static void _remove_lv(struct list *head, struct logical_volume *lv) static void _remove_lv(struct list *head, struct logical_volume *lv)
{ {
struct list *lvh;
struct lv_list *lvl; struct lv_list *lvl;
list_iterate(lvh, head) { list_iterate_items(lvl, head) {
lvl = list_item(lvh, struct lv_list);
if (lvl->lv == lv) { if (lvl->lv == lv) {
list_del(lvh); list_del(&lvl->list);
break; break;
} }
} }
@ -1979,13 +2001,14 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
{ {
struct logical_volume *active, *old_origin; struct logical_volume *active, *old_origin;
struct lv_segment *snap_seg; struct lv_segment *snap_seg;
struct list *sh, *active_head; struct list *active_head;
struct lv_list *lvl;
active_head = &dm->active_list; active_head = &dm->active_list;
/* Remove any snapshots with given origin */ /* Remove any snapshots with given origin */
list_iterate(sh, active_head) { list_iterate_items(lvl, active_head) {
active = list_item(sh, struct lv_list)->lv; active = lvl->lv;
if ((snap_seg = find_cow(active)) && snap_seg->origin == lv) { if ((snap_seg = find_cow(active)) && snap_seg->origin == lv) {
_remove_lv(active_head, active); _remove_lv(active_head, active);
} }
@ -1999,8 +2022,8 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
old_origin = snap_seg->origin; old_origin = snap_seg->origin;
/* Was this the last active snapshot with this origin? */ /* Was this the last active snapshot with this origin? */
list_iterate(sh, active_head) { list_iterate_items(lvl, active_head) {
active = list_item(sh, struct lv_list)->lv; active = lvl->lv;
if ((snap_seg = find_cow(active)) && if ((snap_seg = find_cow(active)) &&
snap_seg->origin == old_origin) { snap_seg->origin == old_origin) {
return 1; return 1;
@ -2015,13 +2038,14 @@ static int _remove_suspended_lvs(struct dev_manager *dm,
{ {
struct logical_volume *suspended; struct logical_volume *suspended;
struct lv_segment *snap_seg; struct lv_segment *snap_seg;
struct list *sh, *suspend_head; struct list *suspend_head;
struct lv_list *lvl;
suspend_head = &dm->suspend_list; suspend_head = &dm->suspend_list;
/* Remove from list any snapshots with given origin */ /* Remove from list any snapshots with given origin */
list_iterate(sh, suspend_head) { list_iterate_items(lvl, suspend_head) {
suspended = list_item(sh, struct lv_list)->lv; suspended = lvl->lv;
if ((snap_seg = find_cow(suspended)) && if ((snap_seg = find_cow(suspended)) &&
snap_seg->origin == lv) { snap_seg->origin == lv) {
_remove_lv(suspend_head, suspended); _remove_lv(suspend_head, suspended);
@ -2036,13 +2060,13 @@ static int _remove_suspended_lvs(struct dev_manager *dm,
static int _targets_present(struct dev_manager *dm, struct list *lvs) static int _targets_present(struct dev_manager *dm, struct list *lvs)
{ {
struct logical_volume *lv; struct logical_volume *lv;
struct list *lvh, *segh; struct lv_list *lvl;
struct segment_type *segtype; struct segment_type *segtype;
struct lv_segment *seg; struct lv_segment *seg;
int snapshots = 0, mirrors = 0; int snapshots = 0, mirrors = 0;
list_iterate(lvh, lvs) { list_iterate_items(lvl, lvs) {
lv = list_item(lvh, struct lv_list)->lv; lv = lvl->lv;
if (!snapshots) if (!snapshots)
if (lv_is_cow(lv) || lv_is_origin(lv)) if (lv_is_cow(lv) || lv_is_origin(lv))
@ -2053,8 +2077,7 @@ static int _targets_present(struct dev_manager *dm, struct list *lvs)
mirrors = 1; mirrors = 1;
if (lv->status & VIRTUAL) { if (lv->status & VIRTUAL) {
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (seg->segtype->ops->target_present && if (seg->segtype->ops->target_present &&
!seg->segtype->ops->target_present()) { !seg->segtype->ops->target_present()) {
log_error("Can't expand LV: %s target " log_error("Can't expand LV: %s target "
@ -2103,16 +2126,14 @@ static int _targets_present(struct dev_manager *dm, struct list *lvs)
static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg) static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
{ {
char *dlid; char *dlid;
struct list *lvh; struct lv_list *lvl;
struct logical_volume *lv;
struct dev_layer *dl; struct dev_layer *dl;
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv; if (lvl->lv->status & SNAPSHOT)
if (lv->status & SNAPSHOT)
continue; continue;
if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, NULL))) { if (!(dlid = _build_dlid(dm->mem, lvl->lv->lvid.s, NULL))) {
stack; stack;
return 0; return 0;
} }
@ -2121,16 +2142,16 @@ static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
pool_free(dm->mem, dlid); pool_free(dm->mem, dlid);
if (dl) { if (dl) {
log_debug("Found active lv %s%s", lv->name, log_debug("Found active lv %s%s", lvl->lv->name,
dl->info.suspended ? " (suspended)" : ""); dl->info.suspended ? " (suspended)" : "");
if (!_add_lv(dm->mem, &dm->active_list, lv)) { if (!_add_lv(dm->mem, &dm->active_list, lvl->lv)) {
stack; stack;
return 0; return 0;
} }
if (dl->info.suspended) { if (dl->info.suspended) {
if (!_add_lv(dm->mem, &dm->suspend_list, lv)) { if (!_add_lv(dm->mem, &dm->suspend_list, lvl->lv)) {
stack; stack;
return 0; return 0;
} }

25
lib/cache/lvmcache.c vendored
View File

@ -104,8 +104,9 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
const struct format_type *fmt_from_vgname(const char *vgname) const struct format_type *fmt_from_vgname(const char *vgname)
{ {
struct lvmcache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
struct label *label; struct label *label;
struct list *ih, *devh, *tmp; struct list *devh, *tmp;
struct list devs; struct list devs;
struct device_list *devl; struct device_list *devl;
@ -115,9 +116,9 @@ const struct format_type *fmt_from_vgname(const char *vgname)
/* This function is normally called before reading metadata so /* This function is normally called before reading metadata so
* we check cached labels here. Unfortunately vginfo is volatile. */ * we check cached labels here. Unfortunately vginfo is volatile. */
list_init(&devs); list_init(&devs);
list_iterate(ih, &vginfo->infos) { list_iterate_items(info, &vginfo->infos) {
devl = malloc(sizeof(*devl)); devl = dbg_malloc(sizeof(*devl));
devl->dev = list_item(ih, struct lvmcache_info)->dev; devl->dev = info->dev;
list_add(&devs, &devl->list); list_add(&devs, &devl->list);
} }
@ -125,7 +126,7 @@ const struct format_type *fmt_from_vgname(const char *vgname)
devl = list_item(devh, struct device_list); devl = list_item(devh, struct device_list);
label_read(devl->dev, &label); label_read(devl->dev, &label);
list_del(&devl->list); list_del(&devl->list);
free(devl); dbg_free(devl);
} }
return vginfo->fmt; return vginfo->fmt;
@ -186,7 +187,6 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
struct label *label; struct label *label;
struct dev_iter *iter; struct dev_iter *iter;
struct device *dev; struct device *dev;
struct list *fmth;
struct format_type *fmt; struct format_type *fmt;
static int _scanning_in_progress = 0; static int _scanning_in_progress = 0;
@ -221,8 +221,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
_has_scanned = 1; _has_scanned = 1;
/* Perform any format-specific scanning e.g. text files */ /* Perform any format-specific scanning e.g. text files */
list_iterate(fmth, &cmd->formats) { list_iterate_items(fmt, &cmd->formats) {
fmt = list_item(fmth, struct format_type);
if (fmt->ops->scan && !fmt->ops->scan(fmt)) if (fmt->ops->scan && !fmt->ops->scan(fmt))
goto out; goto out;
} }
@ -431,18 +430,16 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
int lvmcache_update_vg(struct volume_group *vg) int lvmcache_update_vg(struct volume_group *vg)
{ {
struct list *pvh; struct pv_list *pvl;
struct physical_volume *pv;
struct lvmcache_info *info; struct lvmcache_info *info;
char pvid_s[ID_LEN + 1]; char pvid_s[ID_LEN + 1];
int vgid_updated = 0; int vgid_updated = 0;
pvid_s[sizeof(pvid_s) - 1] = '\0'; pvid_s[sizeof(pvid_s) - 1] = '\0';
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv; strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1); /* FIXME Could pvl->pv->dev->pvid ever be different? */
/* FIXME Could pv->dev->pvid ever be different? */
if ((info = info_from_pvid(pvid_s))) { if ((info = info_from_pvid(pvid_s))) {
lvmcache_update_vgname(info, vg->name); lvmcache_update_vgname(info, vg->name);
if (!vgid_updated) { if (!vgid_updated) {

View File

@ -622,7 +622,6 @@ static int _init_formats(struct cmd_context *cmd)
const char *format; const char *format;
struct format_type *fmt; struct format_type *fmt;
struct list *fmth;
#ifdef HAVE_LIBDL #ifdef HAVE_LIBDL
const struct config_node *cn; const struct config_node *cn;
@ -689,8 +688,7 @@ static int _init_formats(struct cmd_context *cmd)
format = find_config_str(cmd->cft->root, "global/format", format = find_config_str(cmd->cft->root, "global/format",
DEFAULT_FORMAT); DEFAULT_FORMAT);
list_iterate(fmth, &cmd->formats) { list_iterate_items(fmt, &cmd->formats) {
fmt = list_item(fmth, struct format_type);
if (!strcasecmp(fmt->name, format) || if (!strcasecmp(fmt->name, format) ||
(fmt->alias && !strcasecmp(fmt->alias, format))) { (fmt->alias && !strcasecmp(fmt->alias, format))) {
cmd->default_settings.fmt = fmt; cmd->default_settings.fmt = fmt;

View File

@ -91,13 +91,13 @@
#define DEFAULT_REP_HEADINGS 1 #define DEFAULT_REP_HEADINGS 1
#define DEFAULT_REP_SEPARATOR " " #define DEFAULT_REP_SEPARATOR " "
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,copy_percent" #define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent"
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free" #define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free" #define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size" #define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
#define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size" #define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,lv_uuid" #define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,lv_uuid"
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid" #define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid" #define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize" #define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"

View File

@ -103,6 +103,14 @@ static inline int list_end(struct list *head, struct list *elem)
return elem->n == head; return elem->n == head;
} }
/*
* Return first element of the list or NULL if empty
*/
static inline struct list *list_first(struct list *head)
{
return (list_empty(head) ? NULL : head->n);
}
/* /*
* Return last element of the list or NULL if empty * Return last element of the list or NULL if empty
*/ */
@ -194,6 +202,25 @@ static inline struct list *list_next(struct list *head, struct list *elem)
*/ */
#define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list) #define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list)
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The 'struct list' variable within the containing structure is 'field'.
*/
#define list_iterate_back_items_gen(v, head, field) \
for (v = list_struct_base((head)->p, typeof(*v), field); \
&v->field != (head); \
v = list_struct_base(v->field.p, typeof(*v), field))
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct list list' within the containing structure.
*/
#define list_iterate_back_items(v, head) list_iterate_back_items_gen(v, (head), list)
/* /*
* Return the number of elements in a list by walking it. * Return the number of elements in a list by walking it.
*/ */

View File

@ -196,7 +196,7 @@ static int _compare_paths(const char *path0, const char *path1)
static int _add_alias(struct device *dev, const char *path) static int _add_alias(struct device *dev, const char *path)
{ {
struct str_list *sl = _alloc(sizeof(*sl)); struct str_list *sl = _alloc(sizeof(*sl));
struct list *ah; struct str_list *strl;
const char *oldpath; const char *oldpath;
int prefer_old = 1; int prefer_old = 1;
@ -206,8 +206,8 @@ static int _add_alias(struct device *dev, const char *path)
} }
/* Is name already there? */ /* Is name already there? */
list_iterate(ah, &dev->aliases) { list_iterate_items(strl, &dev->aliases) {
if (!strcmp(list_item(ah, struct str_list)->str, path)) { if (!strcmp(strl->str, path)) {
log_debug("%s: Already in device cache", path); log_debug("%s: Already in device cache", path);
return 1; return 1;
} }
@ -414,20 +414,16 @@ static int _insert(const char *path, int rec)
static void _full_scan(int dev_scan) static void _full_scan(int dev_scan)
{ {
struct list *dh; struct dir_list *dl;
if (_cache.has_scanned && !dev_scan) if (_cache.has_scanned && !dev_scan)
return; return;
list_iterate(dh, &_cache.dirs) { list_iterate_items(dl, &_cache.dirs)
struct dir_list *dl = list_item(dh, struct dir_list);
_insert_dir(dl->dir); _insert_dir(dl->dir);
};
list_iterate(dh, &_cache.files) { list_iterate_items(dl, &_cache.files)
struct dir_list *dl = list_item(dh, struct dir_list);
_insert_file(dl->dir); _insert_file(dl->dir);
};
_cache.has_scanned = 1; _cache.has_scanned = 1;
init_full_scan_done(1); init_full_scan_done(1);

View File

@ -449,29 +449,28 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre) void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
{ {
switch (seg->area[s].type) { switch (seg_type(seg, s)) {
case AREA_PV: case AREA_PV:
/* FIXME Re-check the conditions for 'Missing' */ /* FIXME Re-check the conditions for 'Missing' */
log_print("%sPhysical volume\t%s", pre, log_print("%sPhysical volume\t%s", pre,
seg->area[s].u.pv.pvseg->pv ? seg_pv(seg, s) ?
dev_name(seg->area[s].u.pv.pvseg->pv->dev) : dev_name(seg_dev(seg, s)) :
"Missing"); "Missing");
if (seg->area[s].u.pv.pvseg->pv) if (seg_pv(seg, s))
log_print("%sPhysical extents\t%d to %d", pre, log_print("%sPhysical extents\t%d to %d", pre,
seg->area[s].u.pv.pvseg->pe, seg_pe(seg, s),
seg->area[s].u.pv.pvseg->pe + seg_pe(seg, s) + seg->area_len - 1);
seg->area_len - 1);
break; break;
case AREA_LV: case AREA_LV:
log_print("%sLogical volume\t%s", pre, log_print("%sLogical volume\t%s", pre,
seg->area[s].u.lv.lv ? seg_lv(seg, s) ?
seg->area[s].u.lv.lv->name : "Missing"); seg_lv(seg, s)->name : "Missing");
if (seg->area[s].u.lv.lv) if (seg_lv(seg, s))
log_print("%sLogical extents\t%d to %d", pre, log_print("%sLogical extents\t%d to %d", pre,
seg->area[s].u.lv.le, seg_le(seg, s),
seg->area[s].u.lv.le + seg->area_len - 1); seg_le(seg, s) + seg->area_len - 1);
} }
} }

View File

@ -204,16 +204,14 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
struct pfilter *pf = (struct pfilter *) f->private; struct pfilter *pf = (struct pfilter *) f->private;
void *l = hash_lookup(pf->devices, dev_name(dev)); void *l = hash_lookup(pf->devices, dev_name(dev));
struct str_list *sl; struct str_list *sl;
struct list *ah;
if (!l) { if (!l) {
l = pf->real->passes_filter(pf->real, dev) ? l = pf->real->passes_filter(pf->real, dev) ?
PF_GOOD_DEVICE : PF_BAD_DEVICE; PF_GOOD_DEVICE : PF_BAD_DEVICE;
list_iterate(ah, &dev->aliases) { list_iterate_items(sl, &dev->aliases)
sl = list_item(ah, struct str_list);
hash_insert(pf->devices, sl->str, l); hash_insert(pf->devices, sl->str, l);
}
} else if (l == PF_BAD_DEVICE) } else if (l == PF_BAD_DEVICE)
log_debug("%s: Skipping (cached)", dev_name(dev)); log_debug("%s: Skipping (cached)", dev_name(dev));

View File

@ -158,13 +158,11 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
static int _accept_p(struct dev_filter *f, struct device *dev) static int _accept_p(struct dev_filter *f, struct device *dev)
{ {
struct list *ah;
int m, first = 1, rejected = 0; int m, first = 1, rejected = 0;
struct rfilter *rf = (struct rfilter *) f->private; struct rfilter *rf = (struct rfilter *) f->private;
struct str_list *sl; struct str_list *sl;
list_iterate(ah, &dev->aliases) { list_iterate_items(sl, &dev->aliases) {
sl = list_item(ah, struct str_list);
m = matcher_run(rf->engine, sl->str); m = matcher_run(rf->engine, sl->str);
if (m >= 0) { if (m >= 0) {

View File

@ -424,11 +424,11 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
static void _add_pv_to_list(struct list *head, struct disk_list *data) static void _add_pv_to_list(struct list *head, struct disk_list *data)
{ {
struct list *pvdh;
struct pv_disk *pvd; struct pv_disk *pvd;
struct disk_list *diskl;
list_iterate(pvdh, head) { list_iterate_items(diskl, head) {
pvd = &list_item(pvdh, struct disk_list)->pvd; pvd = &diskl->pvd;
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid, if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
sizeof(pvd->pv_uuid))) { sizeof(pvd->pv_uuid))) {
if (MAJOR(data->dev->dev) != md_major()) { if (MAJOR(data->dev->dev) != md_major()) {
@ -439,7 +439,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
} }
log_very_verbose("Duplicate PV %s - using md %s", log_very_verbose("Duplicate PV %s - using md %s",
pvd->pv_uuid, dev_name(data->dev)); pvd->pv_uuid, dev_name(data->dev));
list_del(pvdh); list_del(&diskl->list);
break; break;
} }
} }
@ -458,14 +458,14 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
struct dev_iter *iter; struct dev_iter *iter;
struct device *dev; struct device *dev;
struct disk_list *data = NULL; struct disk_list *data = NULL;
struct list *vgih;
struct lvmcache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
/* Fast path if we already saw this VG and cached the list of PVs */ /* Fast path if we already saw this VG and cached the list of PVs */
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) && if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
vginfo->infos.n) { vginfo->infos.n) {
list_iterate(vgih, &vginfo->infos) { list_iterate_items(info, &vginfo->infos) {
dev = list_item(vgih, struct lvmcache_info)->dev; dev = info->dev;
if (dev && !(data = read_disk(fmt, dev, mem, vg_name))) if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
break; break;
_add_pv_to_list(head, data); _add_pv_to_list(head, data);
@ -518,18 +518,16 @@ static int _write_vgd(struct disk_list *data)
static int _write_uuids(struct disk_list *data) static int _write_uuids(struct disk_list *data)
{ {
struct uuid_list *ul; struct uuid_list *ul;
struct list *uh;
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base; uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size; uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
list_iterate(uh, &data->uuids) { list_iterate_items(ul, &data->uuids) {
if (pos >= end) { if (pos >= end) {
log_error("Too many uuids to fit on %s", log_error("Too many uuids to fit on %s",
dev_name(data->dev)); dev_name(data->dev));
return 0; return 0;
} }
ul = list_item(uh, struct uuid_list);
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid)) if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
fail; fail;
@ -552,7 +550,7 @@ static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
static int _write_lvs(struct disk_list *data) static int _write_lvs(struct disk_list *data)
{ {
struct list *lvh; struct lvd_list *ll;
uint64_t pos, offset; uint64_t pos, offset;
pos = data->pvd.lv_on_disk.base; pos = data->pvd.lv_on_disk.base;
@ -563,9 +561,7 @@ static int _write_lvs(struct disk_list *data)
return 0; return 0;
} }
list_iterate(lvh, &data->lvds) { list_iterate_items(ll, &data->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
offset = sizeof(struct lv_disk) * ll->lvd.lv_number; offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) { if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
log_error("lv_number %d too large", ll->lvd.lv_number); log_error("lv_number %d too large", ll->lvd.lv_number);
@ -704,11 +700,9 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
*/ */
int write_disks(const struct format_type *fmt, struct list *pvs) int write_disks(const struct format_type *fmt, struct list *pvs)
{ {
struct list *pvh;
struct disk_list *dl; struct disk_list *dl;
list_iterate(pvh, pvs) { list_iterate_items(dl, pvs) {
dl = list_item(pvh, struct disk_list);
if (!(_write_all_pvd(fmt, dl))) if (!(_write_all_pvd(fmt, dl)))
fail; fail;

View File

@ -46,9 +46,7 @@ static int _check_vgs(struct list *pvs, int *partial)
* This means an active VG won't be affected if disks are inserted * This means an active VG won't be affected if disks are inserted
* bearing an exported VG with the same name. * bearing an exported VG with the same name.
*/ */
list_iterate(pvh, pvs) { list_iterate_items(dl, pvs) {
dl = list_item(pvh, struct disk_list);
if (first_time) { if (first_time) {
exported = dl->pvd.pv_status & VG_EXPORTED; exported = dl->pvd.pv_status & VG_EXPORTED;
first_time = 0; first_time = 0;
@ -246,13 +244,10 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
struct list *pvds, const char *dev_dir, struct list *pvds, const char *dev_dir,
struct dev_filter *filter) struct dev_filter *filter)
{ {
struct list *pvh;
struct pv_list *pvl; struct pv_list *pvl;
struct disk_list *data; struct disk_list *data;
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) { if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
stack; stack;
return 0; return 0;

View File

@ -87,7 +87,7 @@ int import_pv(struct pool *mem, struct device *dev,
pv->pe_size = pvd->pe_size; pv->pe_size = pvd->pe_size;
pv->pe_start = pvd->pe_start; pv->pe_start = pvd->pe_start;
pv->pe_count = pvd->pe_total; pv->pe_count = pvd->pe_total;
pv->pe_alloc_count = pvd->pe_allocated; pv->pe_alloc_count = 0;
list_init(&pv->tags); list_init(&pv->tags);
list_init(&pv->segments); list_init(&pv->segments);
@ -382,14 +382,11 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
int export_extents(struct disk_list *dl, uint32_t lv_num, int export_extents(struct disk_list *dl, uint32_t lv_num,
struct logical_volume *lv, struct physical_volume *pv) struct logical_volume *lv, struct physical_volume *pv)
{ {
struct list *segh;
struct pe_disk *ped; struct pe_disk *ped;
struct lv_segment *seg; struct lv_segment *seg;
uint32_t pe, s; uint32_t pe, s;
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) { if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
log_error("Segment type %s in LV %s: " log_error("Segment type %s in LV %s: "
@ -397,17 +394,16 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
seg->segtype->name, lv->name); seg->segtype->name, lv->name);
return 0; return 0;
} }
if (seg->area[s].type != AREA_PV) { if (seg_type(seg, s) != AREA_PV) {
log_error("LV stripe found in LV %s: " log_error("LV stripe found in LV %s: "
"unsupported by format1", lv->name); "unsupported by format1", lv->name);
return 0; return 0;
} }
if (seg->area[s].u.pv.pvseg->pv != pv) if (seg_pv(seg, s) != pv)
continue; /* not our pv */ continue; /* not our pv */
for (pe = 0; pe < (seg->len / seg->area_count); pe++) { for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
ped = &dl->extents[pe + ped = &dl->extents[pe + seg_pe(seg, s)];
seg->area[s].u.pv.pvseg->pe];
ped->lv_num = lv_num; ped->lv_num = lv_num;
ped->le_num = (seg->le / seg->area_count) + pe + ped->le_num = (seg->le / seg->area_count) + pe +
s * (lv->le_count / seg->area_count); s * (lv->le_count / seg->area_count);
@ -422,15 +418,11 @@ int import_pvs(const struct format_type *fmt, struct pool *mem,
struct volume_group *vg, struct volume_group *vg,
struct list *pvds, struct list *results, int *count) struct list *pvds, struct list *results, int *count)
{ {
struct list *pvdh;
struct disk_list *dl; struct disk_list *dl;
struct pv_list *pvl; struct pv_list *pvl;
*count = 0; *count = 0;
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds) {
dl = list_item(pvdh, struct disk_list);
if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) || if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = pool_alloc(mem, sizeof(*pvl->pv)))) { !(pvl->pv = pool_alloc(mem, sizeof(*pvl->pv)))) {
stack; stack;
@ -481,12 +473,9 @@ int import_lvs(struct pool *mem, struct volume_group *vg, struct list *pvds)
struct disk_list *dl; struct disk_list *dl;
struct lvd_list *ll; struct lvd_list *ll;
struct lv_disk *lvd; struct lv_disk *lvd;
struct list *pvdh, *lvdh;
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds) {
dl = list_item(pvdh, struct disk_list); list_iterate_items(ll, &dl->lvds) {
list_iterate(lvdh, &dl->lvds) {
ll = list_item(lvdh, struct lvd_list);
lvd = &ll->lvd; lvd = &ll->lvd;
if (!find_lv(vg, lvd->lv_name) && if (!find_lv(vg, lvd->lv_name) &&
@ -505,7 +494,6 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
struct physical_volume *pv, const char *dev_dir) struct physical_volume *pv, const char *dev_dir)
{ {
int r = 0; int r = 0;
struct list *lvh;
struct lv_list *ll; struct lv_list *ll;
struct lvd_list *lvdl; struct lvd_list *lvdl;
size_t len; size_t len;
@ -532,8 +520,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
} }
memset(dl->extents, 0, len); memset(dl->extents, 0, len);
list_iterate(lvh, &vg->lvs) { list_iterate_items(ll, &vg->lvs) {
ll = list_item(lvh, struct lv_list);
if (ll->lv->status & SNAPSHOT) if (ll->lv->status & SNAPSHOT)
continue; continue;
@ -585,19 +572,17 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
struct list *pvds) struct list *pvds)
{ {
struct logical_volume *lvs[MAX_LV]; struct logical_volume *lvs[MAX_LV];
struct list *pvdh, *lvdh;
struct disk_list *dl; struct disk_list *dl;
struct lvd_list *ll;
struct lv_disk *lvd; struct lv_disk *lvd;
int lvnum; int lvnum;
struct logical_volume *org, *cow; struct logical_volume *org, *cow;
/* build an index of lv numbers */ /* build an index of lv numbers */
memset(lvs, 0, sizeof(lvs)); memset(lvs, 0, sizeof(lvs));
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds) {
dl = list_item(pvdh, struct disk_list); list_iterate_items(ll, &dl->lvds) {
lvd = &ll->lvd;
list_iterate(lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
lvnum = lvd->lv_number; lvnum = lvd->lv_number;
@ -619,11 +604,9 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
/* /*
* Now iterate through yet again adding the snapshots. * Now iterate through yet again adding the snapshots.
*/ */
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds) {
dl = list_item(pvdh, struct disk_list); list_iterate_items(ll, &dl->lvds) {
lvd = &ll->lvd;
list_iterate(lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
if (!(lvd->lv_access & LV_SNAPSHOT)) if (!(lvd->lv_access & LV_SNAPSHOT))
continue; continue;
@ -657,10 +640,8 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
{ {
struct uuid_list *ul; struct uuid_list *ul;
struct pv_list *pvl; struct pv_list *pvl;
struct list *pvh;
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
if (!(ul = pool_alloc(dl->mem, sizeof(*ul)))) { if (!(ul = pool_alloc(dl->mem, sizeof(*ul)))) {
stack; stack;
return 0; return 0;
@ -680,41 +661,32 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
*/ */
void export_numbers(struct list *pvds, struct volume_group *vg) void export_numbers(struct list *pvds, struct volume_group *vg)
{ {
struct list *pvdh;
struct disk_list *dl; struct disk_list *dl;
int pv_num = 1; int pv_num = 1;
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds)
dl = list_item(pvdh, struct disk_list);
dl->pvd.pv_number = pv_num++; dl->pvd.pv_number = pv_num++;
} }
}
/* /*
* Calculate vg_disk->pv_act. * Calculate vg_disk->pv_act.
*/ */
void export_pv_act(struct list *pvds) void export_pv_act(struct list *pvds)
{ {
struct list *pvdh;
struct disk_list *dl; struct disk_list *dl;
int act = 0; int act = 0;
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds)
dl = list_item(pvdh, struct disk_list);
if (dl->pvd.pv_status & PV_ACTIVE) if (dl->pvd.pv_status & PV_ACTIVE)
act++; act++;
}
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds)
dl = list_item(pvdh, struct disk_list);
dl->vgd.pv_act = act; dl->vgd.pv_act = act;
} }
}
int export_vg_number(struct format_instance *fid, struct list *pvds, int export_vg_number(struct format_instance *fid, struct list *pvds,
const char *vg_name, struct dev_filter *filter) const char *vg_name, struct dev_filter *filter)
{ {
struct list *pvdh;
struct disk_list *dl; struct disk_list *dl;
int vg_num; int vg_num;
@ -723,10 +695,8 @@ int export_vg_number(struct format_instance *fid, struct list *pvds,
return 0; return 0;
} }
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds)
dl = list_item(pvdh, struct disk_list);
dl->vgd.vg_number = vg_num; dl->vgd.vg_number = vg_num;
}
return 1; return 1;
} }

View File

@ -48,7 +48,6 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
struct volume_group *vg) struct volume_group *vg)
{ {
struct hash_table *maps = hash_create(32); struct hash_table *maps = hash_create(32);
struct list *llh;
struct lv_list *ll; struct lv_list *ll;
struct lv_map *lvm; struct lv_map *lvm;
@ -58,8 +57,7 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
return NULL; return NULL;
} }
list_iterate(llh, &vg->lvs) { list_iterate_items(ll, &vg->lvs) {
ll = list_item(llh, struct lv_list);
if (ll->lv->status & SNAPSHOT) if (ll->lv->status & SNAPSHOT)
continue; continue;
@ -91,13 +89,12 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
static int _fill_lv_array(struct lv_map **lvs, static int _fill_lv_array(struct lv_map **lvs,
struct hash_table *maps, struct disk_list *dl) struct hash_table *maps, struct disk_list *dl)
{ {
struct list *lvh; struct lvd_list *ll;
struct lv_map *lvm; struct lv_map *lvm;
memset(lvs, 0, sizeof(*lvs) * MAX_LV); memset(lvs, 0, sizeof(*lvs) * MAX_LV);
list_iterate(lvh, &dl->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
list_iterate_items(ll, &dl->lvds) {
if (!(lvm = hash_lookup(maps, strrchr(ll->lvd.lv_name, '/') if (!(lvm = hash_lookup(maps, strrchr(ll->lvd.lv_name, '/')
+ 1))) { + 1))) {
log_err("Physical volume (%s) contains an " log_err("Physical volume (%s) contains an "
@ -118,15 +115,13 @@ static int _fill_lv_array(struct lv_map **lvs,
static int _fill_maps(struct hash_table *maps, struct volume_group *vg, static int _fill_maps(struct hash_table *maps, struct volume_group *vg,
struct list *pvds) struct list *pvds)
{ {
struct list *pvdh;
struct disk_list *dl; struct disk_list *dl;
struct physical_volume *pv; struct physical_volume *pv;
struct lv_map *lvms[MAX_LV], *lvm; struct lv_map *lvms[MAX_LV], *lvm;
struct pe_disk *e; struct pe_disk *e;
uint32_t i, lv_num, le; uint32_t i, lv_num, le;
list_iterate(pvdh, pvds) { list_iterate_items(dl, pvds) {
dl = list_item(pvdh, struct disk_list);
pv = find_pv(vg, dl->dev); pv = find_pv(vg, dl->dev);
e = dl->extents; e = dl->extents;
@ -226,7 +221,7 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
lvm->map[le + len].pe == lvm->map[le].pe + len)); lvm->map[le + len].pe == lvm->map[le].pe + len));
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le, if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
len, 0, 0, 1, len, 0, 0))) { len, 0, 0, NULL, 1, len, 0, 0, 0))) {
log_error("Failed to allocate linear segment."); log_error("Failed to allocate linear segment.");
return 0; return 0;
} }
@ -300,8 +295,9 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
lvm->stripes * le, lvm->stripes * le,
lvm->stripes * area_len, lvm->stripes * area_len,
0, lvm->stripe_size, lvm->stripes, 0, lvm->stripe_size, NULL,
area_len, 0, 0))) { lvm->stripes,
area_len, 0, 0, 0))) {
log_error("Failed to allocate striped segment."); log_error("Failed to allocate striped segment.");
return 0; return 0;
} }

View File

@ -27,7 +27,6 @@
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter, int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
const char *candidate_vg, int *result) const char *candidate_vg, int *result)
{ {
struct list *pvh;
struct list all_pvs; struct list all_pvs;
struct disk_list *dl; struct disk_list *dl;
struct pool *mem = pool_create("lvm1 vg_number", 10 * 1024); struct pool *mem = pool_create("lvm1 vg_number", 10 * 1024);
@ -47,8 +46,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
memset(numbers, 0, sizeof(numbers)); memset(numbers, 0, sizeof(numbers));
list_iterate(pvh, &all_pvs) { list_iterate_items(dl, &all_pvs) {
dl = list_item(pvh, struct disk_list);
if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg)) if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
continue; continue;

View File

@ -57,12 +57,9 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
static void _add_pl_to_list(struct list *head, struct pool_list *data) static void _add_pl_to_list(struct list *head, struct pool_list *data)
{ {
struct list *pvdh;
struct pool_list *pl; struct pool_list *pl;
list_iterate(pvdh, head) { list_iterate_items(pl, head) {
pl = list_item(pvdh, struct pool_list);
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) { if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
char uuid[ID_LEN + 7]; char uuid[ID_LEN + 7];
@ -76,7 +73,7 @@ static void _add_pl_to_list(struct list *head, struct pool_list *data)
} }
log_very_verbose("Duplicate PV %s - using md %s", log_very_verbose("Duplicate PV %s - using md %s",
uuid, dev_name(data->dev)); uuid, dev_name(data->dev));
list_del(pvdh); list_del(&pl->list);
break; break;
} }
} }
@ -247,11 +244,9 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
struct lvmcache_vginfo *vginfo, struct list *head, struct lvmcache_vginfo *vginfo, struct list *head,
uint32_t *devcount) uint32_t *devcount)
{ {
struct lvmcache_info *info;
struct list *vgih = NULL; struct pool_list *pl;
struct device *dev; struct pool *tmpmem;
struct pool_list *pl = NULL;
struct pool *tmpmem = NULL;
uint32_t sp_count = 0; uint32_t sp_count = 0;
uint32_t *sp_devs = NULL; uint32_t *sp_devs = NULL;
@ -264,16 +259,16 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
return 0; return 0;
} }
list_iterate(vgih, &vginfo->infos) { list_iterate_items(info, &vginfo->infos) {
dev = list_item(vgih, struct lvmcache_info)->dev; if (info->dev &&
if (dev && !(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
!(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
break; break;
/* /*
* We need to keep track of the total expected number * We need to keep track of the total expected number
* of devices per subpool * of devices per subpool
*/ */
if (!sp_count) { if (!sp_count) {
/* FIXME pl left uninitialised if !info->dev */
sp_count = pl->pd.pl_subpools; sp_count = pl->pd.pl_subpools;
if (!(sp_devs = if (!(sp_devs =
pool_zalloc(tmpmem, pool_zalloc(tmpmem,
@ -298,9 +293,8 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
} }
*devcount = 0; *devcount = 0;
for (i = 0; i < sp_count; i++) { for (i = 0; i < sp_count; i++)
*devcount += sp_devs[i]; *devcount += sp_devs[i];
}
pool_destroy(tmpmem); pool_destroy(tmpmem);

View File

@ -33,8 +33,6 @@
static struct user_subpool *_build_usp(struct list *pls, struct pool *mem, static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
int *sps) int *sps)
{ {
struct list *plhs;
struct pool_list *pl; struct pool_list *pl;
struct user_subpool *usp = NULL, *cur_sp = NULL; struct user_subpool *usp = NULL, *cur_sp = NULL;
struct user_device *cur_dev = NULL; struct user_device *cur_dev = NULL;
@ -43,9 +41,7 @@ static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
* FIXME: Need to do some checks here - I'm tempted to add a * FIXME: Need to do some checks here - I'm tempted to add a
* user_pool structure and build the entire thing to check against. * user_pool structure and build the entire thing to check against.
*/ */
list_iterate(plhs, pls) { list_iterate_items(pl, pls) {
pl = list_item(plhs, struct pool_list);
*sps = pl->pd.pl_subpools; *sps = pl->pd.pl_subpools;
if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) { if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
log_error("Unable to allocate %d subpool structures", log_error("Unable to allocate %d subpool structures",
@ -72,13 +68,13 @@ static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
"structures", pl->pd.pl_sp_devs); "structures", pl->pd.pl_sp_devs);
return 0; return 0;
} }
cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid]; cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
cur_dev->sp_id = cur_sp->id; cur_dev->sp_id = cur_sp->id;
cur_dev->devid = pl->pd.pl_sp_id; cur_dev->devid = pl->pd.pl_sp_id;
cur_dev->blocks = pl->pd.pl_blocks; cur_dev->blocks = pl->pd.pl_blocks;
cur_dev->pv = pl->pv; cur_dev->pv = pl->pv;
cur_dev->initialized = 1; cur_dev->initialized = 1;
} }
return usp; return usp;

View File

@ -30,12 +30,9 @@
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls) int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
{ {
struct list *plhs;
struct pool_list *pl; struct pool_list *pl;
list_iterate(plhs, pls) { list_iterate_items(pl, pls) {
pl = list_item(plhs, struct pool_list);
vg->extent_count += vg->extent_count +=
((pl->pd.pl_blocks) / POOL_PE_SIZE); ((pl->pd.pl_blocks) / POOL_PE_SIZE);
@ -61,7 +58,6 @@ int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls) int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
{ {
struct pool_list *pl; struct pool_list *pl;
struct list *plhs;
struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl)); struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
struct logical_volume *lv; struct logical_volume *lv;
@ -88,9 +84,7 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
list_init(&lv->segments); list_init(&lv->segments);
list_init(&lv->tags); list_init(&lv->tags);
list_iterate(plhs, pls) { list_iterate_items(pl, pls) {
pl = list_item(plhs, struct pool_list);
lv->size += pl->pd.pl_blocks; lv->size += pl->pd.pl_blocks;
if (lv->name) if (lv->name)
@ -134,11 +128,8 @@ int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
{ {
struct pv_list *pvl; struct pv_list *pvl;
struct pool_list *pl; struct pool_list *pl;
struct list *plhs;
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
list_iterate_items(pl, pls) {
if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) { if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
log_error("Unable to allocate pv list structure"); log_error("Unable to allocate pv list structure");
return 0; return 0;
@ -180,7 +171,7 @@ int import_pool_pv(const struct format_type *fmt, struct pool *mem,
pv->pe_size = POOL_PE_SIZE; pv->pe_size = POOL_PE_SIZE;
pv->pe_start = POOL_PE_START; pv->pe_start = POOL_PE_START;
pv->pe_count = pv->size / POOL_PE_SIZE; pv->pe_count = pv->size / POOL_PE_SIZE;
pv->pe_alloc_count = pv->pe_count; pv->pe_alloc_count = 0;
list_init(&pv->tags); list_init(&pv->tags);
list_init(&pv->segments); list_init(&pv->segments);
@ -230,8 +221,8 @@ static int _add_stripe_seg(struct pool *mem,
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur, if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
area_len * usp->num_devs, 0, area_len * usp->num_devs, 0,
usp->striping, usp->num_devs, area_len, usp->striping, NULL, usp->num_devs,
0, 0))) { area_len, 0, 0, 0))) {
log_error("Unable to allocate striped lv_segment structure"); log_error("Unable to allocate striped lv_segment structure");
return 0; return 0;
} }
@ -271,7 +262,8 @@ static int _add_linear_seg(struct pool *mem,
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur, if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
area_len, 0, usp->striping, area_len, 0, usp->striping,
1, area_len, POOL_PE_SIZE, 0))) { NULL, 1, area_len,
POOL_PE_SIZE, 0, 0))) {
log_error("Unable to allocate linear lv_segment " log_error("Unable to allocate linear lv_segment "
"structure"); "structure");
return 0; return 0;
@ -295,15 +287,12 @@ static int _add_linear_seg(struct pool *mem,
int import_pool_segments(struct list *lvs, struct pool *mem, int import_pool_segments(struct list *lvs, struct pool *mem,
struct user_subpool *usp, int subpools) struct user_subpool *usp, int subpools)
{ {
struct list *lvhs;
struct lv_list *lvl; struct lv_list *lvl;
struct logical_volume *lv; struct logical_volume *lv;
uint32_t le_cur = 0; uint32_t le_cur = 0;
int i; int i;
list_iterate(lvhs, lvs) { list_iterate_items(lvl, lvs) {
lvl = list_item(lvhs, struct lv_list);
lv = lvl->lv; lv = lvl->lv;
if (lv->status & SNAPSHOT) if (lv->status & SNAPSHOT)
@ -325,5 +314,4 @@ int import_pool_segments(struct list *lvs, struct pool *mem,
} }
return 1; return 1;
} }

View File

@ -91,7 +91,6 @@ static int _split_vg(const char *filename, char *vgname, size_t vg_size,
static void _insert_file(struct list *head, struct archive_file *b) static void _insert_file(struct list *head, struct archive_file *b)
{ {
struct list *bh;
struct archive_file *bf = NULL; struct archive_file *bf = NULL;
if (list_empty(head)) { if (list_empty(head)) {
@ -99,11 +98,9 @@ static void _insert_file(struct list *head, struct archive_file *b)
return; return;
} }
/* index increases through list */ /* index reduces through list */
list_iterate(bh, head) { list_iterate_items(bf, head) {
bf = list_item(bh, struct archive_file); if (b->index > bf->index) {
if (bf->index > b->index) {
list_add(&bf->list, &b->list); list_add(&bf->list, &b->list);
return; return;
} }
@ -200,7 +197,6 @@ static struct list *_scan_archive(struct pool *mem,
static void _remove_expired(struct list *archives, uint32_t archives_size, static void _remove_expired(struct list *archives, uint32_t archives_size,
uint32_t retain_days, uint32_t min_archive) uint32_t retain_days, uint32_t min_archive)
{ {
struct list *bh;
struct archive_file *bf; struct archive_file *bf;
struct stat sb; struct stat sb;
time_t retain_time; time_t retain_time;
@ -214,9 +210,7 @@ static void _remove_expired(struct list *archives, uint32_t archives_size,
retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY; retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
/* Assume list is ordered oldest first (by index) */ /* Assume list is ordered oldest first (by index) */
list_iterate(bh, archives) { list_iterate_items(bf, archives) {
bf = list_item(bh, struct archive_file);
/* Get the mtime of the file and unlink if too old */ /* Get the mtime of the file and unlink if too old */
if (stat(bf->path, &sb)) { if (stat(bf->path, &sb)) {
log_sys_error("stat", bf->path); log_sys_error("stat", bf->path);
@ -280,7 +274,7 @@ int archive_vg(struct volume_group *vg,
if (list_empty(archives)) if (list_empty(archives))
ix = 0; ix = 0;
else { else {
last = list_item(archives->p, struct archive_file); last = list_item(list_first(archives), struct archive_file);
ix = last->index + 1; ix = last->index + 1;
} }
@ -345,7 +339,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname) int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
{ {
struct list *archives, *ah; struct list *archives;
struct archive_file *af; struct archive_file *af;
if (!(archives = _scan_archive(cmd->mem, vgname, dir))) { if (!(archives = _scan_archive(cmd->mem, vgname, dir))) {
@ -356,11 +350,8 @@ int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
if (list_empty(archives)) if (list_empty(archives))
log_print("No archives found in %s.", dir); log_print("No archives found in %s.", dir);
list_iterate(ah, archives) { list_iterate_back_items(af, archives)
af = list_item(ah, struct archive_file);
_display_archive(cmd, af); _display_archive(cmd, af);
}
pool_free(cmd->mem, archives); pool_free(cmd->mem, archives);

View File

@ -330,7 +330,7 @@ static inline const char *_get_pv_name(struct formatter *f,
static int _print_pvs(struct formatter *f, struct volume_group *vg) static int _print_pvs(struct formatter *f, struct volume_group *vg)
{ {
struct list *pvh; struct pv_list *pvl;
struct physical_volume *pv; struct physical_volume *pv;
char buffer[4096]; char buffer[4096];
const char *name; const char *name;
@ -338,8 +338,8 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
outf(f, "physical_volumes {"); outf(f, "physical_volumes {");
_inc_indent(f); _inc_indent(f);
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv; pv = pvl->pv;
if (!(name = _get_pv_name(f, pv))) { if (!(name = _get_pv_name(f, pv))) {
stack; stack;
@ -442,22 +442,21 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
_inc_indent(f); _inc_indent(f);
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) { switch (seg_type(seg, s)) {
case AREA_PV: case AREA_PV:
if (!(name = _get_pv_name(f, seg->area[s].u.pv.pvseg-> if (!(name = _get_pv_name(f, seg_pv(seg, s)))) {
pv))) {
stack; stack;
return 0; return 0;
} }
outf(f, "\"%s\", %u%s", name, outf(f, "\"%s\", %u%s", name,
seg->area[s].u.pv.pvseg->pe, seg_pe(seg, s),
(s == seg->area_count - 1) ? "" : ","); (s == seg->area_count - 1) ? "" : ",");
break; break;
case AREA_LV: case AREA_LV:
outf(f, "\"%s\", %u%s", outf(f, "\"%s\", %u%s",
seg->area[s].u.lv.lv->name, seg_lv(seg, s)->name,
seg->area[s].u.lv.le, seg_le(seg, s),
(s == seg->area_count - 1) ? "" : ","); (s == seg->area_count - 1) ? "" : ",");
} }
} }
@ -467,37 +466,12 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
return 1; return 1;
} }
static int _count_segments(struct logical_volume *lv) static int _print_lv(struct formatter *f, struct logical_volume *lv)
{ {
int r = 0;
struct list *segh;
list_iterate(segh, &lv->segments)
r++;
return r;
}
static int _print_lvs(struct formatter *f, struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_segment *seg; struct lv_segment *seg;
char buffer[4096]; char buffer[4096];
int seg_count; int seg_count;
/*
* Don't bother with an lv section if there are no lvs.
*/
if (list_empty(&vg->lvs))
return 1;
outf(f, "logical_volumes {");
_inc_indent(f);
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
f->nl(f); f->nl(f);
outf(f, "%s {", lv->name); outf(f, "%s {", lv->name);
_inc_indent(f); _inc_indent(f);
@ -534,12 +508,12 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
outf(f, "major = %d", lv->major); outf(f, "major = %d", lv->major);
if (lv->minor >= 0) if (lv->minor >= 0)
outf(f, "minor = %d", lv->minor); outf(f, "minor = %d", lv->minor);
outf(f, "segment_count = %u", _count_segments(lv)); outf(f, "segment_count = %u", list_size(&lv->segments));
f->nl(f); f->nl(f);
seg_count = 1; seg_count = 1;
list_iterate_items(seg, &lv->segments) { list_iterate_items(seg, &lv->segments) {
if (!_print_segment(f, vg, seg_count++, seg)) { if (!_print_segment(f, lv->vg, seg_count++, seg)) {
stack; stack;
return 0; return 0;
} }
@ -547,6 +521,42 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
_dec_indent(f); _dec_indent(f);
outf(f, "}"); outf(f, "}");
return 1;
}
static int _print_lvs(struct formatter *f, struct volume_group *vg)
{
struct lv_list *lvl;
/*
* Don't bother with an lv section if there are no lvs.
*/
if (list_empty(&vg->lvs))
return 1;
outf(f, "logical_volumes {");
_inc_indent(f);
/*
* Write visible LVs first
*/
list_iterate_items(lvl, &vg->lvs) {
if (!(lvl->lv->status & VISIBLE_LV))
continue;
if (!_print_lv(f, lvl->lv)) {
stack;
return 0;
}
}
list_iterate_items(lvl, &vg->lvs) {
if ((lvl->lv->status & VISIBLE_LV))
continue;
if (!_print_lv(f, lvl->lv)) {
stack;
return 0;
}
} }
_dec_indent(f); _dec_indent(f);
@ -563,7 +573,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
static int _build_pv_names(struct formatter *f, struct volume_group *vg) static int _build_pv_names(struct formatter *f, struct volume_group *vg)
{ {
int count = 0; int count = 0;
struct list *pvh; struct pv_list *pvl;
struct physical_volume *pv; struct physical_volume *pv;
char buffer[32], *name; char buffer[32], *name;
@ -577,8 +587,8 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
goto bad; goto bad;
} }
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv; pv = pvl->pv;
/* FIXME But skip if there's already an LV called pv%d ! */ /* FIXME But skip if there's already an LV called pv%d ! */
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) { if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {

View File

@ -52,6 +52,7 @@ static struct flag _lv_flags[] = {
{VISIBLE_LV, "VISIBLE"}, {VISIBLE_LV, "VISIBLE"},
{PVMOVE, "PVMOVE"}, {PVMOVE, "PVMOVE"},
{LOCKED, "LOCKED"}, {LOCKED, "LOCKED"},
{MIRROR_LOG, NULL},
{MIRRORED, NULL}, {MIRRORED, NULL},
{VIRTUAL, NULL}, {VIRTUAL, NULL},
{SNAPSHOT, NULL}, {SNAPSHOT, NULL},

View File

@ -341,8 +341,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn; struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct raw_locn *rlocn; struct raw_locn *rlocn;
struct mda_header *mdah; struct mda_header *mdah;
struct physical_volume *pv; struct pv_list *pvl;
struct list *pvh;
int r = 0; int r = 0;
uint32_t new_wrap = 0, old_wrap = 0; uint32_t new_wrap = 0, old_wrap = 0;
@ -351,9 +350,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
int found = 0; int found = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */ /* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv; if (pvl->pv->dev == mdac->area.dev) {
if (pv->dev == mdac->area.dev) {
found = 1; found = 1;
break; break;
} }
@ -446,15 +444,13 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn; struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct mda_header *mdah; struct mda_header *mdah;
struct raw_locn *rlocn; struct raw_locn *rlocn;
struct physical_volume *pv; struct pv_list *pvl;
struct list *pvh;
int r = 0; int r = 0;
int found = 0; int found = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */ /* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv; if (pvl->pv->dev == mdac->area.dev) {
if (pv->dev == mdac->area.dev) {
found = 1; found = 1;
break; break;
} }
@ -518,14 +514,12 @@ static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
struct metadata_area *mda) struct metadata_area *mda)
{ {
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn; struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct physical_volume *pv; struct pv_list *pvl;
struct list *pvh;
int found = 0; int found = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */ /* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv; if (pvl->pv->dev == mdac->area.dev) {
if (pv->dev == mdac->area.dev) {
found = 1; found = 1;
break; break;
} }
@ -784,7 +778,7 @@ static int _scan_file(const struct format_type *fmt)
{ {
struct dirent *dirent; struct dirent *dirent;
struct dir_list *dl; struct dir_list *dl;
struct list *dlh, *dir_list; struct list *dir_list;
char *tmp; char *tmp;
DIR *d; DIR *d;
struct volume_group *vg; struct volume_group *vg;
@ -794,8 +788,7 @@ static int _scan_file(const struct format_type *fmt)
dir_list = &((struct mda_lists *) fmt->private)->dirs; dir_list = &((struct mda_lists *) fmt->private)->dirs;
list_iterate(dlh, dir_list) { list_iterate_items(dl, dir_list) {
dl = list_item(dlh, struct dir_list);
if (!(d = opendir(dl->dir))) { if (!(d = opendir(dl->dir))) {
log_sys_error("opendir", dl->dir); log_sys_error("opendir", dl->dir);
continue; continue;
@ -883,7 +876,7 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
static int _scan_raw(const struct format_type *fmt) static int _scan_raw(const struct format_type *fmt)
{ {
struct raw_list *rl; struct raw_list *rl;
struct list *rlh, *raw_list; struct list *raw_list;
char vgnamebuf[NAME_LEN + 2]; char vgnamebuf[NAME_LEN + 2];
struct volume_group *vg; struct volume_group *vg;
struct format_instance fid; struct format_instance fid;
@ -893,9 +886,7 @@ static int _scan_raw(const struct format_type *fmt)
fid.fmt = fmt; fid.fmt = fmt;
list_init(&fid.metadata_areas); list_init(&fid.metadata_areas);
list_iterate(rlh, raw_list) { list_iterate_items(rl, raw_list) {
rl = list_item(rlh, struct raw_list);
/* FIXME We're reading mdah twice here... */ /* FIXME We're reading mdah twice here... */
if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf, if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf,
sizeof(vgnamebuf))) { sizeof(vgnamebuf))) {
@ -925,6 +916,7 @@ static int _mda_setup(const struct format_type *fmt,
uint64_t start1, mda_size1; /* First area - start of disk */ uint64_t start1, mda_size1; /* First area - start of disk */
uint64_t start2, mda_size2; /* Second area - end of disk */ uint64_t start2, mda_size2; /* Second area - end of disk */
uint64_t wipe_size = 8 << SECTOR_SHIFT; uint64_t wipe_size = 8 << SECTOR_SHIFT;
size_t pagesize = getpagesize();
if (!pvmetadatacopies) { if (!pvmetadatacopies) {
/* Space available for PEs */ /* Space available for PEs */
@ -952,10 +944,21 @@ static int _mda_setup(const struct format_type *fmt,
/* Place mda straight after label area at start of disk */ /* Place mda straight after label area at start of disk */
start1 = LABEL_SCAN_SIZE; start1 = LABEL_SCAN_SIZE;
/* Unless the space available is tiny, round to PAGE_SIZE boundary */
if ((!pe_start && !pe_end) ||
((pe_start > start1) && (pe_start - start1 >= MDA_SIZE_MIN))) {
mda_adjustment = start1 % pagesize;
if (mda_adjustment) {
start1 += (pagesize - mda_adjustment);
pv->size -= ((pagesize - mda_adjustment) >>
SECTOR_SHIFT);
}
}
/* Ensure it's not going to be bigger than the disk! */ /* Ensure it's not going to be bigger than the disk! */
if (mda_size1 > disk_size) { if (start1 + mda_size1 > disk_size) {
log_print("Warning: metadata area fills disk %s", log_print("Warning: metadata area fills disk leaving no "
dev_name(pv->dev)); "space for data on %s.", dev_name(pv->dev));
/* Leave some free space for rounding */ /* Leave some free space for rounding */
/* Avoid empty data area as could cause tools problems */ /* Avoid empty data area as could cause tools problems */
mda_size1 = disk_size - start1 - alignment * 2; mda_size1 = disk_size - start1 - alignment * 2;
@ -1048,7 +1051,6 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct label *label; struct label *label;
struct lvmcache_info *info; struct lvmcache_info *info;
struct mda_context *mdac; struct mda_context *mdac;
struct list *mdash;
struct metadata_area *mda; struct metadata_area *mda;
char buf[MDA_HEADER_SIZE]; char buf[MDA_HEADER_SIZE];
struct mda_header *mdah = (struct mda_header *) buf; struct mda_header *mdah = (struct mda_header *) buf;
@ -1076,8 +1078,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
del_mdas(&info->mdas); del_mdas(&info->mdas);
else else
list_init(&info->mdas); list_init(&info->mdas);
list_iterate(mdash, mdas) { list_iterate_items(mda, mdas) {
mda = list_item(mdash, struct metadata_area);
mdac = mda->metadata_locn; mdac = mda->metadata_locn;
log_debug("Creating metadata area on %s at sector %" log_debug("Creating metadata area on %s at sector %"
PRIu64 " size %" PRIu64 " sectors", PRIu64 " size %" PRIu64 " sectors",
@ -1100,8 +1101,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
/* Set pe_start to first aligned sector after any metadata /* Set pe_start to first aligned sector after any metadata
* areas that begin before pe_start */ * areas that begin before pe_start */
pv->pe_start = PE_ALIGN; pv->pe_start = PE_ALIGN;
list_iterate(mdash, &info->mdas) { list_iterate_items(mda, &info->mdas) {
mda = list_item(mdash, struct metadata_area);
mdac = (struct mda_context *) mda->metadata_locn; mdac = (struct mda_context *) mda->metadata_locn;
if (pv->dev == mdac->area.dev && if (pv->dev == mdac->area.dev &&
(mdac->area.start < (pv->pe_start << SECTOR_SHIFT)) && (mdac->area.start < (pv->pe_start << SECTOR_SHIFT)) &&
@ -1125,8 +1125,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
return 0; return 0;
} }
list_iterate(mdash, &info->mdas) { list_iterate_items(mda, &info->mdas) {
mda = list_item(mdash, struct metadata_area);
mdac = mda->metadata_locn; mdac = mda->metadata_locn;
memset(&buf, 0, sizeof(buf)); memset(&buf, 0, sizeof(buf));
mdah->size = mdac->area.size; mdah->size = mdac->area.size;
@ -1152,14 +1151,13 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
static int _add_raw(struct list *raw_list, struct device_area *dev_area) static int _add_raw(struct list *raw_list, struct device_area *dev_area)
{ {
struct raw_list *rl; struct raw_list *rl;
struct list *rlh;
/* Already present? */ /* Already present? */
list_iterate(rlh, raw_list) { list_iterate_items(rl, raw_list) {
rl = list_item(rlh, struct raw_list);
/* FIXME Check size/overlap consistency too */ /* FIXME Check size/overlap consistency too */
if (rl->dev_area.dev == dev_area->dev && if (rl->dev_area.dev == dev_area->dev &&
rl->dev_area.start == dev_area->start) return 1; rl->dev_area.start == dev_area->start)
return 1;
} }
if (!(rl = dbg_malloc(sizeof(struct raw_list)))) { if (!(rl = dbg_malloc(sizeof(struct raw_list)))) {
@ -1180,7 +1178,6 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
struct lvmcache_info *info; struct lvmcache_info *info;
struct metadata_area *mda, *mda_new; struct metadata_area *mda, *mda_new;
struct mda_context *mdac, *mdac_new; struct mda_context *mdac, *mdac_new;
struct list *mdah, *dah;
struct data_area_list *da; struct data_area_list *da;
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) { if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
@ -1227,17 +1224,15 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
list_size(&info->das), dev_name(dev)); list_size(&info->das), dev_name(dev));
return 0; return 0;
} }
list_iterate(dah, &info->das) {
da = list_item(dah, struct data_area_list); list_iterate_items(da, &info->das)
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT; pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
}
if (!mdas) if (!mdas)
return 1; return 1;
/* Add copy of mdas to supplied list */ /* Add copy of mdas to supplied list */
list_iterate(mdah, &info->mdas) { list_iterate_items(mda, &info->mdas) {
mda = list_item(mdah, struct metadata_area);
mdac = (struct mda_context *) mda->metadata_locn; mdac = (struct mda_context *) mda->metadata_locn;
if (!(mda_new = pool_alloc(fmt->cmd->mem, sizeof(*mda_new)))) { if (!(mda_new = pool_alloc(fmt->cmd->mem, sizeof(*mda_new)))) {
log_error("metadata_area allocation failed"); log_error("metadata_area allocation failed");
@ -1327,7 +1322,7 @@ static int _pv_setup(const struct format_type *fmt,
{ {
struct metadata_area *mda, *mda_new, *mda2; struct metadata_area *mda, *mda_new, *mda2;
struct mda_context *mdac, *mdac_new, *mdac2; struct mda_context *mdac, *mdac_new, *mdac2;
struct list *pvmdas, *pvmdash, *mdash; struct list *pvmdas;
struct lvmcache_info *info; struct lvmcache_info *info;
int found; int found;
uint64_t pe_end = 0; uint64_t pe_end = 0;
@ -1342,8 +1337,7 @@ static int _pv_setup(const struct format_type *fmt,
/* Iterate through all mdas on this PV */ /* Iterate through all mdas on this PV */
if ((info = info_from_pvid(pv->dev->pvid))) { if ((info = info_from_pvid(pv->dev->pvid))) {
pvmdas = &info->mdas; pvmdas = &info->mdas;
list_iterate(pvmdash, pvmdas) { list_iterate_items(mda, pvmdas) {
mda = list_item(pvmdash, struct metadata_area);
mdac = mdac =
(struct mda_context *) mda->metadata_locn; (struct mda_context *) mda->metadata_locn;
@ -1351,10 +1345,7 @@ static int _pv_setup(const struct format_type *fmt,
/* Ensure it isn't already on list */ /* Ensure it isn't already on list */
found = 0; found = 0;
list_iterate(mdash, mdas) { list_iterate_items(mda2, mdas) {
mda2 =
list_item(mdash,
struct metadata_area);
if (mda2->ops != if (mda2->ops !=
&_metadata_text_raw_ops) continue; &_metadata_text_raw_ops) continue;
mdac2 = mdac2 =
@ -1416,9 +1407,10 @@ static struct format_instance *_create_text_instance(const struct format_type
struct mda_context *mdac, *mdac_new; struct mda_context *mdac, *mdac_new;
struct dir_list *dl; struct dir_list *dl;
struct raw_list *rl; struct raw_list *rl;
struct list *dlh, *dir_list, *rlh, *raw_list, *mdas, *mdash, *infoh; struct list *dir_list, *raw_list, *mdas;
char path[PATH_MAX]; char path[PATH_MAX];
struct lvmcache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) { if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
log_error("Couldn't allocate format instance object."); log_error("Couldn't allocate format instance object.");
@ -1440,8 +1432,7 @@ static struct format_instance *_create_text_instance(const struct format_type
} else { } else {
dir_list = &((struct mda_lists *) fmt->private)->dirs; dir_list = &((struct mda_lists *) fmt->private)->dirs;
list_iterate(dlh, dir_list) { list_iterate_items(dl, dir_list) {
dl = list_item(dlh, struct dir_list);
if (lvm_snprintf(path, PATH_MAX, "%s/%s", if (lvm_snprintf(path, PATH_MAX, "%s/%s",
dl->dir, vgname) < 0) { dl->dir, vgname) < 0) {
log_error("Name too long %s/%s", dl->dir, log_error("Name too long %s/%s", dl->dir,
@ -1461,9 +1452,7 @@ static struct format_instance *_create_text_instance(const struct format_type
raw_list = &((struct mda_lists *) fmt->private)->raws; raw_list = &((struct mda_lists *) fmt->private)->raws;
list_iterate(rlh, raw_list) { list_iterate_items(rl, raw_list) {
rl = list_item(rlh, struct raw_list);
/* FIXME Cache this; rescan below if some missing */ /* FIXME Cache this; rescan below if some missing */
if (!_raw_holds_vgname(fid, &rl->dev_area, vgname)) if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
continue; continue;
@ -1491,10 +1480,9 @@ static struct format_instance *_create_text_instance(const struct format_type
stack; stack;
goto out; goto out;
} }
list_iterate(infoh, &vginfo->infos) { list_iterate_items(info, &vginfo->infos) {
mdas = &(list_item(infoh, struct lvmcache_info)->mdas); mdas = &info->mdas;
list_iterate(mdash, mdas) { list_iterate_items(mda, mdas) {
mda = list_item(mdash, struct metadata_area);
mdac = mdac =
(struct mda_context *) mda->metadata_locn; (struct mda_context *) mda->metadata_locn;

View File

@ -223,12 +223,9 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg) static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg)
{ {
struct list *segh;
struct lv_segment *comp; struct lv_segment *comp;
list_iterate(segh, &lv->segments) { list_iterate_items(comp, &lv->segments) {
comp = list_item(segh, struct lv_segment);
if (comp->le > seg->le) { if (comp->le > seg->le) {
list_add(&comp->list, &seg->list); list_add(&comp->list, &seg->list);
return; return;
@ -291,8 +288,8 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
} }
if (!(seg = alloc_lv_segment(mem, segtype, lv, start_extent, if (!(seg = alloc_lv_segment(mem, segtype, lv, start_extent,
extent_count, 0, 0, area_count, extent_count, 0, 0, NULL, area_count,
extent_count, 0, 0))) { extent_count, 0, 0, 0))) {
log_error("Segment allocation failed"); log_error("Segment allocation failed");
return 0; return 0;
} }
@ -369,7 +366,6 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
/* /*
* Adjust extent counts in the pv and vg. * Adjust extent counts in the pv and vg.
*/ */
pv->pe_alloc_count += seg->area_len;
seg->lv->vg->free_count -= seg->area_len; seg->lv->vg->free_count -= seg->area_len;
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) { } else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i); set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i);
@ -436,7 +432,7 @@ static int _read_segments(struct pool *mem, struct volume_group *vg,
/* /*
* Check there are no gaps or overlaps in the lv. * Check there are no gaps or overlaps in the lv.
*/ */
if (!lv_check_segments(lv)) { if (!check_lv_segments(lv)) {
stack; stack;
return 0; return 0;
} }

View File

@ -81,5 +81,6 @@ struct mda_context {
#define FMTT_VERSION 1 #define FMTT_VERSION 1
#define MDA_HEADER_SIZE 512 #define MDA_HEADER_SIZE 512
#define LVM2_LABEL "LVM2 001" #define LVM2_LABEL "LVM2 001"
#define MDA_SIZE_MIN (8 * getpagesize())
#endif #endif

View File

@ -39,7 +39,6 @@ static int _write(struct label *label, char *buf)
struct pv_header *pvhdr; struct pv_header *pvhdr;
struct lvmcache_info *info; struct lvmcache_info *info;
struct disk_locn *pvh_dlocn_xl; struct disk_locn *pvh_dlocn_xl;
struct list *mdash, *dash;
struct metadata_area *mda; struct metadata_area *mda;
struct mda_context *mdac; struct mda_context *mdac;
struct data_area_list *da; struct data_area_list *da;
@ -57,9 +56,7 @@ static int _write(struct label *label, char *buf)
pvh_dlocn_xl = &pvhdr->disk_areas_xl[0]; pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
/* List of data areas (holding PEs) */ /* List of data areas (holding PEs) */
list_iterate(dash, &info->das) { list_iterate_items(da, &info->das) {
da = list_item(dash, struct data_area_list);
pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset); pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
pvh_dlocn_xl->size = xlate64(da->disk_locn.size); pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
pvh_dlocn_xl++; pvh_dlocn_xl++;
@ -71,8 +68,7 @@ static int _write(struct label *label, char *buf)
pvh_dlocn_xl++; pvh_dlocn_xl++;
/* List of metadata area header locations */ /* List of metadata area header locations */
list_iterate(mdash, &info->mdas) { list_iterate_items(mda, &info->mdas) {
mda = list_item(mdash, struct metadata_area);
mdac = (struct mda_context *) mda->metadata_locn; mdac = (struct mda_context *) mda->metadata_locn;
if (mdac->area.dev != info->dev) if (mdac->area.dev != info->dev)
@ -198,7 +194,6 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
struct lvmcache_info *info; struct lvmcache_info *info;
struct disk_locn *dlocn_xl; struct disk_locn *dlocn_xl;
uint64_t offset; uint64_t offset;
struct list *mdah;
struct metadata_area *mda; struct metadata_area *mda;
char vgnamebuf[NAME_LEN + 2]; char vgnamebuf[NAME_LEN + 2];
struct mda_context *mdac; struct mda_context *mdac;
@ -235,8 +230,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
dlocn_xl++; dlocn_xl++;
} }
list_iterate(mdah, &info->mdas) { list_iterate_items(mda, &info->mdas) {
mda = list_item(mdah, struct metadata_area);
mdac = (struct mda_context *) mda->metadata_locn; mdac = (struct mda_context *) mda->metadata_locn;
if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf, if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
sizeof(vgnamebuf))) { sizeof(vgnamebuf))) {

View File

@ -98,14 +98,11 @@ int label_register_handler(const char *name, struct labeller *handler)
struct labeller *label_get_handler(const char *name) struct labeller *label_get_handler(const char *name)
{ {
struct list *lih;
struct labeller_i *li; struct labeller_i *li;
list_iterate(lih, &_labellers) { list_iterate_items(li, &_labellers)
li = list_item(lih, struct labeller_i);
if (!strcmp(li->name, name)) if (!strcmp(li->name, name))
return li->l; return li->l;
}
return NULL; return NULL;
} }
@ -113,7 +110,6 @@ struct labeller *label_get_handler(const char *name)
static struct labeller *_find_labeller(struct device *dev, char *buf, static struct labeller *_find_labeller(struct device *dev, char *buf,
uint64_t *label_sector) uint64_t *label_sector)
{ {
struct list *lih;
struct labeller_i *li; struct labeller_i *li;
struct labeller *r = NULL; struct labeller *r = NULL;
struct label_header *lh; struct label_header *lh;
@ -166,8 +162,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
continue; continue;
} }
list_iterate(lih, &_labellers) { list_iterate_items(li, &_labellers) {
li = list_item(lih, struct labeller_i);
if (li->l->ops->can_handle(li->l, (char *) lh, sector)) { if (li->l->ops->can_handle(li->l, (char *) lh, sector)) {
log_very_verbose("%s: %s label detected", log_very_verbose("%s: %s label detected",
dev_name(dev), li->name); dev_name(dev), li->name);
@ -208,7 +203,6 @@ int label_remove(struct device *dev)
int r = 1; int r = 1;
uint64_t sector; uint64_t sector;
int wipe; int wipe;
struct list *lih;
struct labeller_i *li; struct labeller_i *li;
struct label_header *lh; struct label_header *lh;
@ -244,8 +238,7 @@ int label_remove(struct device *dev)
if (xlate64(lh->sector_xl) == sector) if (xlate64(lh->sector_xl) == sector)
wipe = 1; wipe = 1;
} else { } else {
list_iterate(lih, &_labellers) { list_iterate_items(li, &_labellers) {
li = list_item(lih, struct labeller_i);
if (li->l->ops->can_handle(li->l, (char *) lh, if (li->l->ops->can_handle(li->l, (char *) lh,
sector)) { sector)) {
wipe = 1; wipe = 1;

View File

@ -265,13 +265,10 @@ int lock_vol(struct cmd_context *cmd, const char *vol, int flags)
/* Unlock list of LVs */ /* Unlock list of LVs */
int resume_lvs(struct cmd_context *cmd, struct list *lvs) int resume_lvs(struct cmd_context *cmd, struct list *lvs)
{ {
struct list *lvh; struct lv_list *lvl;
struct logical_volume *lv;
list_iterate(lvh, lvs) { list_iterate_items(lvl, lvs)
lv = list_item(lvh, struct lv_list)->lv; resume_lv(cmd, lvl->lv->lvid.s);
resume_lv(cmd, lv->lvid.s);
}
return 1; return 1;
} }
@ -280,15 +277,14 @@ int resume_lvs(struct cmd_context *cmd, struct list *lvs)
int suspend_lvs(struct cmd_context *cmd, struct list *lvs) int suspend_lvs(struct cmd_context *cmd, struct list *lvs)
{ {
struct list *lvh; struct list *lvh;
struct logical_volume *lv; struct lv_list *lvl;
list_iterate(lvh, lvs) { list_iterate_items(lvl, lvs) {
lv = list_item(lvh, struct lv_list)->lv; if (!suspend_lv(cmd, lvl->lv->lvid.s)) {
if (!suspend_lv(cmd, lv->lvid.s)) { log_error("Failed to suspend %s", lvl->lv->name);
log_error("Failed to suspend %s", lv->name); list_uniterate(lvh, lvs, &lvl->list) {
list_uniterate(lvh, lvs, lvh) { lvl = list_item(lvh, struct lv_list);
lv = list_item(lvh, struct lv_list)->lv; resume_lv(cmd, lvl->lv->lvid.s);
resume_lv(cmd, lv->lvid.s);
} }
return 0; return 0;
@ -302,15 +298,14 @@ int suspend_lvs(struct cmd_context *cmd, struct list *lvs)
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs) int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs)
{ {
struct list *lvh; struct list *lvh;
struct logical_volume *lv; struct lv_list *lvl;
list_iterate(lvh, lvs) { list_iterate_items(lvl, lvs) {
lv = list_item(lvh, struct lv_list)->lv; if (!activate_lv_excl(cmd, lvl->lv->lvid.s)) {
if (!activate_lv_excl(cmd, lv->lvid.s)) { log_error("Failed to activate %s", lvl->lv->name);
log_error("Failed to activate %s", lv->name); list_uniterate(lvh, lvs, &lvl->list) {
list_uniterate(lvh, lvs, lvh) { lvl = list_item(lvh, struct lv_list);
lv = list_item(lvh, struct lv_list)->lv; activate_lv(cmd, lvl->lv->lvid.s);
activate_lv(cmd, lv->lvid.s);
} }
return 0; return 0;

View File

@ -41,4 +41,5 @@ int init_no_locking(struct locking_type *locking, struct config_tree *cf);
int init_file_locking(struct locking_type *locking, struct config_tree *cf); int init_file_locking(struct locking_type *locking, struct config_tree *cf);
int init_external_locking(struct locking_type *locking, struct config_tree *cf); int init_external_locking(struct locking_type *locking, struct config_tree *cf);
int init_cluster_locking(struct locking_type *locking, struct config_tree *cf); int init_cluster_locking(struct locking_type *locking, struct config_tree *cf);

View File

@ -22,17 +22,49 @@ struct lv_segment *alloc_lv_segment(struct pool *mem,
uint32_t le, uint32_t len, uint32_t le, uint32_t len,
uint32_t status, uint32_t status,
uint32_t stripe_size, uint32_t stripe_size,
struct logical_volume *log_lv,
uint32_t area_count, uint32_t area_count,
uint32_t area_len, uint32_t area_len,
uint32_t chunk_size, uint32_t chunk_size,
uint32_t region_size,
uint32_t extents_copied); uint32_t extents_copied);
struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv, struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
uint32_t allocated); uint32_t status, uint32_t old_le_count);
int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num, int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
struct physical_volume *pv, uint32_t pe); struct physical_volume *pv, uint32_t pe);
void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num, void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
struct logical_volume *lv, uint32_t le); struct logical_volume *lv, uint32_t le);
struct alloc_handle;
struct alloc_handle *allocate_extents(struct volume_group *vg,
struct logical_volume *lv,
struct segment_type *segtype,
uint32_t stripes,
uint32_t mirrors, uint32_t log_count,
uint32_t extents,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t status,
struct list *allocatable_pvs,
alloc_policy_t alloc);
int lv_add_segment(struct alloc_handle *ah,
uint32_t first_area, uint32_t num_areas,
struct logical_volume *lv,
struct segment_type *segtype,
uint32_t stripe_size,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t status,
uint32_t region_size,
struct logical_volume *log_lv);
int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv);
int lv_add_virtual_segment(struct logical_volume *lv, uint32_t status,
uint32_t extents, struct segment_type *segtype);
void alloc_destroy(struct alloc_handle *ah);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -58,11 +58,13 @@ int lv_merge_segments(struct logical_volume *lv)
/* /*
* Verify that an LV's segments are consecutive, complete and don't overlap. * Verify that an LV's segments are consecutive, complete and don't overlap.
*/ */
int lv_check_segments(struct logical_volume *lv) int check_lv_segments(struct logical_volume *lv)
{ {
struct lv_segment *seg; struct lv_segment *seg;
uint32_t le = 0; uint32_t le = 0;
unsigned seg_count = 0; unsigned seg_count = 0;
int r = 1;
uint32_t area_multiplier, s;
list_iterate_items(seg, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg_count++; seg_count++;
@ -70,13 +72,58 @@ int lv_check_segments(struct logical_volume *lv)
log_error("LV %s invalid: segment %u should begin at " log_error("LV %s invalid: segment %u should begin at "
"LE %" PRIu32 " (found %" PRIu32 ").", "LE %" PRIu32 " (found %" PRIu32 ").",
lv->name, seg_count, le, seg->le); lv->name, seg_count, le, seg->le);
return 0; r = 0;
}
area_multiplier = segtype_is_striped(seg->segtype) ?
seg->area_count : 1;
if (seg->area_len * area_multiplier != seg->len) {
log_error("LV %s: segment %u has inconsistent "
"area_len %u",
lv->name, seg_count, seg->area_len);
r = 0;
}
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_PV) {
if (!seg_pvseg(seg, s) ||
seg_pvseg(seg, s)->lvseg != seg ||
seg_pvseg(seg, s)->lv_area != s) {
log_error("LV %s: segment %u has "
"inconsistent PV area %u",
lv->name, seg_count, s);
r = 0;
}
} else {
if (!seg_lv(seg, s) ||
seg_lv(seg, s)->vg != lv->vg ||
seg_lv(seg, s) == lv) {
log_error("LV %s: segment %u has "
"inconsistent LV area %u",
lv->name, seg_count, s);
r = 0;
}
if (seg_le(seg, s) != le) {
log_error("LV %s: segment %u has "
"inconsistent LV area %u "
"size",
lv->name, seg_count, s);
r = 0;
}
}
} }
le += seg->len; le += seg->len;
} }
return 1; if (le != lv->le_count) {
log_error("LV %s: inconsistent LE count %u != %u",
lv->name, le, lv->le_count);
r = 0;
}
return r;
} }
/* /*
@ -101,8 +148,9 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem, seg->segtype, if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem, seg->segtype,
seg->lv, seg->le, seg->len, seg->lv, seg->le, seg->len,
seg->status, seg->stripe_size, seg->status, seg->stripe_size,
seg->log_lv,
seg->area_count, seg->area_len, seg->area_count, seg->area_len,
seg->chunk_size, seg->chunk_size, seg->region_size,
seg->extents_copied))) { seg->extents_copied))) {
log_error("Couldn't allocate cloned LV segment."); log_error("Couldn't allocate cloned LV segment.");
return 0; return 0;
@ -128,24 +176,24 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
/* Adjust the PV mapping */ /* Adjust the PV mapping */
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
split_seg->area[s].type = seg->area[s].type; seg_type(split_seg, s) = seg_type(seg, s);
/* Split area at the offset */ /* Split area at the offset */
switch (seg->area[s].type) { switch (seg_type(seg, s)) {
case AREA_LV: case AREA_LV:
split_seg->area[s].u.lv.lv = seg->area[s].u.lv.lv; seg_lv(split_seg, s) = seg_lv(seg, s);
split_seg->area[s].u.lv.le = seg_le(split_seg, s) =
seg->area[s].u.lv.le + seg->area_len; seg_le(seg, s) + seg->area_len;
log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name, log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name,
seg->le, s, le, seg->area[s].u.lv.lv->name, seg->le, s, le, seg_lv(seg, s)->name,
split_seg->area[s].u.lv.le); seg_le(split_seg, s));
break; break;
case AREA_PV: case AREA_PV:
if (!assign_peg_to_lvseg(seg->area[s].u.pv.pvseg->pv, if (!assign_peg_to_lvseg(seg_pv(seg, s),
seg->area[s].u.pv.pvseg->pe + seg_pe(seg, s) +
seg->area_len, seg->area_len,
seg->area[s].u.pv.pvseg->len - seg_pvseg(seg, s)->len -
seg->area_len, seg->area_len,
split_seg, s)) { split_seg, s)) {
stack; stack;
@ -153,13 +201,13 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
} }
log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name, log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
seg->le, s, le, seg->le, s, le,
dev_name(seg->area[s].u.pv.pvseg->pv->dev), dev_name(seg_dev(seg, s)),
split_seg->area[s].u.pv.pvseg->pe); seg_pe(split_seg, s));
break; break;
default: default:
log_error("Unrecognised segment type %u", log_error("Unrecognised segment type %u",
seg->area[s].type); seg_type(seg, s));
return 0; return 0;
} }
} }

View File

@ -139,7 +139,6 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
const char *id, struct physical_volume *pv) const char *id, struct physical_volume *pv)
{ {
struct volume_group *vg; struct volume_group *vg;
struct list *pvh;
struct pv_list *pvl; struct pv_list *pvl;
int consistent = 0; int consistent = 0;
@ -153,8 +152,7 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
log_error("Warning: Volume group %s is not consistent", log_error("Warning: Volume group %s is not consistent",
vg_name); vg_name);
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
if (id_equal(&pvl->pv->id, (const struct id *) id)) { if (id_equal(&pvl->pv->id, (const struct id *) id)) {
if (!_copy_pv(pv, pvl->pv)) { if (!_copy_pv(pv, pvl->pv)) {
stack; stack;
@ -171,19 +169,17 @@ int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
const char *new_name) const char *new_name)
{ {
struct pool *mem = cmd->mem; struct pool *mem = cmd->mem;
struct physical_volume *pv; struct pv_list *pvl;
struct list *pvh;
if (!(vg->name = pool_strdup(mem, new_name))) { if (!(vg->name = pool_strdup(mem, new_name))) {
log_error("vg->name allocation failed for '%s'", new_name); log_error("vg->name allocation failed for '%s'", new_name);
return 0; return 0;
} }
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv; if (!(pvl->pv->vg_name = pool_strdup(mem, new_name))) {
if (!(pv->vg_name = pool_strdup(mem, new_name))) {
log_error("pv->vg_name allocation failed for '%s'", log_error("pv->vg_name allocation failed for '%s'",
dev_name(pv->dev)); dev_name(pvl->pv->dev));
return 0; return 0;
} }
} }
@ -441,10 +437,10 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
/* foreach area */ /* foreach area */
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) { switch (seg_type(seg, s)) {
case AREA_PV: case AREA_PV:
if (!_recalc_extents if (!_recalc_extents
(&seg->area[s].u.pv.pvseg->pe, (&seg_pe(seg, s),
lv->name, lv->name,
" pvseg start", old_size, " pvseg start", old_size,
new_size)) { new_size)) {
@ -452,7 +448,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
return 0; return 0;
} }
if (!_recalc_extents if (!_recalc_extents
(&seg->area[s].u.pv.pvseg->len, (&seg_pvseg(seg, s)->len,
lv->name, lv->name,
" pvseg length", old_size, " pvseg length", old_size,
new_size)) { new_size)) {
@ -462,7 +458,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
break; break;
case AREA_LV: case AREA_LV:
if (!_recalc_extents if (!_recalc_extents
(&seg->area[s].u.lv.le, lv->name, (&seg_le(seg, s), lv->name,
" area start", old_size, " area start", old_size,
new_size)) { new_size)) {
stack; stack;
@ -471,7 +467,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
break; break;
default: default:
log_error("Unrecognised segment type " log_error("Unrecognised segment type "
"%u", seg->area[s].type); "%u", seg_type(seg, s));
return 0; return 0;
} }
} }
@ -563,26 +559,22 @@ struct physical_volume *pv_create(const struct format_type *fmt,
struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name) struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
{ {
struct list *pvh;
struct pv_list *pvl; struct pv_list *pvl;
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs)
pvl = list_item(pvh, struct pv_list);
if (pvl->pv->dev == dev_cache_get(pv_name, vg->cmd->filter)) if (pvl->pv->dev == dev_cache_get(pv_name, vg->cmd->filter))
return pvl; return pvl;
}
return NULL; return NULL;
} }
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv) int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
{ {
struct list *pvh; struct pv_list *pvl;
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs)
if (pv == list_item(pvh, struct pv_list)->pv) if (pv == pvl->pv)
return 1; return 1;
}
return 0; return 0;
} }
@ -590,21 +582,17 @@ int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg, struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id) struct id *id)
{ {
struct list *pvh;
struct pv_list *pvl; struct pv_list *pvl;
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs)
pvl = list_item(pvh, struct pv_list);
if (id_equal(&pvl->pv->id, id)) if (id_equal(&pvl->pv->id, id))
return pvl->pv; return pvl->pv;
}
return NULL; return NULL;
} }
struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name) struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
{ {
struct list *lvh;
struct lv_list *lvl; struct lv_list *lvl;
const char *ptr; const char *ptr;
@ -614,11 +602,9 @@ struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
else else
ptr = lv_name; ptr = lv_name;
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl, &vg->lvs)
lvl = list_item(lvh, struct lv_list);
if (!strcmp(lvl->lv->name, ptr)) if (!strcmp(lvl->lv->name, ptr))
return lvl; return lvl;
}
return NULL; return NULL;
} }
@ -643,15 +629,12 @@ struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name)
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev) struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
{ {
struct list *pvh; struct pv_list *pvl;
struct physical_volume *pv;
list_iterate(pvh, &vg->pvs) { list_iterate_items(pvl, &vg->pvs)
pv = list_item(pvh, struct pv_list)->pv; if (dev == pvl->pv->dev)
return pvl->pv;
if (dev == pv->dev)
return pv;
}
return NULL; return NULL;
} }
@ -676,14 +659,11 @@ struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
/* Find segment at a given logical extent in an LV */ /* 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 lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
{ {
struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments)
seg = list_item(segh, struct lv_segment);
if (le >= seg->le && le < seg->le + seg->len) if (le >= seg->le && le < seg->le + seg->len)
return seg; return seg;
}
return NULL; return NULL;
} }
@ -693,23 +673,20 @@ struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe)
{ {
struct pv_segment *peg; struct pv_segment *peg;
list_iterate_items(peg, &pv->segments) { list_iterate_items(peg, &pv->segments)
if (pe >= peg->pe && pe < peg->pe + peg->len) if (pe >= peg->pe && pe < peg->pe + peg->len)
return peg; return peg;
}
return NULL; return NULL;
} }
int vg_remove(struct volume_group *vg) int vg_remove(struct volume_group *vg)
{ {
struct list *mdah;
struct metadata_area *mda; struct metadata_area *mda;
/* FIXME Improve recovery situation? */ /* FIXME Improve recovery situation? */
/* Remove each copy of the metadata */ /* Remove each copy of the metadata */
list_iterate(mdah, &vg->fid->metadata_areas) { list_iterate_items(mda, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
if (mda->ops->vg_remove && if (mda->ops->vg_remove &&
!mda->ops->vg_remove(vg->fid, vg, mda)) { !mda->ops->vg_remove(vg->fid, vg, mda)) {
stack; stack;
@ -726,8 +703,9 @@ int vg_remove(struct volume_group *vg)
*/ */
int vg_write(struct volume_group *vg) int vg_write(struct volume_group *vg)
{ {
struct list *mdah, *mdah2; struct list *mdah;
struct metadata_area *mda; struct metadata_area *mda;
struct lv_list *lvl;
if (!check_pv_segments(vg)) { if (!check_pv_segments(vg)) {
log_error("Internal error: PV segments corrupted in %s.", log_error("Internal error: PV segments corrupted in %s.",
@ -735,6 +713,14 @@ int vg_write(struct volume_group *vg)
return 0; return 0;
} }
list_iterate_items(lvl, &vg->lvs) {
if (!check_lv_segments(lvl->lv)) {
log_error("Internal error: LV segments corrupted in %s.",
lvl->lv->name);
return 0;
}
}
if (vg->status & PARTIAL_VG) { if (vg->status & PARTIAL_VG) {
log_error("Cannot change metadata for partial volume group %s", log_error("Cannot change metadata for partial volume group %s",
vg->name); vg->name);
@ -749,14 +735,13 @@ int vg_write(struct volume_group *vg)
vg->seqno++; vg->seqno++;
/* Write to each copy of the metadata area */ /* Write to each copy of the metadata area */
list_iterate(mdah, &vg->fid->metadata_areas) { list_iterate_items(mda, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
if (!mda->ops->vg_write) { if (!mda->ops->vg_write) {
log_error("Format does not support writing volume" log_error("Format does not support writing volume"
"group metadata areas"); "group metadata areas");
/* Revert */ /* Revert */
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) { list_uniterate(mdah, &vg->fid->metadata_areas, &mda->list) {
mda = list_item(mdah2, struct metadata_area); mda = list_item(mdah, struct metadata_area);
if (mda->ops->vg_revert && if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) { !mda->ops->vg_revert(vg->fid, vg, mda)) {
@ -768,8 +753,9 @@ int vg_write(struct volume_group *vg)
if (!mda->ops->vg_write(vg->fid, vg, mda)) { if (!mda->ops->vg_write(vg->fid, vg, mda)) {
stack; stack;
/* Revert */ /* Revert */
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) { list_uniterate(mdah, &vg->fid->metadata_areas, &mda->list) {
mda = list_item(mdah2, struct metadata_area); mda = list_item(mdah, struct metadata_area);
if (mda->ops->vg_revert && if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) { !mda->ops->vg_revert(vg->fid, vg, mda)) {
stack; stack;
@ -780,14 +766,12 @@ int vg_write(struct volume_group *vg)
} }
/* Now pre-commit each copy of the new metadata */ /* Now pre-commit each copy of the new metadata */
list_iterate(mdah, &vg->fid->metadata_areas) { list_iterate_items(mda, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
if (mda->ops->vg_precommit && if (mda->ops->vg_precommit &&
!mda->ops->vg_precommit(vg->fid, vg, mda)) { !mda->ops->vg_precommit(vg->fid, vg, mda)) {
stack; stack;
/* Revert */ /* Revert */
list_iterate(mdah2, &vg->fid->metadata_areas) { list_iterate_items(mda, &vg->fid->metadata_areas) {
mda = list_item(mdah2, struct metadata_area);
if (mda->ops->vg_revert && if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) { !mda->ops->vg_revert(vg->fid, vg, mda)) {
stack; stack;
@ -803,14 +787,12 @@ int vg_write(struct volume_group *vg)
/* Commit pending changes */ /* Commit pending changes */
int vg_commit(struct volume_group *vg) int vg_commit(struct volume_group *vg)
{ {
struct list *mdah;
struct metadata_area *mda; struct metadata_area *mda;
int cache_updated = 0; int cache_updated = 0;
int failed = 0; int failed = 0;
/* Commit to each copy of the metadata area */ /* Commit to each copy of the metadata area */
list_iterate(mdah, &vg->fid->metadata_areas) { list_iterate_items(mda, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
failed = 0; failed = 0;
if (mda->ops->vg_commit && if (mda->ops->vg_commit &&
!mda->ops->vg_commit(vg->fid, vg, mda)) { !mda->ops->vg_commit(vg->fid, vg, mda)) {
@ -822,7 +804,6 @@ int vg_commit(struct volume_group *vg)
lvmcache_update_vg(vg); lvmcache_update_vg(vg);
cache_updated = 1; cache_updated = 1;
} }
} }
/* If at least one mda commit succeeded, it was committed */ /* If at least one mda commit succeeded, it was committed */
@ -832,11 +813,9 @@ int vg_commit(struct volume_group *vg)
/* Don't commit any pending changes */ /* Don't commit any pending changes */
int vg_revert(struct volume_group *vg) int vg_revert(struct volume_group *vg)
{ {
struct list *mdah;
struct metadata_area *mda; struct metadata_area *mda;
list_iterate(mdah, &vg->fid->metadata_areas) { list_iterate_items(mda, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
if (mda->ops->vg_revert && if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) { !mda->ops->vg_revert(vg->fid, vg, mda)) {
stack; stack;
@ -850,8 +829,7 @@ int vg_revert(struct volume_group *vg)
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd) static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
{ {
struct lvmcache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
struct list *ih; struct lvmcache_info *info;
struct device *dev;
struct pv_list *pvl; struct pv_list *pvl;
struct volume_group *vg; struct volume_group *vg;
struct physical_volume *pv; struct physical_volume *pv;
@ -874,9 +852,8 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
return NULL; return NULL;
} }
list_iterate(ih, &vginfo->infos) { list_iterate_items(info, &vginfo->infos) {
dev = list_item(ih, struct lvmcache_info)->dev; if (!(pv = pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL, 1))) {
continue; continue;
} }
if (!(pvl = pool_zalloc(cmd->mem, sizeof(*pvl)))) { if (!(pvl = pool_zalloc(cmd->mem, sizeof(*pvl)))) {
@ -905,7 +882,6 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
struct format_instance *fid; struct format_instance *fid;
const struct format_type *fmt; const struct format_type *fmt;
struct volume_group *vg, *correct_vg = NULL; struct volume_group *vg, *correct_vg = NULL;
struct list *mdah;
struct metadata_area *mda; struct metadata_area *mda;
int inconsistent = 0; int inconsistent = 0;
@ -949,8 +925,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
} }
/* Ensure contents of all metadata areas match - else do recovery */ /* Ensure contents of all metadata areas match - else do recovery */
list_iterate(mdah, &fid->metadata_areas) { list_iterate_items(mda, &fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
if ((precommitted && if ((precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) || !(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
(!precommitted && (!precommitted &&
@ -993,8 +968,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
} }
/* Ensure contents of all metadata areas match - else recover */ /* Ensure contents of all metadata areas match - else recover */
list_iterate(mdah, &fid->metadata_areas) { list_iterate_items(mda, &fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
if ((precommitted && if ((precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname, !(vg = mda->ops->vg_read_precommit(fid, vgname,
mda))) || mda))) ||
@ -1088,9 +1062,10 @@ struct volume_group *vg_read_precommitted(struct cmd_context *cmd,
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid) struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
{ {
const char *vgname; const char *vgname;
struct list *vgnames, *slh; struct list *vgnames;
struct volume_group *vg; struct volume_group *vg;
struct lvmcache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
struct str_list *strl;
int consistent = 0; int consistent = 0;
/* Is corresponding vgname already cached? */ /* Is corresponding vgname already cached? */
@ -1121,8 +1096,8 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
return NULL; return NULL;
} }
list_iterate(slh, vgnames) { list_iterate_items(strl, vgnames) {
vgname = list_item(slh, struct str_list)->str; vgname = strl->str;
if (!vgname || !*vgname) if (!vgname || !*vgname)
continue; // FIXME Unnecessary? continue; // FIXME Unnecessary?
consistent = 0; consistent = 0;
@ -1228,10 +1203,11 @@ struct list *get_vgs(struct cmd_context *cmd, int full_scan)
struct list *get_pvs(struct cmd_context *cmd) struct list *get_pvs(struct cmd_context *cmd)
{ {
struct str_list *strl;
struct list *results; struct list *results;
const char *vgname; const char *vgname;
struct list *pvh, *tmp; struct list *pvh, *tmp;
struct list *vgnames, *slh; struct list *vgnames;
struct volume_group *vg; struct volume_group *vg;
int consistent = 0; int consistent = 0;
int old_partial; int old_partial;
@ -1258,8 +1234,8 @@ struct list *get_pvs(struct cmd_context *cmd)
old_pvmove = pvmove_mode(); old_pvmove = pvmove_mode();
init_partial(1); init_partial(1);
init_pvmove(1); init_pvmove(1);
list_iterate(slh, vgnames) { list_iterate_items(strl, vgnames) {
vgname = list_item(slh, struct str_list)->str; vgname = strl->str;
if (!vgname) if (!vgname)
continue; /* FIXME Unnecessary? */ continue; /* FIXME Unnecessary? */
consistent = 0; consistent = 0;

View File

@ -55,6 +55,7 @@
#define LOCKED 0x00004000 /* LV */ #define LOCKED 0x00004000 /* LV */
#define MIRRORED 0x00008000 /* LV - internal use only */ #define MIRRORED 0x00008000 /* LV - internal use only */
#define VIRTUAL 0x00010000 /* LV - internal use only */ #define VIRTUAL 0x00010000 /* LV - internal use only */
#define MIRROR_LOG 0x00020000 /* LV */
#define LVM_READ 0x00000100 /* LV VG */ #define LVM_READ 0x00000100 /* LV VG */
#define LVM_WRITE 0x00000200 /* LV VG */ #define LVM_WRITE 0x00000200 /* LV VG */
@ -228,8 +229,10 @@ struct lv_segment {
struct logical_volume *origin; struct logical_volume *origin;
struct logical_volume *cow; struct logical_volume *cow;
struct list origin_list; struct list origin_list;
uint32_t chunk_size; /* In sectors */ uint32_t chunk_size; /* For snapshots - in sectors */
uint32_t region_size; /* For mirrors - in sectors */
uint32_t extents_copied; uint32_t extents_copied;
struct logical_volume *log_lv;
struct list tags; struct list tags;
@ -248,6 +251,14 @@ struct lv_segment {
} area[0]; } area[0];
}; };
#define seg_type(seg, s) (seg)->area[(s)].type
#define seg_pvseg(seg, s) (seg)->area[(s)].u.pv.pvseg
#define seg_pv(seg, s) (seg)->area[(s)].u.pv.pvseg->pv
#define seg_dev(seg, s) (seg)->area[(s)].u.pv.pvseg->pv->dev
#define seg_pe(seg, s) (seg)->area[(s)].u.pv.pvseg->pe
#define seg_lv(seg, s) (seg)->area[(s)].u.lv.lv
#define seg_le(seg, s) (seg)->area[(s)].u.lv.le
struct logical_volume { struct logical_volume {
union lvid lvid; union lvid lvid;
char *name; char *name;
@ -492,7 +503,7 @@ const char *strip_dir(const char *vg_name, const char *dir);
/* /*
* Checks that an lv has no gaps or overlapping segments. * Checks that an lv has no gaps or overlapping segments.
*/ */
int lv_check_segments(struct logical_volume *lv); int check_lv_segments(struct logical_volume *lv);
/* /*
* Sometimes (eg, after an lvextend), it is possible to merge two * Sometimes (eg, after an lvextend), it is possible to merge two

View File

@ -33,7 +33,6 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
alloc_policy_t alloc, alloc_policy_t alloc,
struct list *lvs_changed) struct list *lvs_changed)
{ {
struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
struct lv_list *lvl; struct lv_list *lvl;
struct pv_list *pvl; struct pv_list *pvl;
@ -59,16 +58,15 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
} }
/* Split LV segments to match PE ranges */ /* Split LV segments to match PE ranges */
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV || if (seg_type(seg, s) != AREA_PV ||
seg->area[s].u.pv.pvseg->pv->dev != pvl->pv->dev) seg_dev(seg, s) != pvl->pv->dev)
continue; continue;
/* Do these PEs need moving? */ /* Do these PEs need moving? */
list_iterate_items(per, pvl->pe_ranges) { list_iterate_items(per, pvl->pe_ranges) {
pe_start = seg->area[s].u.pv.pvseg->pe; pe_start = seg_pe(seg, s);
pe_end = pe_start + seg->area_len - 1; pe_end = pe_start + seg->area_len - 1;
per_end = per->start + per->count - 1; per_end = per->start + per->count - 1;
@ -104,14 +102,13 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
} }
/* Work through all segments on the supplied PV */ /* Work through all segments on the supplied PV */
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV || if (seg_type(seg, s) != AREA_PV ||
seg->area[s].u.pv.pvseg->pv->dev != pvl->pv->dev) seg_dev(seg, s) != pvl->pv->dev)
continue; continue;
pe_start = seg->area[s].u.pv.pvseg->pe; pe_start = seg_pe(seg, s);
/* Do these PEs need moving? */ /* Do these PEs need moving? */
list_iterate_items(per, pvl->pe_ranges) { list_iterate_items(per, pvl->pe_ranges) {
@ -123,9 +120,8 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
log_debug("Matched PE range %u-%u against " log_debug("Matched PE range %u-%u against "
"%s %u len %u", per->start, per_end, "%s %u len %u", per->start, per_end,
dev_name(seg->area[s].u.pv.pvseg-> dev_name(seg_dev(seg, s)),
pv->dev), seg_pe(seg, s),
seg->area[s].u.pv.pvseg->pe,
seg->area_len); seg->area_len);
/* First time, add LV to list of LVs affected */ /* First time, add LV to list of LVs affected */
@ -141,16 +137,16 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
log_very_verbose("Moving %s:%u-%u of %s/%s", log_very_verbose("Moving %s:%u-%u of %s/%s",
dev_name(pvl->pv->dev), dev_name(pvl->pv->dev),
seg->area[s].u.pv.pvseg->pe, seg_pe(seg, s),
seg->area[s].u.pv.pvseg->pe + seg_pe(seg, s) +
seg->area_len - 1, seg->area_len - 1,
lv->vg->name, lv->name); lv->vg->name, lv->name);
start_le = lv_mirr->le_count; start_le = lv_mirr->le_count;
if (!lv_extend(lv_mirr, segtype, 1, if (!lv_extend(lv_mirr, segtype, 1,
seg->area_len, 0u, seg->area_len, seg->area_len, 0u, seg->area_len,
seg->area[s].u.pv.pvseg->pv, seg_pv(seg, s),
seg->area[s].u.pv.pvseg->pe, seg_pe(seg, s),
PVMOVE, allocatable_pvs, PVMOVE, allocatable_pvs,
alloc)) { alloc)) {
log_error("Unable to allocate " log_error("Unable to allocate "
@ -178,29 +174,27 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
int remove_pvmove_mirrors(struct volume_group *vg, int remove_pvmove_mirrors(struct volume_group *vg,
struct logical_volume *lv_mirr) struct logical_volume *lv_mirr)
{ {
struct list *lvh, *segh; struct lv_list *lvl;
struct logical_volume *lv1; struct logical_volume *lv1;
struct lv_segment *seg, *mir_seg; struct lv_segment *seg, *mir_seg;
uint32_t s, c; uint32_t s, c;
/* Loop through all LVs except the temporary mirror */ /* Loop through all LVs except the temporary mirror */
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl, &vg->lvs) {
lv1 = list_item(lvh, struct lv_list)->lv; lv1 = lvl->lv;
if (lv1 == lv_mirr) if (lv1 == lv_mirr)
continue; continue;
/* Find all segments that point at the temporary mirror */ /* Find all segments that point at the temporary mirror */
list_iterate(segh, &lv1->segments) { list_iterate_items(seg, &lv1->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV || if (seg_type(seg, s) != AREA_LV ||
seg->area[s].u.lv.lv != lv_mirr) seg_lv(seg, s) != lv_mirr)
continue; continue;
/* Find the mirror segment pointed at */ /* Find the mirror segment pointed at */
if (!(mir_seg = find_seg_by_le(lv_mirr, if (!(mir_seg = find_seg_by_le(lv_mirr,
seg->area[s]. seg_le(seg, s)))) {
u.lv.le))) {
/* FIXME Error message */ /* FIXME Error message */
log_error("No segment found with LE"); log_error("No segment found with LE");
return 0; return 0;
@ -210,7 +204,7 @@ int remove_pvmove_mirrors(struct volume_group *vg,
/* FIXME Improve error mesg & remove restrcn */ /* FIXME Improve error mesg & remove restrcn */
if (!seg_is_mirrored(mir_seg) || if (!seg_is_mirrored(mir_seg) ||
!(mir_seg->status & PVMOVE) || !(mir_seg->status & PVMOVE) ||
mir_seg->le != seg->area[s].u.lv.le || mir_seg->le != seg_le(seg, s) ||
mir_seg->area_count != 2 || mir_seg->area_count != 2 ||
mir_seg->area_len != seg->area_len) { mir_seg->area_len != seg->area_len) {
log_error("Incompatible segments"); log_error("Incompatible segments");
@ -227,8 +221,8 @@ int remove_pvmove_mirrors(struct volume_group *vg,
c = 0; c = 0;
if (!set_lv_segment_area_pv(seg, s, if (!set_lv_segment_area_pv(seg, s,
mir_seg->area[c].u.pv.pvseg->pv, seg_pv(mir_seg, c),
mir_seg->area[c].u.pv.pvseg->pe)) { seg_pe(mir_seg, c))) {
stack; stack;
return 0; return 0;
} }
@ -258,16 +252,14 @@ int remove_pvmove_mirrors(struct volume_group *vg,
const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr) const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr)
{ {
struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
list_iterate(segh, &lv_mirr->segments) { list_iterate_items(seg, &lv_mirr->segments) {
seg = list_item(segh, struct lv_segment);
if (!seg_is_mirrored(seg)) if (!seg_is_mirrored(seg))
continue; continue;
if (seg->area[0].type != AREA_PV) if (seg->area[0].type != AREA_PV)
continue; continue;
return dev_name(seg->area[0].u.pv.pvseg->pv->dev); return dev_name(seg_dev(seg, 0));
} }
return NULL; return NULL;
@ -275,16 +267,14 @@ const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr)
const char *get_pvmove_pvname_from_lv(struct logical_volume *lv) const char *get_pvmove_pvname_from_lv(struct logical_volume *lv)
{ {
struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
uint32_t s; uint32_t s;
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV) if (seg_type(seg, s) != AREA_LV)
continue; continue;
return get_pvmove_pvname_from_lv_mirr(seg->area[s].u.lv.lv); return get_pvmove_pvname_from_lv_mirr(seg_lv(seg, s));
} }
} }
@ -295,23 +285,22 @@ struct logical_volume *find_pvmove_lv(struct volume_group *vg,
struct device *dev, struct device *dev,
uint32_t lv_type) uint32_t lv_type)
{ {
struct list *lvh, *segh; struct lv_list *lvl;
struct logical_volume *lv; struct logical_volume *lv;
struct lv_segment *seg; struct lv_segment *seg;
/* Loop through all LVs */ /* Loop through all LVs */
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv; lv = lvl->lv;
if (!(lv->status & lv_type)) if (!(lv->status & lv_type))
continue; continue;
/* Check segment origins point to pvname */ /* Check segment origins point to pvname */
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (seg->area[0].type != AREA_PV) if (seg->area[0].type != AREA_PV)
continue; continue;
if (seg->area[0].u.pv.pvseg->pv->dev != dev) if (seg_dev(seg, 0) != dev)
continue; continue;
return lv; return lv;
} }
@ -338,9 +327,9 @@ struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg, struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv) struct logical_volume *lv)
{ {
struct list *lvh, *segh, *lvs; struct list *lvs;
struct logical_volume *lv1; struct logical_volume *lv1;
struct lv_list *lvl; struct lv_list *lvl, *lvl1;
struct lv_segment *seg; struct lv_segment *seg;
uint32_t s; uint32_t s;
@ -352,17 +341,16 @@ struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
list_init(lvs); list_init(lvs);
/* Loop through all LVs except the one supplied */ /* Loop through all LVs except the one supplied */
list_iterate(lvh, &vg->lvs) { list_iterate_items(lvl1, &vg->lvs) {
lv1 = list_item(lvh, struct lv_list)->lv; lv1 = lvl1->lv;
if (lv1 == lv) if (lv1 == lv)
continue; continue;
/* Find whether any segment points at the supplied LV */ /* Find whether any segment points at the supplied LV */
list_iterate(segh, &lv1->segments) { list_iterate_items(seg, &lv1->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV || if (seg_type(seg, s) != AREA_LV ||
seg->area[s].u.lv.lv != lv) seg_lv(seg, s) != lv)
continue; continue;
if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) { if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
log_error("lv_list alloc failed"); log_error("lv_list alloc failed");
@ -383,12 +371,9 @@ struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
float copy_percent(struct logical_volume *lv_mirr) float copy_percent(struct logical_volume *lv_mirr)
{ {
uint32_t numerator = 0u, denominator = 0u; uint32_t numerator = 0u, denominator = 0u;
struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
list_iterate(segh, &lv_mirr->segments) { list_iterate_items(seg, &lv_mirr->segments) {
seg = list_item(segh, struct lv_segment);
denominator += seg->area_len; denominator += seg->area_len;
if (seg_is_mirrored(seg)) if (seg_is_mirrored(seg))

View File

@ -22,7 +22,7 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv, uint32_t pe,
struct lv_segment *seg, struct lv_segment *seg,
uint32_t area_num); uint32_t area_num);
int pv_split_segment(struct physical_volume *pv, uint32_t pe); int pv_split_segment(struct physical_volume *pv, uint32_t pe);
int release_pv_segment(struct pv_segment *peg, uint32_t new_area_len); int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction);
int check_pv_segments(struct volume_group *vg); int check_pv_segments(struct volume_group *vg);
void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2); void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2);

View File

@ -165,9 +165,11 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv,
return peg; return peg;
} }
int release_pv_segment(struct pv_segment *peg, uint32_t new_area_len) int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
{ {
if (new_area_len == 0) { peg->pv->pe_alloc_count -= area_reduction;
if (!peg->lvseg->area_len) {
peg->lvseg = NULL; peg->lvseg = NULL;
peg->lv_area = 0; peg->lv_area = 0;
@ -176,7 +178,7 @@ int release_pv_segment(struct pv_segment *peg, uint32_t new_area_len)
return 1; return 1;
} }
if (!pv_split_segment(peg->pv, peg->pe + new_area_len)) { if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len)) {
stack; stack;
return 0; return 0;
} }
@ -203,13 +205,16 @@ int check_pv_segments(struct volume_group *vg)
struct pv_list *pvl; struct pv_list *pvl;
struct pv_segment *peg; struct pv_segment *peg;
unsigned s, segno; unsigned s, segno;
uint32_t start_pe; uint32_t start_pe, alloced;
uint32_t pv_count = 0, free_count = 0, extent_count = 0;
int ret = 1; int ret = 1;
list_iterate_items(pvl, &vg->pvs) { list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv; pv = pvl->pv;
segno = 0; segno = 0;
start_pe = 0; start_pe = 0;
alloced = 0;
pv_count++;
list_iterate_items(peg, &pv->segments) { list_iterate_items(peg, &pv->segments) {
s = peg->lv_area; s = peg->lv_area;
@ -221,30 +226,63 @@ int check_pv_segments(struct volume_group *vg)
peg->lvseg ? peg->lvseg->le : 0, s); peg->lvseg ? peg->lvseg->le : 0, s);
/* FIXME Add details here on failure instead */ /* FIXME Add details here on failure instead */
if (start_pe != peg->pe) { if (start_pe != peg->pe) {
log_debug("Gap in pvsegs: %u, %u", log_error("Gap in pvsegs: %u, %u",
start_pe, peg->pe); start_pe, peg->pe);
ret = 0; ret = 0;
} }
if (peg->lvseg) { if (peg->lvseg) {
if (peg->lvseg->area[s].type != AREA_PV) { if (seg_type(peg->lvseg, s) != AREA_PV) {
log_debug("Wrong lvseg area type"); log_error("Wrong lvseg area type");
ret = 0; ret = 0;
} }
if (peg->lvseg->area[s].u.pv.pvseg != peg) { if (seg_pvseg(peg->lvseg, s) != peg) {
log_debug("Inconsistent pvseg pointers"); log_error("Inconsistent pvseg pointers");
ret = 0; ret = 0;
} }
if (peg->lvseg->area_len != peg->len) { if (peg->lvseg->area_len != peg->len) {
log_debug("Inconsistent length: %u %u", log_error("Inconsistent length: %u %u",
peg->len, peg->len,
peg->lvseg->area_len); peg->lvseg->area_len);
ret = 0; ret = 0;
} }
alloced += peg->len;
} }
start_pe += peg->len; start_pe += peg->len;
} }
if (start_pe != pv->pe_count) {
log_error("PV segment pe_count mismatch: %u != %u",
start_pe, pv->pe_count);
ret = 0;
}
if (alloced != pv->pe_alloc_count) {
log_error("PV segment pe_alloc_count mismatch: "
"%u != %u", alloced, pv->pe_alloc_count);
ret = 0;
}
extent_count += start_pe;
free_count += (start_pe - alloced);
}
if (pv_count != vg->pv_count) {
log_error("PV segment VG pv_count mismatch: %u != %u",
pv_count, vg->pv_count);
ret = 0;
}
if (free_count != vg->free_count) {
log_error("PV segment VG free_count mismatch: %u != %u",
free_count, vg->free_count);
ret = 0;
}
if (extent_count != vg->extent_count) {
log_error("PV segment VG extent_count mismatch: %u != %u",
extent_count, vg->extent_count);
ret = 0;
} }
return ret; return ret;
} }

View File

@ -39,6 +39,10 @@ struct dev_manager;
#define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0) #define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
#define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0) #define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0)
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
#define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
#define segtype_is_virtual(segtype) ((segtype)->flags & SEG_VIRTUAL ? 1 : 0)
struct segment_type { struct segment_type {
struct list list; struct list list;
struct cmd_context *cmd; struct cmd_context *cmd;

View File

@ -59,7 +59,7 @@ int vg_add_snapshot(struct format_instance *fid, const char *name,
snap->le_count = extent_count; snap->le_count = extent_count;
if (!(seg = alloc_snapshot_seg(snap, 0))) { if (!(seg = alloc_snapshot_seg(snap, 0, 0))) {
stack; stack;
return 0; return 0;
} }

View File

@ -35,7 +35,7 @@ enum {
}; };
struct mirror_state { struct mirror_state {
uint32_t region_size; uint32_t default_region_size;
}; };
static const char *_name(const struct lv_segment *seg) static const char *_name(const struct lv_segment *seg)
@ -45,14 +45,25 @@ static const char *_name(const struct lv_segment *seg)
static void _display(const struct lv_segment *seg) static void _display(const struct lv_segment *seg)
{ {
const char *size;
log_print(" Mirrors\t\t%u", seg->area_count); log_print(" Mirrors\t\t%u", seg->area_count);
log_print(" Mirror size\t\t%u", seg->area_len); log_print(" Mirror size\t\t%u", seg->area_len);
if (seg->log_lv)
log_print(" Mirror log volume\t%s", seg->log_lv->name);
if (seg->region_size) {
size = display_size(seg->lv->vg->cmd,
(uint64_t) seg->region_size,
SIZE_SHORT);
log_print(" Mirror region size\t%s", size);
}
log_print(" Mirror original:"); log_print(" Mirror original:");
display_stripe(seg, 0, " "); display_stripe(seg, 0, " ");
log_print(" Mirror destination:"); log_print(" Mirror destination:");
display_stripe(seg, 1, " "); display_stripe(seg, 1, " ");
log_print(" "); log_print(" ");
} }
static int _text_import_area_count(struct config_node *sn, uint32_t *area_count) static int _text_import_area_count(struct config_node *sn, uint32_t *area_count)
@ -70,6 +81,7 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
struct hash_table *pv_hash) struct hash_table *pv_hash)
{ {
const struct config_node *cn; const struct config_node *cn;
char *logname = NULL;
if (find_config_node(sn, "extents_moved")) { if (find_config_node(sn, "extents_moved")) {
if (get_config_uint32(sn, "extents_moved", if (get_config_uint32(sn, "extents_moved",
@ -82,6 +94,35 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
} }
} }
if (find_config_node(sn, "region_size")) {
if (!get_config_uint32(sn, "region_size",
&seg->region_size)) {
log_error("Couldn't read 'region_size' for "
"segment '%s'.", sn->key);
return 0;
}
}
if ((cn = find_config_node(sn, "mirror_log"))) {
if (!cn->v || !cn->v->v.str) {
log_error("Mirror log type must be a string.");
return 0;
}
logname = cn->v->v.str;
if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) {
log_error("Unrecognised mirror log in segment %s.",
sn->key);
return 0;
}
seg->log_lv->status |= MIRROR_LOG;
}
if (logname && !seg->region_size) {
log_error("Missing region size for mirror log for segment "
"'%s'.", sn->key);
return 0;
}
if (!(cn = find_config_node(sn, "mirrors"))) { if (!(cn = find_config_node(sn, "mirrors"))) {
log_error("Couldn't find mirrors array for segment " log_error("Couldn't find mirrors array for segment "
"'%s'.", sn->key); "'%s'.", sn->key);
@ -96,7 +137,11 @@ static int _text_export(const struct lv_segment *seg, struct formatter *f)
outf(f, "mirror_count = %u", seg->area_count); outf(f, "mirror_count = %u", seg->area_count);
if (seg->status & PVMOVE) if (seg->status & PVMOVE)
out_size(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size, out_size(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
"extents_moved = %u", seg->extents_copied); "extents_moved = %" PRIu32, seg->extents_copied);
if (seg->log_lv)
outf(f, "mirror_log = \"%s\"", seg->log_lv->name);
if (seg->region_size)
outf(f, "region_size = %" PRIu32, seg->region_size);
return out_areas(f, seg, "mirror"); return out_areas(f, seg, "mirror");
} }
@ -112,7 +157,7 @@ static struct mirror_state *_init_target(struct pool *mem,
return NULL; return NULL;
} }
mirr_state->region_size = 2 * mirr_state->default_region_size = 2 *
find_config_int(cft->root, find_config_int(cft->root,
"activation/mirror_region_size", "activation/mirror_region_size",
DEFAULT_MIRROR_REGION_SIZE); DEFAULT_MIRROR_REGION_SIZE);
@ -156,16 +201,24 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
} else { } else {
*target = "mirror"; *target = "mirror";
if (!(seg->status & PVMOVE)) {
if (!seg->region_size) {
log_error("Missing region size for mirror segment.");
return 0;
}
region_size = seg->region_size;
} else {
/* Find largest power of 2 region size unit we can use */ /* Find largest power of 2 region size unit we can use */
region_max = (1 << (ffs(seg->area_len) - 1)) * region_max = (1 << (ffs(seg->area_len) - 1)) *
seg->lv->vg->extent_size; seg->lv->vg->extent_size;
region_size = mirr_state->region_size; region_size = mirr_state->default_region_size;
if (region_max < region_size) { if (region_max < region_size) {
region_size = region_max; region_size = region_max;
log_verbose("Using reduced mirror region size of %u sectors", log_verbose("Using reduced mirror region size of %u sectors",
region_size); region_size);
} }
}
if ((ret = compose_log_line(dm, seg, params, paramsize, pos, if ((ret = compose_log_line(dm, seg, params, paramsize, pos,
areas, region_size)) <= 0) { areas, region_size)) <= 0) {

View File

@ -112,6 +112,9 @@ void *malloc_aux(size_t s, const char *file, int line)
if (_mem_stats.bytes > _mem_stats.mbytes) if (_mem_stats.bytes > _mem_stats.mbytes)
_mem_stats.mbytes = _mem_stats.bytes; _mem_stats.mbytes = _mem_stats.bytes;
/* log_debug("Allocated: %u %u %u", nb->id, _mem_stats.blocks_allocated,
_mem_stats.bytes); */
return nb + 1; return nb + 1;
} }

View File

@ -32,6 +32,7 @@ FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent")
FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent") FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent")
FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv") FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv")
FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags") FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags")
FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log")
FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt") FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt")
FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid") FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid")
@ -67,6 +68,7 @@ FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype")
FIELD(SEGS, seg, NUM, "#Str", area_count, 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, "Stripe", stripe_size, 6, size32, "stripesize")
FIELD(SEGS, seg, NUM, "Chunk", chunk_size, 5, size32, "chunksize") FIELD(SEGS, seg, NUM, "Chunk", chunk_size, 5, size32, "chunksize")
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize")
FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start") FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start")
FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size") FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size")
FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags") FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags")

View File

@ -154,14 +154,14 @@ static int _devices_disp(struct report_handle *rh, struct field *field,
} }
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) { switch (seg_type(seg, s)) {
case AREA_LV: case AREA_LV:
name = seg->area[s].u.lv.lv->name; name = seg_lv(seg, s)->name;
extent = seg->area[s].u.lv.le; extent = seg_le(seg, s);
break; break;
case AREA_PV: case AREA_PV:
name = dev_name(seg->area[s].u.pv.pvseg->pv->dev); name = dev_name(seg_dev(seg, s));
extent = seg->area[s].u.pv.pvseg->pe; extent = seg_pe(seg, s);
break; break;
default: default:
name = "unknown"; name = "unknown";
@ -337,6 +337,8 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
repstr[0] = 'p'; repstr[0] = 'p';
else if (lv->status & MIRRORED) else if (lv->status & MIRRORED)
repstr[0] = 'm'; repstr[0] = 'm';
else if (lv->status & MIRROR_LOG)
repstr[0] = 'l';
else if (lv->status & VIRTUAL) else if (lv->status & VIRTUAL)
repstr[0] = 'v'; repstr[0] = 'v';
else if (lv_is_origin(lv)) else if (lv_is_origin(lv))
@ -490,19 +492,35 @@ static int _origin_disp(struct report_handle *rh, struct field *field,
return 1; return 1;
} }
static int _loglv_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lv_segment *seg;
list_iterate_items(seg, &lv->segments) {
if (!seg_is_mirrored(seg) || !seg->log_lv)
continue;
return _string_disp(rh, field, &seg->log_lv->name);
}
field->report_string = "";
field->sort_value = (const void *) field->report_string;
return 1;
}
static int _movepv_disp(struct report_handle *rh, struct field *field, static int _movepv_disp(struct report_handle *rh, struct field *field,
const void *data) const void *data)
{ {
const struct logical_volume *lv = (const struct logical_volume *) data; const struct logical_volume *lv = (const struct logical_volume *) data;
const char *name; const char *name;
struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (!(seg->status & PVMOVE)) if (!(seg->status & PVMOVE))
continue; continue;
name = dev_name(seg->area[0].u.pv.pvseg->pv->dev); name = dev_name(seg_dev(seg, 0));
return _string_disp(rh, field, &name); return _string_disp(rh, field, &name);
} }
@ -917,12 +935,9 @@ static int _field_match(struct report_handle *rh, const char *field, size_t len)
static int _add_sort_key(struct report_handle *rh, uint32_t field_num, static int _add_sort_key(struct report_handle *rh, uint32_t field_num,
uint32_t flags) uint32_t flags)
{ {
struct list *fh;
struct field_properties *fp, *found = NULL; struct field_properties *fp, *found = NULL;
list_iterate(fh, &rh->field_props) { list_iterate_items(fp, &rh->field_props) {
fp = list_item(fh, struct field_properties);
if (fp->field_num == field_num) { if (fp->field_num == field_num) {
found = fp; found = fp;
break; break;
@ -1138,7 +1153,6 @@ int report_object(void *handle, struct volume_group *vg,
struct lv_segment *seg, struct pv_segment *pvseg) struct lv_segment *seg, struct pv_segment *pvseg)
{ {
struct report_handle *rh = handle; struct report_handle *rh = handle;
struct list *fh;
struct field_properties *fp; struct field_properties *fp;
struct row *row; struct row *row;
struct field *field; struct field *field;
@ -1168,9 +1182,7 @@ int report_object(void *handle, struct volume_group *vg,
list_add(&rh->rows, &row->list); list_add(&rh->rows, &row->list);
/* For each field to be displayed, call its report_fn */ /* For each field to be displayed, call its report_fn */
list_iterate(fh, &rh->field_props) { list_iterate_items(fp, &rh->field_props) {
fp = list_item(fh, struct field_properties);
skip = 0; skip = 0;
if (!(field = pool_zalloc(rh->mem, sizeof(*field)))) { if (!(field = pool_zalloc(rh->mem, sizeof(*field)))) {
@ -1231,7 +1243,6 @@ int report_object(void *handle, struct volume_group *vg,
static int _report_headings(void *handle) static int _report_headings(void *handle)
{ {
struct report_handle *rh = handle; struct report_handle *rh = handle;
struct list *fh;
struct field_properties *fp; struct field_properties *fp;
const char *heading; const char *heading;
char buf[1024]; char buf[1024];
@ -1250,8 +1261,7 @@ static int _report_headings(void *handle)
} }
/* First heading line */ /* First heading line */
list_iterate(fh, &rh->field_props) { list_iterate_items(fp, &rh->field_props) {
fp = list_item(fh, struct field_properties);
if (fp->flags & FLD_HIDDEN) if (fp->flags & FLD_HIDDEN)
continue; continue;
@ -1268,7 +1278,7 @@ static int _report_headings(void *handle)
} else if (!pool_grow_object(rh->mem, heading, strlen(heading))) } else if (!pool_grow_object(rh->mem, heading, strlen(heading)))
goto bad; goto bad;
if (!list_end(&rh->field_props, fh)) if (!list_end(&rh->field_props, &fp->list))
if (!pool_grow_object(rh->mem, rh->separator, if (!pool_grow_object(rh->mem, rh->separator,
strlen(rh->separator))) strlen(rh->separator)))
goto bad; goto bad;
@ -1336,7 +1346,6 @@ static int _row_compare(const void *a, const void *b)
static int _sort_rows(struct report_handle *rh) static int _sort_rows(struct report_handle *rh)
{ {
struct row *(*rows)[]; struct row *(*rows)[];
struct list *rowh;
uint32_t count = 0; uint32_t count = 0;
struct row *row; struct row *row;
@ -1346,10 +1355,8 @@ static int _sort_rows(struct report_handle *rh)
return 0; return 0;
} }
list_iterate(rowh, &rh->rows) { list_iterate_items(row, &rh->rows)
row = list_item(rowh, struct row);
(*rows)[count++] = row; (*rows)[count++] = row;
}
qsort(rows, count, sizeof(**rows), _row_compare); qsort(rows, count, sizeof(**rows), _row_compare);

View File

@ -119,10 +119,10 @@ static int _segments_compatible(struct lv_segment *first,
width = first->area_len; width = first->area_len;
if ((first->area[s].u.pv.pvseg->pv != if ((seg_pv(first, s) !=
second->area[s].u.pv.pvseg->pv) || seg_pv(second, s)) ||
(first->area[s].u.pv.pvseg->pe + width != (seg_pe(first, s) + width !=
second->area[s].u.pv.pvseg->pe)) seg_pe(second, s)))
return 0; return 0;
} }
@ -144,8 +144,8 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
for (s = 0; s < seg1->area_count; s++) for (s = 0; s < seg1->area_count; s++)
if (seg1->area[s].type == AREA_PV) if (seg1->area[s].type == AREA_PV)
merge_pv_segments(seg1->area[s].u.pv.pvseg, merge_pv_segments(seg_pvseg(seg1, s),
seg2->area[s].u.pv.pvseg); seg_pvseg(seg2, s));
return 1; return 1;
} }

View File

@ -103,6 +103,14 @@ static inline int list_end(struct list *head, struct list *elem)
return elem->n == head; return elem->n == head;
} }
/*
* Return first element of the list or NULL if empty
*/
static inline struct list *list_first(struct list *head)
{
return (list_empty(head) ? NULL : head->n);
}
/* /*
* Return last element of the list or NULL if empty * Return last element of the list or NULL if empty
*/ */
@ -194,6 +202,25 @@ static inline struct list *list_next(struct list *head, struct list *elem)
*/ */
#define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list) #define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list)
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The 'struct list' variable within the containing structure is 'field'.
*/
#define list_iterate_back_items_gen(v, head, field) \
for (v = list_struct_base((head)->p, typeof(*v), field); \
&v->field != (head); \
v = list_struct_base(v->field.p, typeof(*v), field))
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct list list' within the containing structure.
*/
#define list_iterate_back_items(v, head) list_iterate_back_items_gen(v, (head), list)
/* /*
* Return the number of elements in a list by walking it. * Return the number of elements in a list by walking it.
*/ */

View File

@ -85,6 +85,7 @@ arg(size_ARG, 'L', "size", size_mb_arg)
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign) arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign)
arg(persistent_ARG, 'M', "persistent", yes_no_arg) arg(persistent_ARG, 'M', "persistent", yes_no_arg)
arg(major_ARG, 'j', "major", major_arg) arg(major_ARG, 'j', "major", major_arg)
arg(mirrors_ARG, 'm', "mirrors", int_arg)
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg) arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg)
arg(maps_ARG, 'm', "maps", NULL) arg(maps_ARG, 'm', "maps", NULL)
arg(name_ARG, 'n', "name", string_arg) arg(name_ARG, 'n', "name", string_arg)
@ -100,6 +101,7 @@ arg(physicalvolume_ARG, 'P', "physicalvolume", NULL)
arg(readahead_ARG, 'r', "readahead", int_arg) arg(readahead_ARG, 'r', "readahead", int_arg)
arg(resizefs_ARG, 'r', "resizefs", NULL) arg(resizefs_ARG, 'r', "resizefs", NULL)
arg(reset_ARG, 'R', "reset", NULL) arg(reset_ARG, 'R', "reset", NULL)
arg(regionsize_ARG, 'R', "regionsize", size_mb_arg)
arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg) arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg)
arg(stdin_ARG, 's', "stdin", NULL) arg(stdin_ARG, 's', "stdin", NULL)
arg(snapshot_ARG, 's', "snapshot", NULL) arg(snapshot_ARG, 's', "snapshot", NULL)

View File

@ -91,9 +91,11 @@ xx(lvcreate,
"\t{-l|--extents LogicalExtentsNumber |\n" "\t{-l|--extents LogicalExtentsNumber |\n"
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n" "\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n" "\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-m|--mirrors Mirrors]\n"
"\t[-n|--name LogicalVolumeName]\n" "\t[-n|--name LogicalVolumeName]\n"
"\t[-p|--permission {r|rw}]\n" "\t[-p|--permission {r|rw}]\n"
"\t[-r|--readahead ReadAheadSectors]\n" "\t[-r|--readahead ReadAheadSectors]\n"
"\t[-R|--regionsize MirrorLogRegionSize]\n"
"\t[-t|--test]\n" "\t[-t|--test]\n"
"\t[--type VolumeType]\n" "\t[--type VolumeType]\n"
"\t[-v|--verbose]\n" "\t[-v|--verbose]\n"
@ -122,9 +124,9 @@ xx(lvcreate,
"\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n", "\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n",
addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG, addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG,
extents_ARG, major_ARG, minor_ARG, name_ARG, permission_ARG, extents_ARG, major_ARG, minor_ARG, mirrors_ARG, name_ARG, permission_ARG,
persistent_ARG, readahead_ARG, size_ARG, snapshot_ARG, stripes_ARG, persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG,
stripesize_ARG, test_ARG, type_ARG, zero_ARG) stripes_ARG, stripesize_ARG, test_ARG, type_ARG, zero_ARG)
xx(lvdisplay, xx(lvdisplay,
"Display information about a logical volume", "Display information about a logical volume",

View File

@ -405,6 +405,12 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED; return ECMD_FAILED;
} }
/* FIXME Test for VISIBLE instead? */
if (lv->status & MIRROR_LOG) {
log_error("Unable to change mirror log LV %s directly", lv->name);
return ECMD_FAILED;
}
/* access permission change */ /* access permission change */
if (arg_count(cmd, permission_ARG)) { if (arg_count(cmd, permission_ARG)) {
if (!archive(lv->vg)) if (!archive(lv->vg))

View File

@ -14,6 +14,7 @@
*/ */
#include "tools.h" #include "tools.h"
#include "lv_alloc.h"
#include <fcntl.h> #include <fcntl.h>
@ -31,6 +32,7 @@ struct lvcreate_params {
uint32_t stripes; uint32_t stripes;
uint32_t stripe_size; uint32_t stripe_size;
uint32_t chunk_size; uint32_t chunk_size;
uint32_t region_size;
uint32_t mirrors; uint32_t mirrors;
@ -228,6 +230,38 @@ static int _read_stripe_params(struct lvcreate_params *lp,
return 1; return 1;
} }
static int _read_mirror_params(struct lvcreate_params *lp,
struct cmd_context *cmd,
int *pargc, char ***pargv)
{
int argc = *pargc;
if (argc && (unsigned) argc < lp->mirrors) {
log_error("Too few physical volumes on "
"command line for %d-way mirroring", lp->mirrors);
return 0;
}
if (arg_count(cmd, regionsize_ARG)) {
if (arg_sign_value(cmd, regionsize_ARG, 0) == SIGN_MINUS) {
log_error("Negative regionsize is invalid");
return 0;
}
lp->region_size = 2 * arg_uint_value(cmd, regionsize_ARG, 0);
} else
lp->region_size = 2 * find_config_int(cmd->cft->root,
"activation/mirror_region_size",
DEFAULT_MIRROR_REGION_SIZE);
if (lp->region_size & (lp->region_size - 1)) {
log_error("Region size (%" PRIu32 ") must be a power of 2",
lp->region_size);
return 0;
}
return 1;
}
static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd, static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
int argc, char **argv) int argc, char **argv)
{ {
@ -249,6 +283,18 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
if (arg_count(cmd, snapshot_ARG) || seg_is_snapshot(lp)) if (arg_count(cmd, snapshot_ARG) || seg_is_snapshot(lp))
lp->snapshot = 1; lp->snapshot = 1;
lp->mirrors = 1;
/* Default to 2 mirrored areas if --type mirror */
if (seg_is_mirrored(lp))
lp->mirrors = 2;
if (arg_count(cmd, mirrors_ARG)) {
lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
if (lp->mirrors == 1)
log_print("Redundant mirrors argument: default is 0");
}
if (lp->snapshot) { if (lp->snapshot) {
if (arg_count(cmd, zero_ARG)) { if (arg_count(cmd, zero_ARG)) {
log_error("-Z is incompatible with snapshots"); log_error("-Z is incompatible with snapshots");
@ -272,6 +318,25 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
} }
} }
if (lp->mirrors > 1) {
if (lp->snapshot) {
log_error("mirrors and snapshots are currently "
"incompatible");
return 0;
}
if (lp->stripes > 1) {
log_error("mirrors and stripes are currently "
"incompatible");
return 0;
}
if (!(lp->segtype = get_segtype_from_string(cmd, "mirror"))) {
stack;
return 0;
}
}
if (activation() && lp->segtype->ops->target_present && if (activation() && lp->segtype->ops->target_present &&
!lp->segtype->ops->target_present()) { !lp->segtype->ops->target_present()) {
log_error("%s: Required device-mapper target(s) not " log_error("%s: Required device-mapper target(s) not "
@ -281,8 +346,11 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
if (!_read_name_params(lp, cmd, &argc, &argv) || if (!_read_name_params(lp, cmd, &argc, &argv) ||
!_read_size_params(lp, cmd, &argc, &argv) || !_read_size_params(lp, cmd, &argc, &argv) ||
!_read_stripe_params(lp, cmd, &argc, &argv)) !_read_stripe_params(lp, cmd, &argc, &argv) ||
!_read_mirror_params(lp, cmd, &argc, &argv)) {
stack;
return 0; return 0;
}
/* /*
* Should we zero the lv. * Should we zero the lv.
@ -392,14 +460,15 @@ static int _zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
{ {
uint32_t size_rest; uint32_t size_rest, region_max;
uint32_t status = 0; uint32_t status = 0;
uint64_t tmp_size; uint64_t tmp_size;
struct volume_group *vg; struct volume_group *vg;
struct logical_volume *lv, *org = NULL; struct logical_volume *lv, *org = NULL, *log_lv = NULL;
struct list *pvh; struct list *pvh;
const char *tag; const char *tag;
int consistent = 1; int consistent = 1;
struct alloc_handle *ah = NULL;
status |= lp->permission | VISIBLE_LV; status |= lp->permission | VISIBLE_LV;
@ -505,32 +574,100 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0; return 0;
} }
if (lp->stripes > list_size(pvh)) { if (lp->stripes > list_size(pvh) && lp->alloc != ALLOC_ANYWHERE) {
log_error("Number of stripes (%u) must not exceed " log_error("Number of stripes (%u) must not exceed "
"number of physical volumes (%d)", lp->stripes, "number of physical volumes (%d)", lp->stripes,
list_size(pvh)); list_size(pvh));
return 0; return 0;
} }
if (!(lv = lv_create_empty(vg->fid, lp->lv_name, "lvol%d", NULL, if (lp->mirrors > 1 && !activation()) {
status, lp->alloc, 0, vg))) { log_error("Can't create mirror without using "
stack; "device-mapper kernel driver.");
return 0; return 0;
} }
/* The snapshot segment gets created later */ /* The snapshot segment gets created later */
if (lp->snapshot) if (lp->snapshot &&
if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) { !(lp->segtype = get_segtype_from_string(cmd, "striped"))) {
stack; stack;
return 0; return 0;
} }
if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size, if (!archive(vg))
lp->mirrors, lp->extents, NULL, 0u, 0u, pvh, lp->alloc)) { return 0;
if (lp->mirrors > 1) {
/* FIXME Adjust lp->region_size if necessary */
region_max = (1 << (ffs(lp->extents) - 1)) * vg->extent_size;
if (region_max < lp->region_size) {
lp->region_size = region_max;
log_print("Using reduced mirror region size of %" PRIu32
" sectors", lp->region_size);
}
/* FIXME Calculate how many extents needed for the log */
if (!(log_lv = lv_create_empty(vg->fid, NULL, "mirrorlog%d", NULL,
VISIBLE_LV | LVM_READ | LVM_WRITE,
lp->alloc, 0, vg))) {
stack; stack;
return 0; return 0;
} }
if (!(ah = allocate_extents(vg, NULL, lp->segtype, lp->stripes,
lp->mirrors, 1, lp->extents,
NULL, 0, 0, pvh, lp->alloc))) {
stack;
return 0;
}
if (!lv_add_log_segment(ah, log_lv)) {
stack;
goto error;
}
/* store mirror log on disk(s) */
if (!vg_write(vg)) {
stack;
goto error;
}
backup(vg);
if (!vg_commit(vg)) {
stack;
goto error;
}
if (!activate_lv(cmd, log_lv->lvid.s)) {
log_error("Aborting. Failed to activate mirror log. "
"Remove new LVs and retry.");
goto error;
}
if (activation() && !_zero_lv(cmd, log_lv)) {
log_error("Aborting. Failed to wipe mirror log. "
"Remove new LV and retry.");
goto error;
}
if (!deactivate_lv(cmd, log_lv->lvid.s)) {
log_error("Aborting. Failed to deactivate mirror log. "
"Remove new LV and retry.");
goto error;
}
log_lv->status &= ~VISIBLE_LV;
}
if (!(lv = lv_create_empty(vg->fid, lp->lv_name, "lvol%d", NULL,
status, lp->alloc, 0, vg))) {
stack;
goto error;
}
if (lp->read_ahead) { if (lp->read_ahead) {
log_verbose("Setting read ahead sectors"); log_verbose("Setting read ahead sectors");
lv->read_ahead = lp->read_ahead; lv->read_ahead = lp->read_ahead;
@ -547,24 +684,38 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
if (arg_count(cmd, addtag_ARG)) { if (arg_count(cmd, addtag_ARG)) {
if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) { if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
log_error("Failed to get tag"); log_error("Failed to get tag");
return 0; goto error;
} }
if (!(lv->vg->fid->fmt->features & FMT_TAGS)) { if (!(lv->vg->fid->fmt->features & FMT_TAGS)) {
log_error("Volume group %s does not support tags", log_error("Volume group %s does not support tags",
lv->vg->name); lv->vg->name);
return 0; goto error;
} }
if (!str_list_add(cmd->mem, &lv->tags, tag)) { if (!str_list_add(cmd->mem, &lv->tags, tag)) {
log_error("Failed to add tag %s to %s/%s", log_error("Failed to add tag %s to %s/%s",
tag, lv->vg->name, lv->name); tag, lv->vg->name, lv->name);
return 0; goto error;
} }
} }
if (!archive(vg)) if (lp->mirrors > 1) {
if (!lv_add_segment(ah, 0, lp->mirrors, lv, lp->segtype,
lp->stripe_size, NULL, 0, 0,
lp->region_size, log_lv)) {
log_error("Aborting. Failed to add mirror segment. "
"Remove new LV and retry.");
goto error;
}
alloc_destroy(ah);
ah = NULL;
} else if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size,
lp->mirrors, lp->extents, NULL, 0u, 0u, pvh, lp->alloc)) {
stack;
return 0; return 0;
}
/* store vg on disk(s) */ /* store vg on disk(s) */
if (!vg_write(vg)) { if (!vg_write(vg)) {
@ -642,6 +793,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
*/ */
return 1; return 1;
error:
if (ah)
alloc_destroy(ah);
return 0;
} }
int lvcreate(struct cmd_context *cmd, int argc, char **argv) int lvcreate(struct cmd_context *cmd, int argc, char **argv)

View File

@ -34,6 +34,12 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED; return ECMD_FAILED;
} }
if (lv->status & MIRROR_LOG) {
log_error("Can't remove logical volume %s used as mirror log",
lv->name);
return ECMD_FAILED;
}
if (lv->status & LOCKED) { if (lv->status & LOCKED) {
log_error("Can't remove locked LV %s", lv->name); log_error("Can't remove locked LV %s", lv->name);
return ECMD_FAILED; return ECMD_FAILED;

View File

@ -110,9 +110,9 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
int ret = 0; int ret = 0;
int consistent; int consistent;
struct list *slh, *tags_arg; struct list *tags_arg;
struct list *vgnames; /* VGs to process */ struct list *vgnames; /* VGs to process */
struct str_list *sll; struct str_list *sll, *strl;
struct volume_group *vg; struct volume_group *vg;
struct list tags, lvnames; struct list tags, lvnames;
struct list arg_lvnames; /* Cmdline vgname or vgname/lvname */ struct list arg_lvnames; /* Cmdline vgname or vgname/lvname */
@ -228,8 +228,8 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
} }
} }
list_iterate(slh, vgnames) { list_iterate_items(strl, vgnames) {
vgname = list_item(slh, struct str_list)->str; vgname = strl->str;
if (!vgname || !*vgname) if (!vgname || !*vgname)
continue; /* FIXME Unnecessary? */ continue; /* FIXME Unnecessary? */
if (!lock_vol(cmd, vgname, lock_type)) { if (!lock_vol(cmd, vgname, lock_type)) {

View File

@ -30,10 +30,10 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
if ((lv->status & SNAPSHOT) || lv_is_cow(lv)) if ((lv->status & SNAPSHOT) || lv_is_cow(lv))
continue; continue;
/* Can't deactive a pvmove LV */ /* Can't deactive a pvmove or log LV */
/* FIXME There needs to be a controlled way of doing this */ /* FIXME There needs to be a controlled way of doing this */
if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) && if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
(lv->status & PVMOVE)) ((lv->status & PVMOVE) || (lv->status & MIRROR_LOG)))
continue; continue;
if (activate == CHANGE_AN) { if (activate == CHANGE_AN) {

View File

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

View File

@ -78,10 +78,10 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
list_iterate_items(seg, &lv->segments) { list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) { for (s = 0; s < seg->area_count; s++) {
/* FIXME Check AREA_LV too */ /* FIXME Check AREA_LV too */
if (seg->area[s].type != AREA_PV) if (seg_type(seg, s) != AREA_PV)
continue; continue;
pv = seg->area[s].u.pv.pvseg->pv; pv = seg_pv(seg, s);
if (vg_with) { if (vg_with) {
if (!pv_is_in_vg(vg_with, pv)) { if (!pv_is_in_vg(vg_with, pv)) {
log_error("Logical Volume %s " log_error("Logical Volume %s "