mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-30 17:18:21 +03:00
Basic support for mirrors.
This commit is contained in:
parent
8e6230ddd9
commit
60f13f01d2
11
WHATS_NEW
11
WHATS_NEW
@ -1,5 +1,16 @@
|
||||
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 vgmerge to handle duplicate LVIDs.
|
||||
Move archiver code from tools into library.
|
||||
|
@ -517,17 +517,15 @@ static int _lv_suspend_lv(struct logical_volume *lv)
|
||||
*/
|
||||
int lvs_in_vg_activated(struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_list *lvl;
|
||||
int count = 0;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (lv->status & VISIBLE_LV)
|
||||
count += (_lv_active(lv) == 1);
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lvl->lv->status & VISIBLE_LV)
|
||||
count += (_lv_active(lvl->lv) == 1);
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -535,17 +533,16 @@ int lvs_in_vg_activated(struct volume_group *vg)
|
||||
|
||||
int lvs_in_vg_opened(struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct lv_list *lvl;
|
||||
struct logical_volume *lv;
|
||||
int count = 0;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (lv->status & VISIBLE_LV)
|
||||
count += (_lv_open_count(lv) > 0);
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lvl->lv->status & VISIBLE_LV)
|
||||
count += (_lv_open_count(lvl->lv) > 0);
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -732,9 +732,38 @@ int compose_log_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
uint32_t region_size)
|
||||
{
|
||||
int tw;
|
||||
char devbuf[10];
|
||||
char *name;
|
||||
struct dev_layer *dl;
|
||||
|
||||
tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
|
||||
region_size, areas);
|
||||
if (!seg->log_lv)
|
||||
tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
|
||||
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) {
|
||||
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) {
|
||||
trailing_space = (areas - s - 1) ? " " : "";
|
||||
if ((seg->area[s].type == AREA_PV &&
|
||||
(!seg->area[s].u.pv.pvseg ||
|
||||
!seg->area[s].u.pv.pvseg->pv ||
|
||||
!seg->area[s].u.pv.pvseg->pv->dev)) ||
|
||||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
|
||||
if ((seg_type(seg, s) == AREA_PV &&
|
||||
(!seg_pvseg(seg, s) ||
|
||||
!seg_pv(seg, s) ||
|
||||
!seg_dev(seg, s))) ||
|
||||
(seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
|
||||
tw = lvm_snprintf(params + *pos, paramsize - *pos,
|
||||
"%s 0%s", dm->stripe_filler,
|
||||
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,
|
||||
"%s %" PRIu64 "%s",
|
||||
dev_name(seg->area[s].u.pv.pvseg->
|
||||
pv->dev),
|
||||
(seg->area[s].u.pv.pvseg->pv->
|
||||
pe_start +
|
||||
(esize * seg->area[s].u.pv.pvseg->
|
||||
pe)),
|
||||
dev_name(seg_dev(seg, s)),
|
||||
(seg_pv(seg, s)->pe_start +
|
||||
(esize * seg_pe(seg, s))),
|
||||
trailing_space);
|
||||
else {
|
||||
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",
|
||||
seg->area[s].u.lv.lv->lvid.s);
|
||||
seg_lv(seg, s)->lvid.s);
|
||||
return 0;
|
||||
}
|
||||
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,
|
||||
"%s %" PRIu64 "%s", devbuf,
|
||||
esize * seg->area[s].u.lv.le,
|
||||
esize * seg_le(seg, s),
|
||||
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,
|
||||
struct dm_task *dmt, struct dev_layer *dl)
|
||||
{
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
struct logical_volume *lv = dl->lv;
|
||||
|
||||
dm->pvmove_mirror_count = 0u;
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (!_emit_target(dm, dmt, seg)) {
|
||||
log_error("Unable to build table for '%s'", lv->name);
|
||||
return 0;
|
||||
@ -1201,7 +1225,6 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
|
||||
* only one layer.
|
||||
*/
|
||||
struct dev_layer *dl, *dlr;
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
uint32_t s;
|
||||
|
||||
@ -1219,14 +1242,22 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
|
||||
_set_flag(dl, TOPLEVEL);
|
||||
|
||||
/* Add dependencies for any LVs that segments refer to */
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
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++) {
|
||||
if (seg->area[s].type != AREA_LV)
|
||||
if (seg_type(seg, s) != AREA_LV)
|
||||
continue;
|
||||
if (!str_list_add(dm->mem, &dl->pre_create,
|
||||
_build_dlid(dm->mem,
|
||||
seg->area[s].u.lv.lv->
|
||||
seg_lv(seg, s)->
|
||||
lvid.s, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
@ -1300,14 +1331,14 @@ static int _expand_origin(struct dev_manager *dm, struct logical_volume *lv)
|
||||
{
|
||||
struct logical_volume *active;
|
||||
struct lv_segment *snap_seg;
|
||||
struct list *sh;
|
||||
struct lv_list *lvl;
|
||||
|
||||
/*
|
||||
* We only need to create an origin layer if one of our
|
||||
* snapshots is in the active list
|
||||
*/
|
||||
list_iterate(sh, &dm->active_list) {
|
||||
active = list_item(sh, struct lv_list)->lv;
|
||||
list_iterate_items(lvl, &dm->active_list) {
|
||||
active = lvl->lv;
|
||||
if ((snap_seg = find_cow(active)) && (snap_seg->origin == 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,
|
||||
int flag)
|
||||
{
|
||||
struct list *sh;
|
||||
struct str_list *strl;
|
||||
const char *dlid;
|
||||
struct dev_layer *dep;
|
||||
|
||||
list_iterate(sh, &dl->pre_create) {
|
||||
dlid = list_item(sh, struct str_list)->str;
|
||||
list_iterate_items(strl, &dl->pre_create) {
|
||||
dlid = strl->str;
|
||||
|
||||
if (!(dep = hash_lookup(dm->layers, 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)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_list *lvl;
|
||||
struct dev_layer *dl;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (lv->status & SNAPSHOT)
|
||||
list_iterate_items(lvl, lvs) {
|
||||
if (lvl->lv->status & SNAPSHOT)
|
||||
continue;
|
||||
|
||||
if (!(dl = _lookup(dm, lv->lvid.s, NULL))) {
|
||||
if (!(dl = _lookup(dm, lvl->lv->lvid.s, NULL))) {
|
||||
stack;
|
||||
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)
|
||||
{
|
||||
struct list *sh;
|
||||
struct str_list *strl;
|
||||
struct dev_layer *dep;
|
||||
const char *dlid;
|
||||
|
||||
list_iterate(sh, &dl->pre_suspend) {
|
||||
dlid = list_item(sh, struct str_list)->str;
|
||||
list_iterate_items(strl, &dl->pre_suspend) {
|
||||
dlid = strl->str;
|
||||
|
||||
if (!(dep = hash_lookup(dm->layers, dlid))) {
|
||||
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)
|
||||
{
|
||||
struct list *sh;
|
||||
struct str_list *strl;
|
||||
struct dev_layer *dep;
|
||||
const char *dlid;
|
||||
|
||||
list_iterate(sh, &dl->pre_create) {
|
||||
dlid = list_item(sh, struct str_list)->str;
|
||||
list_iterate_items(strl, &dl->pre_create) {
|
||||
dlid = strl->str;
|
||||
|
||||
if (!(dep = hash_lookup(dm->layers, dlid))) {
|
||||
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)
|
||||
{
|
||||
struct list *sh;
|
||||
struct str_list *strl;
|
||||
struct dev_layer *dep;
|
||||
const char *dlid;
|
||||
char *newname, *suffix;
|
||||
@ -1577,8 +1606,8 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate(sh, &dl->pre_create) {
|
||||
dlid = list_item(sh, struct str_list)->str;
|
||||
list_iterate_items(strl, &dl->pre_create) {
|
||||
dlid = strl->str;
|
||||
|
||||
if (!(dep = hash_lookup(dm->layers, 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)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_list *lvl;
|
||||
|
||||
/*
|
||||
* Build layers for complete vg.
|
||||
*/
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (lv->status & SNAPSHOT)
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lvl->lv->status & SNAPSHOT)
|
||||
continue;
|
||||
if (!_expand_lv(dm, lv)) {
|
||||
if (!_expand_lv(dm, lvl->lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@ -1684,15 +1711,15 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
|
||||
{
|
||||
struct hash_node *hn;
|
||||
struct dev_layer *dl;
|
||||
struct list *sh;
|
||||
struct str_list *strl;
|
||||
const char *dlid;
|
||||
struct dev_layer *dep;
|
||||
|
||||
hash_iterate(hn, dm->layers) {
|
||||
dl = hash_get_data(dm->layers, hn);
|
||||
|
||||
list_iterate(sh, &dl->pre_suspend) {
|
||||
dlid = list_item(sh, struct str_list)->str;
|
||||
list_iterate_items(strl, &dl->pre_suspend) {
|
||||
dlid = strl->str;
|
||||
|
||||
if (!(dep = hash_lookup(dm->layers, dlid))) {
|
||||
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) {
|
||||
dlid = list_item(sh, struct str_list)->str;
|
||||
list_iterate_items(strl, &dl->pre_create) {
|
||||
dlid = strl->str;
|
||||
|
||||
if (!(dep = hash_lookup(dm->layers, dlid))) {
|
||||
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)
|
||||
{
|
||||
int change;
|
||||
struct dl_list *dll;
|
||||
struct list *rh, *n;
|
||||
struct dev_layer *dl;
|
||||
|
||||
@ -1755,10 +1783,8 @@ static int _remove_old_layers(struct dev_manager *dm)
|
||||
} while (change);
|
||||
|
||||
if (!list_empty(&dm->remove_list)) {
|
||||
list_iterate(rh, &dm->remove_list) {
|
||||
dl = list_item(rh, struct dl_list)->dl;
|
||||
log_error("Couldn't deactivate device %s", dl->name);
|
||||
}
|
||||
list_iterate_items(dll, &dm->remove_list)
|
||||
log_error("Couldn't deactivate device %s", dll->dl->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1945,16 +1971,14 @@ static int _add_lv(struct pool *mem,
|
||||
static int _add_lvs(struct pool *mem,
|
||||
struct list *head, struct logical_volume *origin)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *snap_seg;
|
||||
struct list *lvh;
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate(lvh, &origin->vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (lv->status & SNAPSHOT)
|
||||
list_iterate_items(lvl, &origin->vg->lvs) {
|
||||
if (lvl->lv->status & SNAPSHOT)
|
||||
continue;
|
||||
if ((snap_seg = find_cow(lv)) && snap_seg->origin == origin)
|
||||
if (!_add_lv(mem, head, lv))
|
||||
if ((snap_seg = find_cow(lvl->lv)) && snap_seg->origin == origin)
|
||||
if (!_add_lv(mem, head, lvl->lv))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1963,13 +1987,11 @@ static int _add_lvs(struct pool *mem,
|
||||
|
||||
static void _remove_lv(struct list *head, struct logical_volume *lv)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate(lvh, head) {
|
||||
lvl = list_item(lvh, struct lv_list);
|
||||
list_iterate_items(lvl, head) {
|
||||
if (lvl->lv == lv) {
|
||||
list_del(lvh);
|
||||
list_del(&lvl->list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1979,13 +2001,14 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
|
||||
{
|
||||
struct logical_volume *active, *old_origin;
|
||||
struct lv_segment *snap_seg;
|
||||
struct list *sh, *active_head;
|
||||
struct list *active_head;
|
||||
struct lv_list *lvl;
|
||||
|
||||
active_head = &dm->active_list;
|
||||
|
||||
/* Remove any snapshots with given origin */
|
||||
list_iterate(sh, active_head) {
|
||||
active = list_item(sh, struct lv_list)->lv;
|
||||
list_iterate_items(lvl, active_head) {
|
||||
active = lvl->lv;
|
||||
if ((snap_seg = find_cow(active)) && snap_seg->origin == lv) {
|
||||
_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;
|
||||
|
||||
/* Was this the last active snapshot with this origin? */
|
||||
list_iterate(sh, active_head) {
|
||||
active = list_item(sh, struct lv_list)->lv;
|
||||
list_iterate_items(lvl, active_head) {
|
||||
active = lvl->lv;
|
||||
if ((snap_seg = find_cow(active)) &&
|
||||
snap_seg->origin == old_origin) {
|
||||
return 1;
|
||||
@ -2015,13 +2038,14 @@ static int _remove_suspended_lvs(struct dev_manager *dm,
|
||||
{
|
||||
struct logical_volume *suspended;
|
||||
struct lv_segment *snap_seg;
|
||||
struct list *sh, *suspend_head;
|
||||
struct list *suspend_head;
|
||||
struct lv_list *lvl;
|
||||
|
||||
suspend_head = &dm->suspend_list;
|
||||
|
||||
/* Remove from list any snapshots with given origin */
|
||||
list_iterate(sh, suspend_head) {
|
||||
suspended = list_item(sh, struct lv_list)->lv;
|
||||
list_iterate_items(lvl, suspend_head) {
|
||||
suspended = lvl->lv;
|
||||
if ((snap_seg = find_cow(suspended)) &&
|
||||
snap_seg->origin == lv) {
|
||||
_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)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct list *lvh, *segh;
|
||||
struct lv_list *lvl;
|
||||
struct segment_type *segtype;
|
||||
struct lv_segment *seg;
|
||||
int snapshots = 0, mirrors = 0;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
list_iterate_items(lvl, lvs) {
|
||||
lv = lvl->lv;
|
||||
|
||||
if (!snapshots)
|
||||
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;
|
||||
|
||||
if (lv->status & VIRTUAL) {
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (seg->segtype->ops->target_present &&
|
||||
!seg->segtype->ops->target_present()) {
|
||||
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)
|
||||
{
|
||||
char *dlid;
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_list *lvl;
|
||||
struct dev_layer *dl;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (lv->status & SNAPSHOT)
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lvl->lv->status & SNAPSHOT)
|
||||
continue;
|
||||
|
||||
if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, NULL))) {
|
||||
if (!(dlid = _build_dlid(dm->mem, lvl->lv->lvid.s, NULL))) {
|
||||
stack;
|
||||
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);
|
||||
|
||||
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)" : "");
|
||||
|
||||
if (!_add_lv(dm->mem, &dm->active_list, lv)) {
|
||||
if (!_add_lv(dm->mem, &dm->active_list, lvl->lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dl->info.suspended) {
|
||||
if (!_add_lv(dm->mem, &dm->suspend_list, lv)) {
|
||||
if (!_add_lv(dm->mem, &dm->suspend_list, lvl->lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
25
lib/cache/lvmcache.c
vendored
25
lib/cache/lvmcache.c
vendored
@ -104,8 +104,9 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
|
||||
const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
struct label *label;
|
||||
struct list *ih, *devh, *tmp;
|
||||
struct list *devh, *tmp;
|
||||
struct list devs;
|
||||
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
|
||||
* we check cached labels here. Unfortunately vginfo is volatile. */
|
||||
list_init(&devs);
|
||||
list_iterate(ih, &vginfo->infos) {
|
||||
devl = malloc(sizeof(*devl));
|
||||
devl->dev = list_item(ih, struct lvmcache_info)->dev;
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
devl = dbg_malloc(sizeof(*devl));
|
||||
devl->dev = info->dev;
|
||||
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);
|
||||
label_read(devl->dev, &label);
|
||||
list_del(&devl->list);
|
||||
free(devl);
|
||||
dbg_free(devl);
|
||||
}
|
||||
|
||||
return vginfo->fmt;
|
||||
@ -186,7 +187,6 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
struct label *label;
|
||||
struct dev_iter *iter;
|
||||
struct device *dev;
|
||||
struct list *fmth;
|
||||
struct format_type *fmt;
|
||||
|
||||
static int _scanning_in_progress = 0;
|
||||
@ -221,8 +221,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
_has_scanned = 1;
|
||||
|
||||
/* Perform any format-specific scanning e.g. text files */
|
||||
list_iterate(fmth, &cmd->formats) {
|
||||
fmt = list_item(fmth, struct format_type);
|
||||
list_iterate_items(fmt, &cmd->formats) {
|
||||
if (fmt->ops->scan && !fmt->ops->scan(fmt))
|
||||
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)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct physical_volume *pv;
|
||||
struct pv_list *pvl;
|
||||
struct lvmcache_info *info;
|
||||
char pvid_s[ID_LEN + 1];
|
||||
int vgid_updated = 0;
|
||||
|
||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
|
||||
/* FIXME Could pv->dev->pvid ever be different? */
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
|
||||
/* FIXME Could pvl->pv->dev->pvid ever be different? */
|
||||
if ((info = info_from_pvid(pvid_s))) {
|
||||
lvmcache_update_vgname(info, vg->name);
|
||||
if (!vgid_updated) {
|
||||
|
@ -622,7 +622,6 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
const char *format;
|
||||
|
||||
struct format_type *fmt;
|
||||
struct list *fmth;
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
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",
|
||||
DEFAULT_FORMAT);
|
||||
|
||||
list_iterate(fmth, &cmd->formats) {
|
||||
fmt = list_item(fmth, struct format_type);
|
||||
list_iterate_items(fmt, &cmd->formats) {
|
||||
if (!strcasecmp(fmt->name, format) ||
|
||||
(fmt->alias && !strcasecmp(fmt->alias, format))) {
|
||||
cmd->default_settings.fmt = fmt;
|
||||
|
@ -91,13 +91,13 @@
|
||||
#define DEFAULT_REP_HEADINGS 1
|
||||
#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_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_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_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"
|
||||
|
@ -103,6 +103,14 @@ static inline int list_end(struct list *head, struct list *elem)
|
||||
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
|
||||
*/
|
||||
@ -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)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
@ -196,7 +196,7 @@ static int _compare_paths(const char *path0, const char *path1)
|
||||
static int _add_alias(struct device *dev, const char *path)
|
||||
{
|
||||
struct str_list *sl = _alloc(sizeof(*sl));
|
||||
struct list *ah;
|
||||
struct str_list *strl;
|
||||
const char *oldpath;
|
||||
int prefer_old = 1;
|
||||
|
||||
@ -206,8 +206,8 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
}
|
||||
|
||||
/* Is name already there? */
|
||||
list_iterate(ah, &dev->aliases) {
|
||||
if (!strcmp(list_item(ah, struct str_list)->str, path)) {
|
||||
list_iterate_items(strl, &dev->aliases) {
|
||||
if (!strcmp(strl->str, path)) {
|
||||
log_debug("%s: Already in device cache", path);
|
||||
return 1;
|
||||
}
|
||||
@ -414,20 +414,16 @@ static int _insert(const char *path, int rec)
|
||||
|
||||
static void _full_scan(int dev_scan)
|
||||
{
|
||||
struct list *dh;
|
||||
struct dir_list *dl;
|
||||
|
||||
if (_cache.has_scanned && !dev_scan)
|
||||
return;
|
||||
|
||||
list_iterate(dh, &_cache.dirs) {
|
||||
struct dir_list *dl = list_item(dh, struct dir_list);
|
||||
list_iterate_items(dl, &_cache.dirs)
|
||||
_insert_dir(dl->dir);
|
||||
};
|
||||
|
||||
list_iterate(dh, &_cache.files) {
|
||||
struct dir_list *dl = list_item(dh, struct dir_list);
|
||||
list_iterate_items(dl, &_cache.files)
|
||||
_insert_file(dl->dir);
|
||||
};
|
||||
|
||||
_cache.has_scanned = 1;
|
||||
init_full_scan_done(1);
|
||||
|
@ -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)
|
||||
{
|
||||
switch (seg->area[s].type) {
|
||||
switch (seg_type(seg, s)) {
|
||||
case AREA_PV:
|
||||
/* FIXME Re-check the conditions for 'Missing' */
|
||||
log_print("%sPhysical volume\t%s", pre,
|
||||
seg->area[s].u.pv.pvseg->pv ?
|
||||
dev_name(seg->area[s].u.pv.pvseg->pv->dev) :
|
||||
seg_pv(seg, s) ?
|
||||
dev_name(seg_dev(seg, s)) :
|
||||
"Missing");
|
||||
|
||||
if (seg->area[s].u.pv.pvseg->pv)
|
||||
if (seg_pv(seg, s))
|
||||
log_print("%sPhysical extents\t%d to %d", pre,
|
||||
seg->area[s].u.pv.pvseg->pe,
|
||||
seg->area[s].u.pv.pvseg->pe +
|
||||
seg->area_len - 1);
|
||||
seg_pe(seg, s),
|
||||
seg_pe(seg, s) + seg->area_len - 1);
|
||||
break;
|
||||
case AREA_LV:
|
||||
log_print("%sLogical volume\t%s", pre,
|
||||
seg->area[s].u.lv.lv ?
|
||||
seg->area[s].u.lv.lv->name : "Missing");
|
||||
seg_lv(seg, s) ?
|
||||
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,
|
||||
seg->area[s].u.lv.le,
|
||||
seg->area[s].u.lv.le + seg->area_len - 1);
|
||||
seg_le(seg, s),
|
||||
seg_le(seg, s) + seg->area_len - 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -204,16 +204,14 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
void *l = hash_lookup(pf->devices, dev_name(dev));
|
||||
struct str_list *sl;
|
||||
struct list *ah;
|
||||
|
||||
if (!l) {
|
||||
l = pf->real->passes_filter(pf->real, dev) ?
|
||||
PF_GOOD_DEVICE : PF_BAD_DEVICE;
|
||||
|
||||
list_iterate(ah, &dev->aliases) {
|
||||
sl = list_item(ah, struct str_list);
|
||||
list_iterate_items(sl, &dev->aliases)
|
||||
hash_insert(pf->devices, sl->str, l);
|
||||
}
|
||||
|
||||
} else if (l == PF_BAD_DEVICE)
|
||||
log_debug("%s: Skipping (cached)", dev_name(dev));
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
struct list *ah;
|
||||
int m, first = 1, rejected = 0;
|
||||
struct rfilter *rf = (struct rfilter *) f->private;
|
||||
struct str_list *sl;
|
||||
|
||||
list_iterate(ah, &dev->aliases) {
|
||||
sl = list_item(ah, struct str_list);
|
||||
list_iterate_items(sl, &dev->aliases) {
|
||||
m = matcher_run(rf->engine, sl->str);
|
||||
|
||||
if (m >= 0) {
|
||||
|
@ -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)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct pv_disk *pvd;
|
||||
struct disk_list *diskl;
|
||||
|
||||
list_iterate(pvdh, head) {
|
||||
pvd = &list_item(pvdh, struct disk_list)->pvd;
|
||||
list_iterate_items(diskl, head) {
|
||||
pvd = &diskl->pvd;
|
||||
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
|
||||
sizeof(pvd->pv_uuid))) {
|
||||
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",
|
||||
pvd->pv_uuid, dev_name(data->dev));
|
||||
list_del(pvdh);
|
||||
list_del(&diskl->list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -458,14 +458,14 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
||||
struct dev_iter *iter;
|
||||
struct device *dev;
|
||||
struct disk_list *data = NULL;
|
||||
struct list *vgih;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* Fast path if we already saw this VG and cached the list of PVs */
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
||||
vginfo->infos.n) {
|
||||
list_iterate(vgih, &vginfo->infos) {
|
||||
dev = list_item(vgih, struct lvmcache_info)->dev;
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
dev = info->dev;
|
||||
if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
|
||||
break;
|
||||
_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)
|
||||
{
|
||||
struct uuid_list *ul;
|
||||
struct list *uh;
|
||||
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
|
||||
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) {
|
||||
log_error("Too many uuids to fit on %s",
|
||||
dev_name(data->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ul = list_item(uh, struct uuid_list);
|
||||
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
|
||||
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)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct lvd_list *ll;
|
||||
uint64_t pos, offset;
|
||||
|
||||
pos = data->pvd.lv_on_disk.base;
|
||||
@ -563,9 +561,7 @@ static int _write_lvs(struct disk_list *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate(lvh, &data->lvds) {
|
||||
struct lvd_list *ll = list_item(lvh, struct lvd_list);
|
||||
|
||||
list_iterate_items(ll, &data->lvds) {
|
||||
offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
|
||||
if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
|
||||
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)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct disk_list *dl;
|
||||
|
||||
list_iterate(pvh, pvs) {
|
||||
dl = list_item(pvh, struct disk_list);
|
||||
list_iterate_items(dl, pvs) {
|
||||
if (!(_write_all_pvd(fmt, dl)))
|
||||
fail;
|
||||
|
||||
|
@ -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
|
||||
* bearing an exported VG with the same name.
|
||||
*/
|
||||
list_iterate(pvh, pvs) {
|
||||
dl = list_item(pvh, struct disk_list);
|
||||
|
||||
list_iterate_items(dl, pvs) {
|
||||
if (first_time) {
|
||||
exported = dl->pvd.pv_status & VG_EXPORTED;
|
||||
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 dev_filter *filter)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
struct disk_list *data;
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pvl = list_item(pvh, struct pv_list);
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
|
||||
stack;
|
||||
return 0;
|
||||
|
@ -87,7 +87,7 @@ int import_pv(struct pool *mem, struct device *dev,
|
||||
pv->pe_size = pvd->pe_size;
|
||||
pv->pe_start = pvd->pe_start;
|
||||
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->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,
|
||||
struct logical_volume *lv, struct physical_volume *pv)
|
||||
{
|
||||
struct list *segh;
|
||||
struct pe_disk *ped;
|
||||
struct lv_segment *seg;
|
||||
uint32_t pe, s;
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
if (seg->area[s].type != AREA_PV) {
|
||||
if (seg_type(seg, s) != AREA_PV) {
|
||||
log_error("LV stripe found in LV %s: "
|
||||
"unsupported by format1", lv->name);
|
||||
return 0;
|
||||
}
|
||||
if (seg->area[s].u.pv.pvseg->pv != pv)
|
||||
if (seg_pv(seg, s) != pv)
|
||||
continue; /* not our pv */
|
||||
|
||||
for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
|
||||
ped = &dl->extents[pe +
|
||||
seg->area[s].u.pv.pvseg->pe];
|
||||
ped = &dl->extents[pe + seg_pe(seg, s)];
|
||||
ped->lv_num = lv_num;
|
||||
ped->le_num = (seg->le / seg->area_count) + pe +
|
||||
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 list *pvds, struct list *results, int *count)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct disk_list *dl;
|
||||
struct pv_list *pvl;
|
||||
|
||||
*count = 0;
|
||||
list_iterate(pvdh, pvds) {
|
||||
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
|
||||
list_iterate_items(dl, pvds) {
|
||||
if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) ||
|
||||
!(pvl->pv = pool_alloc(mem, sizeof(*pvl->pv)))) {
|
||||
stack;
|
||||
@ -481,12 +473,9 @@ int import_lvs(struct pool *mem, struct volume_group *vg, struct list *pvds)
|
||||
struct disk_list *dl;
|
||||
struct lvd_list *ll;
|
||||
struct lv_disk *lvd;
|
||||
struct list *pvdh, *lvdh;
|
||||
|
||||
list_iterate(pvdh, pvds) {
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
list_iterate(lvdh, &dl->lvds) {
|
||||
ll = list_item(lvdh, struct lvd_list);
|
||||
list_iterate_items(dl, pvds) {
|
||||
list_iterate_items(ll, &dl->lvds) {
|
||||
lvd = &ll->lvd;
|
||||
|
||||
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)
|
||||
{
|
||||
int r = 0;
|
||||
struct list *lvh;
|
||||
struct lv_list *ll;
|
||||
struct lvd_list *lvdl;
|
||||
size_t len;
|
||||
@ -532,8 +520,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
||||
}
|
||||
memset(dl->extents, 0, len);
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
ll = list_item(lvh, struct lv_list);
|
||||
list_iterate_items(ll, &vg->lvs) {
|
||||
if (ll->lv->status & SNAPSHOT)
|
||||
continue;
|
||||
|
||||
@ -585,19 +572,17 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
|
||||
struct list *pvds)
|
||||
{
|
||||
struct logical_volume *lvs[MAX_LV];
|
||||
struct list *pvdh, *lvdh;
|
||||
struct disk_list *dl;
|
||||
struct lvd_list *ll;
|
||||
struct lv_disk *lvd;
|
||||
int lvnum;
|
||||
struct logical_volume *org, *cow;
|
||||
|
||||
/* build an index of lv numbers */
|
||||
memset(lvs, 0, sizeof(lvs));
|
||||
list_iterate(pvdh, pvds) {
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
|
||||
list_iterate(lvdh, &dl->lvds) {
|
||||
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
|
||||
list_iterate_items(dl, pvds) {
|
||||
list_iterate_items(ll, &dl->lvds) {
|
||||
lvd = &ll->lvd;
|
||||
|
||||
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.
|
||||
*/
|
||||
list_iterate(pvdh, pvds) {
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
|
||||
list_iterate(lvdh, &dl->lvds) {
|
||||
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
|
||||
list_iterate_items(dl, pvds) {
|
||||
list_iterate_items(ll, &dl->lvds) {
|
||||
lvd = &ll->lvd;
|
||||
|
||||
if (!(lvd->lv_access & LV_SNAPSHOT))
|
||||
continue;
|
||||
@ -657,10 +640,8 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
|
||||
{
|
||||
struct uuid_list *ul;
|
||||
struct pv_list *pvl;
|
||||
struct list *pvh;
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pvl = list_item(pvh, struct pv_list);
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!(ul = pool_alloc(dl->mem, sizeof(*ul)))) {
|
||||
stack;
|
||||
return 0;
|
||||
@ -680,14 +661,11 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
|
||||
*/
|
||||
void export_numbers(struct list *pvds, struct volume_group *vg)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct disk_list *dl;
|
||||
int pv_num = 1;
|
||||
|
||||
list_iterate(pvdh, pvds) {
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
list_iterate_items(dl, pvds)
|
||||
dl->pvd.pv_number = pv_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -695,26 +673,20 @@ void export_numbers(struct list *pvds, struct volume_group *vg)
|
||||
*/
|
||||
void export_pv_act(struct list *pvds)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct disk_list *dl;
|
||||
int act = 0;
|
||||
|
||||
list_iterate(pvdh, pvds) {
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
list_iterate_items(dl, pvds)
|
||||
if (dl->pvd.pv_status & PV_ACTIVE)
|
||||
act++;
|
||||
}
|
||||
|
||||
list_iterate(pvdh, pvds) {
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
list_iterate_items(dl, pvds)
|
||||
dl->vgd.pv_act = act;
|
||||
}
|
||||
}
|
||||
|
||||
int export_vg_number(struct format_instance *fid, struct list *pvds,
|
||||
const char *vg_name, struct dev_filter *filter)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct disk_list *dl;
|
||||
int vg_num;
|
||||
|
||||
@ -723,10 +695,8 @@ int export_vg_number(struct format_instance *fid, struct list *pvds,
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate(pvdh, pvds) {
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
list_iterate_items(dl, pvds)
|
||||
dl->vgd.vg_number = vg_num;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
struct hash_table *maps = hash_create(32);
|
||||
struct list *llh;
|
||||
struct lv_list *ll;
|
||||
struct lv_map *lvm;
|
||||
|
||||
@ -58,8 +57,7 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate(llh, &vg->lvs) {
|
||||
ll = list_item(llh, struct lv_list);
|
||||
list_iterate_items(ll, &vg->lvs) {
|
||||
if (ll->lv->status & SNAPSHOT)
|
||||
continue;
|
||||
|
||||
@ -91,13 +89,12 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
|
||||
static int _fill_lv_array(struct lv_map **lvs,
|
||||
struct hash_table *maps, struct disk_list *dl)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct lvd_list *ll;
|
||||
struct lv_map *lvm;
|
||||
|
||||
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, '/')
|
||||
+ 1))) {
|
||||
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,
|
||||
struct list *pvds)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct disk_list *dl;
|
||||
struct physical_volume *pv;
|
||||
struct lv_map *lvms[MAX_LV], *lvm;
|
||||
struct pe_disk *e;
|
||||
uint32_t i, lv_num, le;
|
||||
|
||||
list_iterate(pvdh, pvds) {
|
||||
dl = list_item(pvdh, struct disk_list);
|
||||
list_iterate_items(dl, pvds) {
|
||||
pv = find_pv(vg, dl->dev);
|
||||
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));
|
||||
|
||||
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.");
|
||||
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,
|
||||
lvm->stripes * le,
|
||||
lvm->stripes * area_len,
|
||||
0, lvm->stripe_size, lvm->stripes,
|
||||
area_len, 0, 0))) {
|
||||
0, lvm->stripe_size, NULL,
|
||||
lvm->stripes,
|
||||
area_len, 0, 0, 0))) {
|
||||
log_error("Failed to allocate striped segment.");
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@
|
||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
const char *candidate_vg, int *result)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct list all_pvs;
|
||||
struct disk_list *dl;
|
||||
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));
|
||||
|
||||
list_iterate(pvh, &all_pvs) {
|
||||
dl = list_item(pvh, struct disk_list);
|
||||
list_iterate_items(dl, &all_pvs) {
|
||||
if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
|
||||
continue;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct pool_list *pl;
|
||||
|
||||
list_iterate(pvdh, head) {
|
||||
pl = list_item(pvdh, struct pool_list);
|
||||
|
||||
list_iterate_items(pl, head) {
|
||||
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
|
||||
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",
|
||||
uuid, dev_name(data->dev));
|
||||
list_del(pvdh);
|
||||
list_del(&pl->list);
|
||||
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,
|
||||
uint32_t *devcount)
|
||||
{
|
||||
|
||||
struct list *vgih = NULL;
|
||||
struct device *dev;
|
||||
struct pool_list *pl = NULL;
|
||||
struct pool *tmpmem = NULL;
|
||||
struct lvmcache_info *info;
|
||||
struct pool_list *pl;
|
||||
struct pool *tmpmem;
|
||||
|
||||
uint32_t sp_count = 0;
|
||||
uint32_t *sp_devs = NULL;
|
||||
@ -264,16 +259,16 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate(vgih, &vginfo->infos) {
|
||||
dev = list_item(vgih, struct lvmcache_info)->dev;
|
||||
if (dev &&
|
||||
!(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
if (info->dev &&
|
||||
!(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
|
||||
break;
|
||||
/*
|
||||
* We need to keep track of the total expected number
|
||||
* of devices per subpool
|
||||
*/
|
||||
if (!sp_count) {
|
||||
/* FIXME pl left uninitialised if !info->dev */
|
||||
sp_count = pl->pd.pl_subpools;
|
||||
if (!(sp_devs =
|
||||
pool_zalloc(tmpmem,
|
||||
@ -298,9 +293,8 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
||||
}
|
||||
|
||||
*devcount = 0;
|
||||
for (i = 0; i < sp_count; i++) {
|
||||
for (i = 0; i < sp_count; i++)
|
||||
*devcount += sp_devs[i];
|
||||
}
|
||||
|
||||
pool_destroy(tmpmem);
|
||||
|
||||
|
@ -33,8 +33,6 @@
|
||||
static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
|
||||
int *sps)
|
||||
{
|
||||
|
||||
struct list *plhs;
|
||||
struct pool_list *pl;
|
||||
struct user_subpool *usp = NULL, *cur_sp = 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
|
||||
* user_pool structure and build the entire thing to check against.
|
||||
*/
|
||||
list_iterate(plhs, pls) {
|
||||
pl = list_item(plhs, struct pool_list);
|
||||
|
||||
list_iterate_items(pl, pls) {
|
||||
*sps = pl->pd.pl_subpools;
|
||||
if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
|
||||
cur_dev->sp_id = cur_sp->id;
|
||||
cur_dev->devid = pl->pd.pl_sp_id;
|
||||
cur_dev->blocks = pl->pd.pl_blocks;
|
||||
cur_dev->pv = pl->pv;
|
||||
cur_dev->initialized = 1;
|
||||
|
||||
}
|
||||
|
||||
return usp;
|
||||
|
@ -30,12 +30,9 @@
|
||||
|
||||
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
|
||||
{
|
||||
struct list *plhs;
|
||||
struct pool_list *pl;
|
||||
|
||||
list_iterate(plhs, pls) {
|
||||
pl = list_item(plhs, struct pool_list);
|
||||
|
||||
list_iterate_items(pl, pls) {
|
||||
vg->extent_count +=
|
||||
((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)
|
||||
{
|
||||
struct pool_list *pl;
|
||||
struct list *plhs;
|
||||
struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
|
||||
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->tags);
|
||||
|
||||
list_iterate(plhs, pls) {
|
||||
pl = list_item(plhs, struct pool_list);
|
||||
|
||||
list_iterate_items(pl, pls) {
|
||||
lv->size += pl->pd.pl_blocks;
|
||||
|
||||
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 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)))) {
|
||||
log_error("Unable to allocate pv list structure");
|
||||
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_start = POOL_PE_START;
|
||||
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->segments);
|
||||
@ -230,8 +221,8 @@ static int _add_stripe_seg(struct pool *mem,
|
||||
|
||||
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
|
||||
area_len * usp->num_devs, 0,
|
||||
usp->striping, usp->num_devs, area_len,
|
||||
0, 0))) {
|
||||
usp->striping, NULL, usp->num_devs,
|
||||
area_len, 0, 0, 0))) {
|
||||
log_error("Unable to allocate striped lv_segment structure");
|
||||
return 0;
|
||||
}
|
||||
@ -271,7 +262,8 @@ static int _add_linear_seg(struct pool *mem,
|
||||
|
||||
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
|
||||
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 "
|
||||
"structure");
|
||||
return 0;
|
||||
@ -295,15 +287,12 @@ static int _add_linear_seg(struct pool *mem,
|
||||
int import_pool_segments(struct list *lvs, struct pool *mem,
|
||||
struct user_subpool *usp, int subpools)
|
||||
{
|
||||
|
||||
struct list *lvhs;
|
||||
struct lv_list *lvl;
|
||||
struct logical_volume *lv;
|
||||
uint32_t le_cur = 0;
|
||||
int i;
|
||||
|
||||
list_iterate(lvhs, lvs) {
|
||||
lvl = list_item(lvhs, struct lv_list);
|
||||
list_iterate_items(lvl, lvs) {
|
||||
lv = lvl->lv;
|
||||
|
||||
if (lv->status & SNAPSHOT)
|
||||
@ -325,5 +314,4 @@ int import_pool_segments(struct list *lvs, struct pool *mem,
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
struct list *bh;
|
||||
struct archive_file *bf = NULL;
|
||||
|
||||
if (list_empty(head)) {
|
||||
@ -99,11 +98,9 @@ static void _insert_file(struct list *head, struct archive_file *b)
|
||||
return;
|
||||
}
|
||||
|
||||
/* index increases through list */
|
||||
list_iterate(bh, head) {
|
||||
bf = list_item(bh, struct archive_file);
|
||||
|
||||
if (bf->index > b->index) {
|
||||
/* index reduces through list */
|
||||
list_iterate_items(bf, head) {
|
||||
if (b->index > bf->index) {
|
||||
list_add(&bf->list, &b->list);
|
||||
return;
|
||||
}
|
||||
@ -200,7 +197,6 @@ static struct list *_scan_archive(struct pool *mem,
|
||||
static void _remove_expired(struct list *archives, uint32_t archives_size,
|
||||
uint32_t retain_days, uint32_t min_archive)
|
||||
{
|
||||
struct list *bh;
|
||||
struct archive_file *bf;
|
||||
struct stat sb;
|
||||
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;
|
||||
|
||||
/* Assume list is ordered oldest first (by index) */
|
||||
list_iterate(bh, archives) {
|
||||
bf = list_item(bh, struct archive_file);
|
||||
|
||||
list_iterate_items(bf, archives) {
|
||||
/* Get the mtime of the file and unlink if too old */
|
||||
if (stat(bf->path, &sb)) {
|
||||
log_sys_error("stat", bf->path);
|
||||
@ -280,7 +274,7 @@ int archive_vg(struct volume_group *vg,
|
||||
if (list_empty(archives))
|
||||
ix = 0;
|
||||
else {
|
||||
last = list_item(archives->p, struct archive_file);
|
||||
last = list_item(list_first(archives), struct archive_file);
|
||||
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)
|
||||
{
|
||||
struct list *archives, *ah;
|
||||
struct list *archives;
|
||||
struct archive_file *af;
|
||||
|
||||
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))
|
||||
log_print("No archives found in %s.", dir);
|
||||
|
||||
list_iterate(ah, archives) {
|
||||
af = list_item(ah, struct archive_file);
|
||||
|
||||
list_iterate_back_items(af, archives)
|
||||
_display_archive(cmd, af);
|
||||
}
|
||||
|
||||
pool_free(cmd->mem, archives);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
struct physical_volume *pv;
|
||||
char buffer[4096];
|
||||
const char *name;
|
||||
@ -338,8 +338,8 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
outf(f, "physical_volumes {");
|
||||
_inc_indent(f);
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
pv = pvl->pv;
|
||||
|
||||
if (!(name = _get_pv_name(f, pv))) {
|
||||
stack;
|
||||
@ -442,22 +442,21 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
_inc_indent(f);
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
switch (seg->area[s].type) {
|
||||
switch (seg_type(seg, s)) {
|
||||
case AREA_PV:
|
||||
if (!(name = _get_pv_name(f, seg->area[s].u.pv.pvseg->
|
||||
pv))) {
|
||||
if (!(name = _get_pv_name(f, seg_pv(seg, s)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
outf(f, "\"%s\", %u%s", name,
|
||||
seg->area[s].u.pv.pvseg->pe,
|
||||
seg_pe(seg, s),
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
break;
|
||||
case AREA_LV:
|
||||
outf(f, "\"%s\", %u%s",
|
||||
seg->area[s].u.lv.lv->name,
|
||||
seg->area[s].u.lv.le,
|
||||
seg_lv(seg, s)->name,
|
||||
seg_le(seg, s),
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
}
|
||||
}
|
||||
@ -467,24 +466,68 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
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;
|
||||
struct lv_segment *seg;
|
||||
char buffer[4096];
|
||||
int seg_count;
|
||||
|
||||
list_iterate(segh, &lv->segments)
|
||||
r++;
|
||||
f->nl(f);
|
||||
outf(f, "%s {", lv->name);
|
||||
_inc_indent(f);
|
||||
|
||||
return r;
|
||||
/* FIXME: Write full lvid */
|
||||
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!list_empty(&lv->tags)) {
|
||||
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
if (lv->alloc != ALLOC_INHERIT)
|
||||
outf(f, "allocation_policy = \"%s\"",
|
||||
get_alloc_string(lv->alloc));
|
||||
|
||||
if (lv->read_ahead)
|
||||
outf(f, "read_ahead = %u", lv->read_ahead);
|
||||
if (lv->major >= 0)
|
||||
outf(f, "major = %d", lv->major);
|
||||
if (lv->minor >= 0)
|
||||
outf(f, "minor = %d", lv->minor);
|
||||
outf(f, "segment_count = %u", list_size(&lv->segments));
|
||||
f->nl(f);
|
||||
|
||||
seg_count = 1;
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (!_print_segment(f, lv->vg, seg_count++, seg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
outf(f, "}");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *seg;
|
||||
char buffer[4096];
|
||||
int seg_count;
|
||||
struct lv_list *lvl;
|
||||
|
||||
/*
|
||||
* Don't bother with an lv section if there are no lvs.
|
||||
@ -495,58 +538,25 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
outf(f, "logical_volumes {");
|
||||
_inc_indent(f);
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
|
||||
f->nl(f);
|
||||
outf(f, "%s {", lv->name);
|
||||
_inc_indent(f);
|
||||
|
||||
/* FIXME: Write full lvid */
|
||||
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if ((lvl->lv->status & VISIBLE_LV))
|
||||
continue;
|
||||
if (!_print_lv(f, lvl->lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!list_empty(&lv->tags)) {
|
||||
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
if (lv->alloc != ALLOC_INHERIT)
|
||||
outf(f, "allocation_policy = \"%s\"",
|
||||
get_alloc_string(lv->alloc));
|
||||
|
||||
if (lv->read_ahead)
|
||||
outf(f, "read_ahead = %u", lv->read_ahead);
|
||||
if (lv->major >= 0)
|
||||
outf(f, "major = %d", lv->major);
|
||||
if (lv->minor >= 0)
|
||||
outf(f, "minor = %d", lv->minor);
|
||||
outf(f, "segment_count = %u", _count_segments(lv));
|
||||
f->nl(f);
|
||||
|
||||
seg_count = 1;
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (!_print_segment(f, vg, seg_count++, seg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
outf(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)
|
||||
{
|
||||
int count = 0;
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
struct physical_volume *pv;
|
||||
char buffer[32], *name;
|
||||
|
||||
@ -577,8 +587,8 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
pv = pvl->pv;
|
||||
|
||||
/* FIXME But skip if there's already an LV called pv%d ! */
|
||||
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
|
||||
|
@ -52,6 +52,7 @@ static struct flag _lv_flags[] = {
|
||||
{VISIBLE_LV, "VISIBLE"},
|
||||
{PVMOVE, "PVMOVE"},
|
||||
{LOCKED, "LOCKED"},
|
||||
{MIRROR_LOG, NULL},
|
||||
{MIRRORED, NULL},
|
||||
{VIRTUAL, NULL},
|
||||
{SNAPSHOT, NULL},
|
||||
|
@ -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 raw_locn *rlocn;
|
||||
struct mda_header *mdah;
|
||||
struct physical_volume *pv;
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
int r = 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;
|
||||
|
||||
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
if (pv->dev == mdac->area.dev) {
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (pvl->pv->dev == mdac->area.dev) {
|
||||
found = 1;
|
||||
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_header *mdah;
|
||||
struct raw_locn *rlocn;
|
||||
struct physical_volume *pv;
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
int r = 0;
|
||||
int found = 0;
|
||||
|
||||
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
if (pv->dev == mdac->area.dev) {
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (pvl->pv->dev == mdac->area.dev) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@ -518,14 +514,12 @@ static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
|
||||
struct physical_volume *pv;
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
int found = 0;
|
||||
|
||||
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
if (pv->dev == mdac->area.dev) {
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (pvl->pv->dev == mdac->area.dev) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@ -784,7 +778,7 @@ static int _scan_file(const struct format_type *fmt)
|
||||
{
|
||||
struct dirent *dirent;
|
||||
struct dir_list *dl;
|
||||
struct list *dlh, *dir_list;
|
||||
struct list *dir_list;
|
||||
char *tmp;
|
||||
DIR *d;
|
||||
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;
|
||||
|
||||
list_iterate(dlh, dir_list) {
|
||||
dl = list_item(dlh, struct dir_list);
|
||||
list_iterate_items(dl, dir_list) {
|
||||
if (!(d = opendir(dl->dir))) {
|
||||
log_sys_error("opendir", dl->dir);
|
||||
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)
|
||||
{
|
||||
struct raw_list *rl;
|
||||
struct list *rlh, *raw_list;
|
||||
struct list *raw_list;
|
||||
char vgnamebuf[NAME_LEN + 2];
|
||||
struct volume_group *vg;
|
||||
struct format_instance fid;
|
||||
@ -893,9 +886,7 @@ static int _scan_raw(const struct format_type *fmt)
|
||||
fid.fmt = fmt;
|
||||
list_init(&fid.metadata_areas);
|
||||
|
||||
list_iterate(rlh, raw_list) {
|
||||
rl = list_item(rlh, struct raw_list);
|
||||
|
||||
list_iterate_items(rl, raw_list) {
|
||||
/* FIXME We're reading mdah twice here... */
|
||||
if (vgname_from_mda(fmt, &rl->dev_area, 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 start2, mda_size2; /* Second area - end of disk */
|
||||
uint64_t wipe_size = 8 << SECTOR_SHIFT;
|
||||
size_t pagesize = getpagesize();
|
||||
|
||||
if (!pvmetadatacopies) {
|
||||
/* 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 */
|
||||
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! */
|
||||
if (mda_size1 > disk_size) {
|
||||
log_print("Warning: metadata area fills disk %s",
|
||||
dev_name(pv->dev));
|
||||
if (start1 + mda_size1 > disk_size) {
|
||||
log_print("Warning: metadata area fills disk leaving no "
|
||||
"space for data on %s.", dev_name(pv->dev));
|
||||
/* Leave some free space for rounding */
|
||||
/* Avoid empty data area as could cause tools problems */
|
||||
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 lvmcache_info *info;
|
||||
struct mda_context *mdac;
|
||||
struct list *mdash;
|
||||
struct metadata_area *mda;
|
||||
char buf[MDA_HEADER_SIZE];
|
||||
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);
|
||||
else
|
||||
list_init(&info->mdas);
|
||||
list_iterate(mdash, mdas) {
|
||||
mda = list_item(mdash, struct metadata_area);
|
||||
list_iterate_items(mda, mdas) {
|
||||
mdac = mda->metadata_locn;
|
||||
log_debug("Creating metadata area on %s at sector %"
|
||||
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
|
||||
* areas that begin before pe_start */
|
||||
pv->pe_start = PE_ALIGN;
|
||||
list_iterate(mdash, &info->mdas) {
|
||||
mda = list_item(mdash, struct metadata_area);
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
if (pv->dev == mdac->area.dev &&
|
||||
(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;
|
||||
}
|
||||
|
||||
list_iterate(mdash, &info->mdas) {
|
||||
mda = list_item(mdash, struct metadata_area);
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = mda->metadata_locn;
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
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)
|
||||
{
|
||||
struct raw_list *rl;
|
||||
struct list *rlh;
|
||||
|
||||
/* Already present? */
|
||||
list_iterate(rlh, raw_list) {
|
||||
rl = list_item(rlh, struct raw_list);
|
||||
list_iterate_items(rl, raw_list) {
|
||||
/* FIXME Check size/overlap consistency too */
|
||||
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)))) {
|
||||
@ -1180,7 +1178,6 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct lvmcache_info *info;
|
||||
struct metadata_area *mda, *mda_new;
|
||||
struct mda_context *mdac, *mdac_new;
|
||||
struct list *mdah, *dah;
|
||||
struct data_area_list *da;
|
||||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
if (!mdas)
|
||||
return 1;
|
||||
|
||||
/* Add copy of mdas to supplied list */
|
||||
list_iterate(mdah, &info->mdas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
if (!(mda_new = pool_alloc(fmt->cmd->mem, sizeof(*mda_new)))) {
|
||||
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 mda_context *mdac, *mdac_new, *mdac2;
|
||||
struct list *pvmdas, *pvmdash, *mdash;
|
||||
struct list *pvmdas;
|
||||
struct lvmcache_info *info;
|
||||
int found;
|
||||
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 */
|
||||
if ((info = info_from_pvid(pv->dev->pvid))) {
|
||||
pvmdas = &info->mdas;
|
||||
list_iterate(pvmdash, pvmdas) {
|
||||
mda = list_item(pvmdash, struct metadata_area);
|
||||
list_iterate_items(mda, pvmdas) {
|
||||
mdac =
|
||||
(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 */
|
||||
found = 0;
|
||||
list_iterate(mdash, mdas) {
|
||||
mda2 =
|
||||
list_item(mdash,
|
||||
struct metadata_area);
|
||||
list_iterate_items(mda2, mdas) {
|
||||
if (mda2->ops !=
|
||||
&_metadata_text_raw_ops) continue;
|
||||
mdac2 =
|
||||
@ -1416,9 +1407,10 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
struct mda_context *mdac, *mdac_new;
|
||||
struct dir_list *dl;
|
||||
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];
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
|
||||
log_error("Couldn't allocate format instance object.");
|
||||
@ -1440,8 +1432,7 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
} else {
|
||||
dir_list = &((struct mda_lists *) fmt->private)->dirs;
|
||||
|
||||
list_iterate(dlh, dir_list) {
|
||||
dl = list_item(dlh, struct dir_list);
|
||||
list_iterate_items(dl, dir_list) {
|
||||
if (lvm_snprintf(path, PATH_MAX, "%s/%s",
|
||||
dl->dir, vgname) < 0) {
|
||||
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;
|
||||
|
||||
list_iterate(rlh, raw_list) {
|
||||
rl = list_item(rlh, struct raw_list);
|
||||
|
||||
list_iterate_items(rl, raw_list) {
|
||||
/* FIXME Cache this; rescan below if some missing */
|
||||
if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
|
||||
continue;
|
||||
@ -1491,10 +1480,9 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
list_iterate(infoh, &vginfo->infos) {
|
||||
mdas = &(list_item(infoh, struct lvmcache_info)->mdas);
|
||||
list_iterate(mdash, mdas) {
|
||||
mda = list_item(mdash, struct metadata_area);
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
mdas = &info->mdas;
|
||||
list_iterate_items(mda, mdas) {
|
||||
mdac =
|
||||
(struct mda_context *) mda->metadata_locn;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
struct list *segh;
|
||||
struct lv_segment *comp;
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
comp = list_item(segh, struct lv_segment);
|
||||
|
||||
list_iterate_items(comp, &lv->segments) {
|
||||
if (comp->le > seg->le) {
|
||||
list_add(&comp->list, &seg->list);
|
||||
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,
|
||||
extent_count, 0, 0, area_count,
|
||||
extent_count, 0, 0))) {
|
||||
extent_count, 0, 0, NULL, area_count,
|
||||
extent_count, 0, 0, 0))) {
|
||||
log_error("Segment allocation failed");
|
||||
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.
|
||||
*/
|
||||
pv->pe_alloc_count += seg->area_len;
|
||||
seg->lv->vg->free_count -= seg->area_len;
|
||||
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
|
||||
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.
|
||||
*/
|
||||
if (!lv_check_segments(lv)) {
|
||||
if (!check_lv_segments(lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
@ -81,5 +81,6 @@ struct mda_context {
|
||||
#define FMTT_VERSION 1
|
||||
#define MDA_HEADER_SIZE 512
|
||||
#define LVM2_LABEL "LVM2 001"
|
||||
#define MDA_SIZE_MIN (8 * getpagesize())
|
||||
|
||||
#endif
|
||||
|
@ -39,7 +39,6 @@ static int _write(struct label *label, char *buf)
|
||||
struct pv_header *pvhdr;
|
||||
struct lvmcache_info *info;
|
||||
struct disk_locn *pvh_dlocn_xl;
|
||||
struct list *mdash, *dash;
|
||||
struct metadata_area *mda;
|
||||
struct mda_context *mdac;
|
||||
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];
|
||||
|
||||
/* List of data areas (holding PEs) */
|
||||
list_iterate(dash, &info->das) {
|
||||
da = list_item(dash, struct data_area_list);
|
||||
|
||||
list_iterate_items(da, &info->das) {
|
||||
pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
|
||||
pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
|
||||
pvh_dlocn_xl++;
|
||||
@ -71,8 +68,7 @@ static int _write(struct label *label, char *buf)
|
||||
pvh_dlocn_xl++;
|
||||
|
||||
/* List of metadata area header locations */
|
||||
list_iterate(mdash, &info->mdas) {
|
||||
mda = list_item(mdash, struct metadata_area);
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
|
||||
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 disk_locn *dlocn_xl;
|
||||
uint64_t offset;
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
char vgnamebuf[NAME_LEN + 2];
|
||||
struct mda_context *mdac;
|
||||
@ -235,8 +230,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
dlocn_xl++;
|
||||
}
|
||||
|
||||
list_iterate(mdah, &info->mdas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
|
||||
sizeof(vgnamebuf))) {
|
||||
|
@ -98,14 +98,11 @@ int label_register_handler(const char *name, struct labeller *handler)
|
||||
|
||||
struct labeller *label_get_handler(const char *name)
|
||||
{
|
||||
struct list *lih;
|
||||
struct labeller_i *li;
|
||||
|
||||
list_iterate(lih, &_labellers) {
|
||||
li = list_item(lih, struct labeller_i);
|
||||
list_iterate_items(li, &_labellers)
|
||||
if (!strcmp(li->name, name))
|
||||
return li->l;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -113,7 +110,6 @@ struct labeller *label_get_handler(const char *name)
|
||||
static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
uint64_t *label_sector)
|
||||
{
|
||||
struct list *lih;
|
||||
struct labeller_i *li;
|
||||
struct labeller *r = NULL;
|
||||
struct label_header *lh;
|
||||
@ -166,8 +162,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
continue;
|
||||
}
|
||||
|
||||
list_iterate(lih, &_labellers) {
|
||||
li = list_item(lih, struct labeller_i);
|
||||
list_iterate_items(li, &_labellers) {
|
||||
if (li->l->ops->can_handle(li->l, (char *) lh, sector)) {
|
||||
log_very_verbose("%s: %s label detected",
|
||||
dev_name(dev), li->name);
|
||||
@ -208,7 +203,6 @@ int label_remove(struct device *dev)
|
||||
int r = 1;
|
||||
uint64_t sector;
|
||||
int wipe;
|
||||
struct list *lih;
|
||||
struct labeller_i *li;
|
||||
struct label_header *lh;
|
||||
|
||||
@ -244,8 +238,7 @@ int label_remove(struct device *dev)
|
||||
if (xlate64(lh->sector_xl) == sector)
|
||||
wipe = 1;
|
||||
} else {
|
||||
list_iterate(lih, &_labellers) {
|
||||
li = list_item(lih, struct labeller_i);
|
||||
list_iterate_items(li, &_labellers) {
|
||||
if (li->l->ops->can_handle(li->l, (char *) lh,
|
||||
sector)) {
|
||||
wipe = 1;
|
||||
|
@ -265,13 +265,10 @@ int lock_vol(struct cmd_context *cmd, const char *vol, int flags)
|
||||
/* Unlock list of LVs */
|
||||
int resume_lvs(struct cmd_context *cmd, struct list *lvs)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
}
|
||||
list_iterate_items(lvl, lvs)
|
||||
resume_lv(cmd, lvl->lv->lvid.s);
|
||||
|
||||
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)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (!suspend_lv(cmd, lv->lvid.s)) {
|
||||
log_error("Failed to suspend %s", lv->name);
|
||||
list_uniterate(lvh, lvs, lvh) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
list_iterate_items(lvl, lvs) {
|
||||
if (!suspend_lv(cmd, lvl->lv->lvid.s)) {
|
||||
log_error("Failed to suspend %s", lvl->lv->name);
|
||||
list_uniterate(lvh, lvs, &lvl->list) {
|
||||
lvl = list_item(lvh, struct lv_list);
|
||||
resume_lv(cmd, lvl->lv->lvid.s);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (!activate_lv_excl(cmd, lv->lvid.s)) {
|
||||
log_error("Failed to activate %s", lv->name);
|
||||
list_uniterate(lvh, lvs, lvh) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
activate_lv(cmd, lv->lvid.s);
|
||||
list_iterate_items(lvl, lvs) {
|
||||
if (!activate_lv_excl(cmd, lvl->lv->lvid.s)) {
|
||||
log_error("Failed to activate %s", lvl->lv->name);
|
||||
list_uniterate(lvh, lvs, &lvl->list) {
|
||||
lvl = list_item(lvh, struct lv_list);
|
||||
activate_lv(cmd, lvl->lv->lvid.s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -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_external_locking(struct locking_type *locking, struct config_tree *cf);
|
||||
|
||||
int init_cluster_locking(struct locking_type *locking, struct config_tree *cf);
|
||||
|
@ -22,17 +22,49 @@ struct lv_segment *alloc_lv_segment(struct pool *mem,
|
||||
uint32_t le, uint32_t len,
|
||||
uint32_t status,
|
||||
uint32_t stripe_size,
|
||||
struct logical_volume *log_lv,
|
||||
uint32_t area_count,
|
||||
uint32_t area_len,
|
||||
uint32_t chunk_size,
|
||||
uint32_t region_size,
|
||||
uint32_t extents_copied);
|
||||
|
||||
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,
|
||||
struct physical_volume *pv, uint32_t pe);
|
||||
void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
|
||||
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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
*/
|
||||
int lv_check_segments(struct logical_volume *lv)
|
||||
int check_lv_segments(struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
uint32_t le = 0;
|
||||
unsigned seg_count = 0;
|
||||
int r = 1;
|
||||
uint32_t area_multiplier, s;
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
seg_count++;
|
||||
@ -70,13 +72,58 @@ int lv_check_segments(struct logical_volume *lv)
|
||||
log_error("LV %s invalid: segment %u should begin at "
|
||||
"LE %" PRIu32 " (found %" PRIu32 ").",
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
seg->lv, seg->le, seg->len,
|
||||
seg->status, seg->stripe_size,
|
||||
seg->log_lv,
|
||||
seg->area_count, seg->area_len,
|
||||
seg->chunk_size,
|
||||
seg->chunk_size, seg->region_size,
|
||||
seg->extents_copied))) {
|
||||
log_error("Couldn't allocate cloned LV segment.");
|
||||
return 0;
|
||||
@ -128,24 +176,24 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
|
||||
/* Adjust the PV mapping */
|
||||
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 */
|
||||
switch (seg->area[s].type) {
|
||||
switch (seg_type(seg, s)) {
|
||||
case AREA_LV:
|
||||
split_seg->area[s].u.lv.lv = seg->area[s].u.lv.lv;
|
||||
split_seg->area[s].u.lv.le =
|
||||
seg->area[s].u.lv.le + seg->area_len;
|
||||
seg_lv(split_seg, s) = seg_lv(seg, s);
|
||||
seg_le(split_seg, s) =
|
||||
seg_le(seg, s) + seg->area_len;
|
||||
log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name,
|
||||
seg->le, s, le, seg->area[s].u.lv.lv->name,
|
||||
split_seg->area[s].u.lv.le);
|
||||
seg->le, s, le, seg_lv(seg, s)->name,
|
||||
seg_le(split_seg, s));
|
||||
break;
|
||||
|
||||
case AREA_PV:
|
||||
if (!assign_peg_to_lvseg(seg->area[s].u.pv.pvseg->pv,
|
||||
seg->area[s].u.pv.pvseg->pe +
|
||||
if (!assign_peg_to_lvseg(seg_pv(seg, s),
|
||||
seg_pe(seg, s) +
|
||||
seg->area_len,
|
||||
seg->area[s].u.pv.pvseg->len -
|
||||
seg_pvseg(seg, s)->len -
|
||||
seg->area_len,
|
||||
split_seg, s)) {
|
||||
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,
|
||||
seg->le, s, le,
|
||||
dev_name(seg->area[s].u.pv.pvseg->pv->dev),
|
||||
split_seg->area[s].u.pv.pvseg->pe);
|
||||
dev_name(seg_dev(seg, s)),
|
||||
seg_pe(split_seg, s));
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Unrecognised segment type %u",
|
||||
seg->area[s].type);
|
||||
seg_type(seg, s));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
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",
|
||||
vg_name);
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pvl = list_item(pvh, struct pv_list);
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (id_equal(&pvl->pv->id, (const struct id *) id)) {
|
||||
if (!_copy_pv(pv, pvl->pv)) {
|
||||
stack;
|
||||
@ -171,19 +169,17 @@ int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
|
||||
const char *new_name)
|
||||
{
|
||||
struct pool *mem = cmd->mem;
|
||||
struct physical_volume *pv;
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
|
||||
if (!(vg->name = pool_strdup(mem, new_name))) {
|
||||
log_error("vg->name allocation failed for '%s'", new_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
if (!(pv->vg_name = pool_strdup(mem, new_name))) {
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!(pvl->pv->vg_name = pool_strdup(mem, new_name))) {
|
||||
log_error("pv->vg_name allocation failed for '%s'",
|
||||
dev_name(pv->dev));
|
||||
dev_name(pvl->pv->dev));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -441,10 +437,10 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
|
||||
/* foreach area */
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
switch (seg->area[s].type) {
|
||||
switch (seg_type(seg, s)) {
|
||||
case AREA_PV:
|
||||
if (!_recalc_extents
|
||||
(&seg->area[s].u.pv.pvseg->pe,
|
||||
(&seg_pe(seg, s),
|
||||
lv->name,
|
||||
" pvseg start", old_size,
|
||||
new_size)) {
|
||||
@ -452,7 +448,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
if (!_recalc_extents
|
||||
(&seg->area[s].u.pv.pvseg->len,
|
||||
(&seg_pvseg(seg, s)->len,
|
||||
lv->name,
|
||||
" pvseg length", old_size,
|
||||
new_size)) {
|
||||
@ -462,7 +458,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
break;
|
||||
case AREA_LV:
|
||||
if (!_recalc_extents
|
||||
(&seg->area[s].u.lv.le, lv->name,
|
||||
(&seg_le(seg, s), lv->name,
|
||||
" area start", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
@ -471,7 +467,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
break;
|
||||
default:
|
||||
log_error("Unrecognised segment type "
|
||||
"%u", seg->area[s].type);
|
||||
"%u", seg_type(seg, s));
|
||||
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 list *pvh;
|
||||
struct pv_list *pvl;
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pvl = list_item(pvh, struct pv_list);
|
||||
list_iterate_items(pvl, &vg->pvs)
|
||||
if (pvl->pv->dev == dev_cache_get(pv_name, vg->cmd->filter))
|
||||
return pvl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (pv == list_item(pvh, struct pv_list)->pv)
|
||||
list_iterate_items(pvl, &vg->pvs)
|
||||
if (pv == pvl->pv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 id *id)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct pv_list *pvl;
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pvl = list_item(pvh, struct pv_list);
|
||||
list_iterate_items(pvl, &vg->pvs)
|
||||
if (id_equal(&pvl->pv->id, id))
|
||||
return pvl->pv;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct lv_list *lvl;
|
||||
const char *ptr;
|
||||
|
||||
@ -614,11 +602,9 @@ struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
|
||||
else
|
||||
ptr = lv_name;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lvl = list_item(lvh, struct lv_list);
|
||||
list_iterate_items(lvl, &vg->lvs)
|
||||
if (!strcmp(lvl->lv->name, ptr))
|
||||
return lvl;
|
||||
}
|
||||
|
||||
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 list *pvh;
|
||||
struct physical_volume *pv;
|
||||
struct pv_list *pvl;
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
list_iterate_items(pvl, &vg->pvs)
|
||||
if (dev == pvl->pv->dev)
|
||||
return pvl->pv;
|
||||
|
||||
if (dev == pv->dev)
|
||||
return pv;
|
||||
}
|
||||
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 */
|
||||
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
|
||||
{
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments)
|
||||
if (le >= seg->le && le < seg->le + seg->len)
|
||||
return seg;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -693,23 +673,20 @@ struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe)
|
||||
{
|
||||
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)
|
||||
return peg;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int vg_remove(struct volume_group *vg)
|
||||
{
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
|
||||
/* FIXME Improve recovery situation? */
|
||||
/* Remove each copy of the metadata */
|
||||
list_iterate(mdah, &vg->fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
if (mda->ops->vg_remove &&
|
||||
!mda->ops->vg_remove(vg->fid, vg, mda)) {
|
||||
stack;
|
||||
@ -726,8 +703,9 @@ int vg_remove(struct volume_group *vg)
|
||||
*/
|
||||
int vg_write(struct volume_group *vg)
|
||||
{
|
||||
struct list *mdah, *mdah2;
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
struct lv_list *lvl;
|
||||
|
||||
if (!check_pv_segments(vg)) {
|
||||
log_error("Internal error: PV segments corrupted in %s.",
|
||||
@ -735,6 +713,14 @@ int vg_write(struct volume_group *vg)
|
||||
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) {
|
||||
log_error("Cannot change metadata for partial volume group %s",
|
||||
vg->name);
|
||||
@ -749,14 +735,13 @@ int vg_write(struct volume_group *vg)
|
||||
vg->seqno++;
|
||||
|
||||
/* Write to each copy of the metadata area */
|
||||
list_iterate(mdah, &vg->fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
if (!mda->ops->vg_write) {
|
||||
log_error("Format does not support writing volume"
|
||||
"group metadata areas");
|
||||
/* Revert */
|
||||
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
|
||||
mda = list_item(mdah2, struct metadata_area);
|
||||
list_uniterate(mdah, &vg->fid->metadata_areas, &mda->list) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
|
||||
if (mda->ops->vg_revert &&
|
||||
!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)) {
|
||||
stack;
|
||||
/* Revert */
|
||||
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
|
||||
mda = list_item(mdah2, struct metadata_area);
|
||||
list_uniterate(mdah, &vg->fid->metadata_areas, &mda->list) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
|
||||
if (mda->ops->vg_revert &&
|
||||
!mda->ops->vg_revert(vg->fid, vg, mda)) {
|
||||
stack;
|
||||
@ -780,14 +766,12 @@ int vg_write(struct volume_group *vg)
|
||||
}
|
||||
|
||||
/* Now pre-commit each copy of the new metadata */
|
||||
list_iterate(mdah, &vg->fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
if (mda->ops->vg_precommit &&
|
||||
!mda->ops->vg_precommit(vg->fid, vg, mda)) {
|
||||
stack;
|
||||
/* Revert */
|
||||
list_iterate(mdah2, &vg->fid->metadata_areas) {
|
||||
mda = list_item(mdah2, struct metadata_area);
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
if (mda->ops->vg_revert &&
|
||||
!mda->ops->vg_revert(vg->fid, vg, mda)) {
|
||||
stack;
|
||||
@ -803,14 +787,12 @@ int vg_write(struct volume_group *vg)
|
||||
/* Commit pending changes */
|
||||
int vg_commit(struct volume_group *vg)
|
||||
{
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
int cache_updated = 0;
|
||||
int failed = 0;
|
||||
|
||||
/* Commit to each copy of the metadata area */
|
||||
list_iterate(mdah, &vg->fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
failed = 0;
|
||||
if (mda->ops->vg_commit &&
|
||||
!mda->ops->vg_commit(vg->fid, vg, mda)) {
|
||||
@ -822,7 +804,6 @@ int vg_commit(struct volume_group *vg)
|
||||
lvmcache_update_vg(vg);
|
||||
cache_updated = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
int vg_revert(struct volume_group *vg)
|
||||
{
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
|
||||
list_iterate(mdah, &vg->fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
if (mda->ops->vg_revert &&
|
||||
!mda->ops->vg_revert(vg->fid, vg, mda)) {
|
||||
stack;
|
||||
@ -850,8 +829,7 @@ int vg_revert(struct volume_group *vg)
|
||||
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct list *ih;
|
||||
struct device *dev;
|
||||
struct lvmcache_info *info;
|
||||
struct pv_list *pvl;
|
||||
struct volume_group *vg;
|
||||
struct physical_volume *pv;
|
||||
@ -874,9 +852,8 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate(ih, &vginfo->infos) {
|
||||
dev = list_item(ih, struct lvmcache_info)->dev;
|
||||
if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL, 1))) {
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
if (!(pv = pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
const struct format_type *fmt;
|
||||
struct volume_group *vg, *correct_vg = NULL;
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
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 */
|
||||
list_iterate(mdah, &fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &fid->metadata_areas) {
|
||||
if ((precommitted &&
|
||||
!(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
|
||||
(!precommitted &&
|
||||
@ -993,8 +968,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
/* Ensure contents of all metadata areas match - else recover */
|
||||
list_iterate(mdah, &fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
list_iterate_items(mda, &fid->metadata_areas) {
|
||||
if ((precommitted &&
|
||||
!(vg = mda->ops->vg_read_precommit(fid, vgname,
|
||||
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)
|
||||
{
|
||||
const char *vgname;
|
||||
struct list *vgnames, *slh;
|
||||
struct list *vgnames;
|
||||
struct volume_group *vg;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct str_list *strl;
|
||||
int consistent = 0;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
list_iterate(slh, vgnames) {
|
||||
vgname = list_item(slh, struct str_list)->str;
|
||||
list_iterate_items(strl, vgnames) {
|
||||
vgname = strl->str;
|
||||
if (!vgname || !*vgname)
|
||||
continue; // FIXME Unnecessary?
|
||||
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 str_list *strl;
|
||||
struct list *results;
|
||||
const char *vgname;
|
||||
struct list *pvh, *tmp;
|
||||
struct list *vgnames, *slh;
|
||||
struct list *vgnames;
|
||||
struct volume_group *vg;
|
||||
int consistent = 0;
|
||||
int old_partial;
|
||||
@ -1258,8 +1234,8 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
old_pvmove = pvmove_mode();
|
||||
init_partial(1);
|
||||
init_pvmove(1);
|
||||
list_iterate(slh, vgnames) {
|
||||
vgname = list_item(slh, struct str_list)->str;
|
||||
list_iterate_items(strl, vgnames) {
|
||||
vgname = strl->str;
|
||||
if (!vgname)
|
||||
continue; /* FIXME Unnecessary? */
|
||||
consistent = 0;
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define LOCKED 0x00004000 /* LV */
|
||||
#define MIRRORED 0x00008000 /* LV - internal use only */
|
||||
#define VIRTUAL 0x00010000 /* LV - internal use only */
|
||||
#define MIRROR_LOG 0x00020000 /* LV */
|
||||
|
||||
#define LVM_READ 0x00000100 /* LV VG */
|
||||
#define LVM_WRITE 0x00000200 /* LV VG */
|
||||
@ -228,8 +229,10 @@ struct lv_segment {
|
||||
struct logical_volume *origin;
|
||||
struct logical_volume *cow;
|
||||
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;
|
||||
struct logical_volume *log_lv;
|
||||
|
||||
struct list tags;
|
||||
|
||||
@ -248,6 +251,14 @@ struct lv_segment {
|
||||
} 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 {
|
||||
union lvid lvid;
|
||||
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.
|
||||
*/
|
||||
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
|
||||
|
@ -33,7 +33,6 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
|
||||
alloc_policy_t alloc,
|
||||
struct list *lvs_changed)
|
||||
{
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
struct lv_list *lvl;
|
||||
struct pv_list *pvl;
|
||||
@ -59,16 +58,15 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
/* Split LV segments to match PE ranges */
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->area[s].type != AREA_PV ||
|
||||
seg->area[s].u.pv.pvseg->pv->dev != pvl->pv->dev)
|
||||
if (seg_type(seg, s) != AREA_PV ||
|
||||
seg_dev(seg, s) != pvl->pv->dev)
|
||||
continue;
|
||||
|
||||
/* Do these PEs need moving? */
|
||||
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;
|
||||
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 */
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->area[s].type != AREA_PV ||
|
||||
seg->area[s].u.pv.pvseg->pv->dev != pvl->pv->dev)
|
||||
if (seg_type(seg, s) != AREA_PV ||
|
||||
seg_dev(seg, s) != pvl->pv->dev)
|
||||
continue;
|
||||
|
||||
pe_start = seg->area[s].u.pv.pvseg->pe;
|
||||
pe_start = seg_pe(seg, s);
|
||||
|
||||
/* Do these PEs need moving? */
|
||||
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 "
|
||||
"%s %u len %u", per->start, per_end,
|
||||
dev_name(seg->area[s].u.pv.pvseg->
|
||||
pv->dev),
|
||||
seg->area[s].u.pv.pvseg->pe,
|
||||
dev_name(seg_dev(seg, s)),
|
||||
seg_pe(seg, s),
|
||||
seg->area_len);
|
||||
|
||||
/* 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",
|
||||
dev_name(pvl->pv->dev),
|
||||
seg->area[s].u.pv.pvseg->pe,
|
||||
seg->area[s].u.pv.pvseg->pe +
|
||||
seg_pe(seg, s),
|
||||
seg_pe(seg, s) +
|
||||
seg->area_len - 1,
|
||||
lv->vg->name, lv->name);
|
||||
|
||||
start_le = lv_mirr->le_count;
|
||||
if (!lv_extend(lv_mirr, segtype, 1,
|
||||
seg->area_len, 0u, seg->area_len,
|
||||
seg->area[s].u.pv.pvseg->pv,
|
||||
seg->area[s].u.pv.pvseg->pe,
|
||||
seg_pv(seg, s),
|
||||
seg_pe(seg, s),
|
||||
PVMOVE, allocatable_pvs,
|
||||
alloc)) {
|
||||
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,
|
||||
struct logical_volume *lv_mirr)
|
||||
{
|
||||
struct list *lvh, *segh;
|
||||
struct lv_list *lvl;
|
||||
struct logical_volume *lv1;
|
||||
struct lv_segment *seg, *mir_seg;
|
||||
uint32_t s, c;
|
||||
|
||||
/* Loop through all LVs except the temporary mirror */
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv1 = list_item(lvh, struct lv_list)->lv;
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
lv1 = lvl->lv;
|
||||
if (lv1 == lv_mirr)
|
||||
continue;
|
||||
|
||||
/* Find all segments that point at the temporary mirror */
|
||||
list_iterate(segh, &lv1->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv1->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->area[s].type != AREA_LV ||
|
||||
seg->area[s].u.lv.lv != lv_mirr)
|
||||
if (seg_type(seg, s) != AREA_LV ||
|
||||
seg_lv(seg, s) != lv_mirr)
|
||||
continue;
|
||||
|
||||
/* Find the mirror segment pointed at */
|
||||
if (!(mir_seg = find_seg_by_le(lv_mirr,
|
||||
seg->area[s].
|
||||
u.lv.le))) {
|
||||
seg_le(seg, s)))) {
|
||||
/* FIXME Error message */
|
||||
log_error("No segment found with LE");
|
||||
return 0;
|
||||
@ -210,7 +204,7 @@ int remove_pvmove_mirrors(struct volume_group *vg,
|
||||
/* FIXME Improve error mesg & remove restrcn */
|
||||
if (!seg_is_mirrored(mir_seg) ||
|
||||
!(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_len != seg->area_len) {
|
||||
log_error("Incompatible segments");
|
||||
@ -227,8 +221,8 @@ int remove_pvmove_mirrors(struct volume_group *vg,
|
||||
c = 0;
|
||||
|
||||
if (!set_lv_segment_area_pv(seg, s,
|
||||
mir_seg->area[c].u.pv.pvseg->pv,
|
||||
mir_seg->area[c].u.pv.pvseg->pe)) {
|
||||
seg_pv(mir_seg, c),
|
||||
seg_pe(mir_seg, c))) {
|
||||
stack;
|
||||
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)
|
||||
{
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
|
||||
list_iterate(segh, &lv_mirr->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv_mirr->segments) {
|
||||
if (!seg_is_mirrored(seg))
|
||||
continue;
|
||||
if (seg->area[0].type != AREA_PV)
|
||||
continue;
|
||||
return dev_name(seg->area[0].u.pv.pvseg->pv->dev);
|
||||
return dev_name(seg_dev(seg, 0));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
uint32_t s;
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->area[s].type != AREA_LV)
|
||||
if (seg_type(seg, s) != AREA_LV)
|
||||
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,
|
||||
uint32_t lv_type)
|
||||
{
|
||||
struct list *lvh, *segh;
|
||||
struct lv_list *lvl;
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *seg;
|
||||
|
||||
/* Loop through all LVs */
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
lv = lvl->lv;
|
||||
|
||||
if (!(lv->status & lv_type))
|
||||
continue;
|
||||
|
||||
/* Check segment origins point to pvname */
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (seg->area[0].type != AREA_PV)
|
||||
continue;
|
||||
if (seg->area[0].u.pv.pvseg->pv->dev != dev)
|
||||
if (seg_dev(seg, 0) != dev)
|
||||
continue;
|
||||
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 logical_volume *lv)
|
||||
{
|
||||
struct list *lvh, *segh, *lvs;
|
||||
struct list *lvs;
|
||||
struct logical_volume *lv1;
|
||||
struct lv_list *lvl;
|
||||
struct lv_list *lvl, *lvl1;
|
||||
struct lv_segment *seg;
|
||||
uint32_t s;
|
||||
|
||||
@ -352,17 +341,16 @@ struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
|
||||
list_init(lvs);
|
||||
|
||||
/* Loop through all LVs except the one supplied */
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv1 = list_item(lvh, struct lv_list)->lv;
|
||||
list_iterate_items(lvl1, &vg->lvs) {
|
||||
lv1 = lvl1->lv;
|
||||
if (lv1 == lv)
|
||||
continue;
|
||||
|
||||
/* Find whether any segment points at the supplied LV */
|
||||
list_iterate(segh, &lv1->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv1->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->area[s].type != AREA_LV ||
|
||||
seg->area[s].u.lv.lv != lv)
|
||||
if (seg_type(seg, s) != AREA_LV ||
|
||||
seg_lv(seg, s) != lv)
|
||||
continue;
|
||||
if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
|
||||
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)
|
||||
{
|
||||
uint32_t numerator = 0u, denominator = 0u;
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
|
||||
list_iterate(segh, &lv_mirr->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
|
||||
list_iterate_items(seg, &lv_mirr->segments) {
|
||||
denominator += seg->area_len;
|
||||
|
||||
if (seg_is_mirrored(seg))
|
||||
|
@ -22,7 +22,7 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv, uint32_t pe,
|
||||
struct lv_segment *seg,
|
||||
uint32_t area_num);
|
||||
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);
|
||||
void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2);
|
||||
|
||||
|
@ -165,9 +165,11 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv,
|
||||
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->lv_area = 0;
|
||||
|
||||
@ -176,7 +178,7 @@ int release_pv_segment(struct pv_segment *peg, uint32_t new_area_len)
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
@ -203,13 +205,16 @@ int check_pv_segments(struct volume_group *vg)
|
||||
struct pv_list *pvl;
|
||||
struct pv_segment *peg;
|
||||
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;
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
pv = pvl->pv;
|
||||
segno = 0;
|
||||
start_pe = 0;
|
||||
alloced = 0;
|
||||
pv_count++;
|
||||
|
||||
list_iterate_items(peg, &pv->segments) {
|
||||
s = peg->lv_area;
|
||||
@ -221,30 +226,63 @@ int check_pv_segments(struct volume_group *vg)
|
||||
peg->lvseg ? peg->lvseg->le : 0, s);
|
||||
/* FIXME Add details here on failure instead */
|
||||
if (start_pe != peg->pe) {
|
||||
log_debug("Gap in pvsegs: %u, %u",
|
||||
log_error("Gap in pvsegs: %u, %u",
|
||||
start_pe, peg->pe);
|
||||
ret = 0;
|
||||
}
|
||||
if (peg->lvseg) {
|
||||
if (peg->lvseg->area[s].type != AREA_PV) {
|
||||
log_debug("Wrong lvseg area type");
|
||||
if (seg_type(peg->lvseg, s) != AREA_PV) {
|
||||
log_error("Wrong lvseg area type");
|
||||
ret = 0;
|
||||
}
|
||||
if (peg->lvseg->area[s].u.pv.pvseg != peg) {
|
||||
log_debug("Inconsistent pvseg pointers");
|
||||
if (seg_pvseg(peg->lvseg, s) != peg) {
|
||||
log_error("Inconsistent pvseg pointers");
|
||||
ret = 0;
|
||||
}
|
||||
if (peg->lvseg->area_len != peg->len) {
|
||||
log_debug("Inconsistent length: %u %u",
|
||||
log_error("Inconsistent length: %u %u",
|
||||
peg->len,
|
||||
peg->lvseg->area_len);
|
||||
ret = 0;
|
||||
}
|
||||
alloced += 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;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,10 @@ struct dev_manager;
|
||||
#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 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 list list;
|
||||
struct cmd_context *cmd;
|
||||
|
@ -59,7 +59,7 @@ int vg_add_snapshot(struct format_instance *fid, const char *name,
|
||||
|
||||
snap->le_count = extent_count;
|
||||
|
||||
if (!(seg = alloc_snapshot_seg(snap, 0))) {
|
||||
if (!(seg = alloc_snapshot_seg(snap, 0, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ enum {
|
||||
};
|
||||
|
||||
struct mirror_state {
|
||||
uint32_t region_size;
|
||||
uint32_t default_region_size;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
const char *size;
|
||||
|
||||
log_print(" Mirrors\t\t%u", seg->area_count);
|
||||
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:");
|
||||
display_stripe(seg, 0, " ");
|
||||
log_print(" Mirror destination:");
|
||||
display_stripe(seg, 1, " ");
|
||||
log_print(" ");
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const struct config_node *cn;
|
||||
char *logname = NULL;
|
||||
|
||||
if (find_config_node(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"))) {
|
||||
log_error("Couldn't find mirrors array for segment "
|
||||
"'%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);
|
||||
if (seg->status & PVMOVE)
|
||||
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");
|
||||
}
|
||||
@ -112,7 +157,7 @@ static struct mirror_state *_init_target(struct pool *mem,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mirr_state->region_size = 2 *
|
||||
mirr_state->default_region_size = 2 *
|
||||
find_config_int(cft->root,
|
||||
"activation/mirror_region_size",
|
||||
DEFAULT_MIRROR_REGION_SIZE);
|
||||
@ -156,15 +201,23 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
|
||||
} else {
|
||||
*target = "mirror";
|
||||
|
||||
/* Find largest power of 2 region size unit we can use */
|
||||
region_max = (1 << (ffs(seg->area_len) - 1)) *
|
||||
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 */
|
||||
region_max = (1 << (ffs(seg->area_len) - 1)) *
|
||||
seg->lv->vg->extent_size;
|
||||
|
||||
region_size = mirr_state->region_size;
|
||||
if (region_max < region_size) {
|
||||
region_size = region_max;
|
||||
log_verbose("Using reduced mirror region size of %u sectors",
|
||||
region_size);
|
||||
region_size = mirr_state->default_region_size;
|
||||
if (region_max < region_size) {
|
||||
region_size = region_max;
|
||||
log_verbose("Using reduced mirror region size of %u sectors",
|
||||
region_size);
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = compose_log_line(dm, seg, params, paramsize, pos,
|
||||
|
@ -112,6 +112,9 @@ void *malloc_aux(size_t s, const char *file, int line)
|
||||
if (_mem_stats.bytes > _mem_stats.mbytes)
|
||||
_mem_stats.mbytes = _mem_stats.bytes;
|
||||
|
||||
/* log_debug("Allocated: %u %u %u", nb->id, _mem_stats.blocks_allocated,
|
||||
_mem_stats.bytes); */
|
||||
|
||||
return nb + 1;
|
||||
}
|
||||
|
||||
|
@ -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, STR, "Move", lvid, 4, movepv, "move_pv")
|
||||
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, "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, "Stripe", stripe_size, 6, size32, "stripesize")
|
||||
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, "SSize", list, 5, segsize, "seg_size")
|
||||
FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags")
|
||||
|
@ -154,14 +154,14 @@ static int _devices_disp(struct report_handle *rh, struct field *field,
|
||||
}
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
switch (seg->area[s].type) {
|
||||
switch (seg_type(seg, s)) {
|
||||
case AREA_LV:
|
||||
name = seg->area[s].u.lv.lv->name;
|
||||
extent = seg->area[s].u.lv.le;
|
||||
name = seg_lv(seg, s)->name;
|
||||
extent = seg_le(seg, s);
|
||||
break;
|
||||
case AREA_PV:
|
||||
name = dev_name(seg->area[s].u.pv.pvseg->pv->dev);
|
||||
extent = seg->area[s].u.pv.pvseg->pe;
|
||||
name = dev_name(seg_dev(seg, s));
|
||||
extent = seg_pe(seg, s);
|
||||
break;
|
||||
default:
|
||||
name = "unknown";
|
||||
@ -337,6 +337,8 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
repstr[0] = 'p';
|
||||
else if (lv->status & MIRRORED)
|
||||
repstr[0] = 'm';
|
||||
else if (lv->status & MIRROR_LOG)
|
||||
repstr[0] = 'l';
|
||||
else if (lv->status & VIRTUAL)
|
||||
repstr[0] = 'v';
|
||||
else if (lv_is_origin(lv))
|
||||
@ -490,19 +492,35 @@ static int _origin_disp(struct report_handle *rh, struct field *field,
|
||||
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,
|
||||
const void *data)
|
||||
{
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
const char *name;
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (!(seg->status & PVMOVE))
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct list *fh;
|
||||
struct field_properties *fp, *found = NULL;
|
||||
|
||||
list_iterate(fh, &rh->field_props) {
|
||||
fp = list_item(fh, struct field_properties);
|
||||
|
||||
list_iterate_items(fp, &rh->field_props) {
|
||||
if (fp->field_num == field_num) {
|
||||
found = fp;
|
||||
break;
|
||||
@ -1138,7 +1153,6 @@ int report_object(void *handle, struct volume_group *vg,
|
||||
struct lv_segment *seg, struct pv_segment *pvseg)
|
||||
{
|
||||
struct report_handle *rh = handle;
|
||||
struct list *fh;
|
||||
struct field_properties *fp;
|
||||
struct row *row;
|
||||
struct field *field;
|
||||
@ -1168,9 +1182,7 @@ int report_object(void *handle, struct volume_group *vg,
|
||||
list_add(&rh->rows, &row->list);
|
||||
|
||||
/* For each field to be displayed, call its report_fn */
|
||||
list_iterate(fh, &rh->field_props) {
|
||||
fp = list_item(fh, struct field_properties);
|
||||
|
||||
list_iterate_items(fp, &rh->field_props) {
|
||||
skip = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
struct report_handle *rh = handle;
|
||||
struct list *fh;
|
||||
struct field_properties *fp;
|
||||
const char *heading;
|
||||
char buf[1024];
|
||||
@ -1250,8 +1261,7 @@ static int _report_headings(void *handle)
|
||||
}
|
||||
|
||||
/* First heading line */
|
||||
list_iterate(fh, &rh->field_props) {
|
||||
fp = list_item(fh, struct field_properties);
|
||||
list_iterate_items(fp, &rh->field_props) {
|
||||
if (fp->flags & FLD_HIDDEN)
|
||||
continue;
|
||||
|
||||
@ -1268,7 +1278,7 @@ static int _report_headings(void *handle)
|
||||
} else if (!pool_grow_object(rh->mem, heading, strlen(heading)))
|
||||
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,
|
||||
strlen(rh->separator)))
|
||||
goto bad;
|
||||
@ -1336,7 +1346,6 @@ static int _row_compare(const void *a, const void *b)
|
||||
static int _sort_rows(struct report_handle *rh)
|
||||
{
|
||||
struct row *(*rows)[];
|
||||
struct list *rowh;
|
||||
uint32_t count = 0;
|
||||
struct row *row;
|
||||
|
||||
@ -1346,10 +1355,8 @@ static int _sort_rows(struct report_handle *rh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate(rowh, &rh->rows) {
|
||||
row = list_item(rowh, struct row);
|
||||
list_iterate_items(row, &rh->rows)
|
||||
(*rows)[count++] = row;
|
||||
}
|
||||
|
||||
qsort(rows, count, sizeof(**rows), _row_compare);
|
||||
|
||||
|
@ -119,10 +119,10 @@ static int _segments_compatible(struct lv_segment *first,
|
||||
|
||||
width = first->area_len;
|
||||
|
||||
if ((first->area[s].u.pv.pvseg->pv !=
|
||||
second->area[s].u.pv.pvseg->pv) ||
|
||||
(first->area[s].u.pv.pvseg->pe + width !=
|
||||
second->area[s].u.pv.pvseg->pe))
|
||||
if ((seg_pv(first, s) !=
|
||||
seg_pv(second, s)) ||
|
||||
(seg_pe(first, s) + width !=
|
||||
seg_pe(second, s)))
|
||||
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++)
|
||||
if (seg1->area[s].type == AREA_PV)
|
||||
merge_pv_segments(seg1->area[s].u.pv.pvseg,
|
||||
seg2->area[s].u.pv.pvseg);
|
||||
merge_pv_segments(seg_pvseg(seg1, s),
|
||||
seg_pvseg(seg2, s));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -103,6 +103,14 @@ static inline int list_end(struct list *head, struct list *elem)
|
||||
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
|
||||
*/
|
||||
@ -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)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
@ -85,6 +85,7 @@ arg(size_ARG, 'L', "size", size_mb_arg)
|
||||
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign)
|
||||
arg(persistent_ARG, 'M', "persistent", yes_no_arg)
|
||||
arg(major_ARG, 'j', "major", major_arg)
|
||||
arg(mirrors_ARG, 'm', "mirrors", int_arg)
|
||||
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg)
|
||||
arg(maps_ARG, 'm', "maps", NULL)
|
||||
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(resizefs_ARG, 'r', "resizefs", NULL)
|
||||
arg(reset_ARG, 'R', "reset", NULL)
|
||||
arg(regionsize_ARG, 'R', "regionsize", size_mb_arg)
|
||||
arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg)
|
||||
arg(stdin_ARG, 's', "stdin", NULL)
|
||||
arg(snapshot_ARG, 's', "snapshot", NULL)
|
||||
|
@ -91,9 +91,11 @@ xx(lvcreate,
|
||||
"\t{-l|--extents LogicalExtentsNumber |\n"
|
||||
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
|
||||
"\t[-m|--mirrors Mirrors]\n"
|
||||
"\t[-n|--name LogicalVolumeName]\n"
|
||||
"\t[-p|--permission {r|rw}]\n"
|
||||
"\t[-r|--readahead ReadAheadSectors]\n"
|
||||
"\t[-R|--regionsize MirrorLogRegionSize]\n"
|
||||
"\t[-t|--test]\n"
|
||||
"\t[--type VolumeType]\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
@ -122,9 +124,9 @@ xx(lvcreate,
|
||||
"\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n",
|
||||
|
||||
addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG,
|
||||
extents_ARG, major_ARG, minor_ARG, name_ARG, permission_ARG,
|
||||
persistent_ARG, readahead_ARG, size_ARG, snapshot_ARG, stripes_ARG,
|
||||
stripesize_ARG, test_ARG, type_ARG, zero_ARG)
|
||||
extents_ARG, major_ARG, minor_ARG, mirrors_ARG, name_ARG, permission_ARG,
|
||||
persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG,
|
||||
stripes_ARG, stripesize_ARG, test_ARG, type_ARG, zero_ARG)
|
||||
|
||||
xx(lvdisplay,
|
||||
"Display information about a logical volume",
|
||||
|
@ -405,6 +405,12 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
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 */
|
||||
if (arg_count(cmd, permission_ARG)) {
|
||||
if (!archive(lv->vg))
|
||||
|
188
tools/lvcreate.c
188
tools/lvcreate.c
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
#include "lv_alloc.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
@ -31,6 +32,7 @@ struct lvcreate_params {
|
||||
uint32_t stripes;
|
||||
uint32_t stripe_size;
|
||||
uint32_t chunk_size;
|
||||
uint32_t region_size;
|
||||
|
||||
uint32_t mirrors;
|
||||
|
||||
@ -228,6 +230,38 @@ static int _read_stripe_params(struct lvcreate_params *lp,
|
||||
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,
|
||||
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))
|
||||
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 (arg_count(cmd, zero_ARG)) {
|
||||
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 &&
|
||||
!lp->segtype->ops->target_present()) {
|
||||
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) ||
|
||||
!_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
uint32_t size_rest;
|
||||
uint32_t size_rest, region_max;
|
||||
uint32_t status = 0;
|
||||
uint64_t tmp_size;
|
||||
struct volume_group *vg;
|
||||
struct logical_volume *lv, *org = NULL;
|
||||
struct logical_volume *lv, *org = NULL, *log_lv = NULL;
|
||||
struct list *pvh;
|
||||
const char *tag;
|
||||
int consistent = 1;
|
||||
struct alloc_handle *ah = NULL;
|
||||
|
||||
status |= lp->permission | VISIBLE_LV;
|
||||
|
||||
@ -505,30 +574,98 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
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 "
|
||||
"number of physical volumes (%d)", lp->stripes,
|
||||
list_size(pvh));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(lv = lv_create_empty(vg->fid, lp->lv_name, "lvol%d", NULL,
|
||||
status, lp->alloc, 0, vg))) {
|
||||
stack;
|
||||
if (lp->mirrors > 1 && !activation()) {
|
||||
log_error("Can't create mirror without using "
|
||||
"device-mapper kernel driver.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The snapshot segment gets created later */
|
||||
if (lp->snapshot)
|
||||
if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||
if (lp->snapshot &&
|
||||
!(lp->segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!archive(vg))
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size,
|
||||
lp->mirrors, lp->extents, NULL, 0u, 0u, pvh, lp->alloc)) {
|
||||
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;
|
||||
return 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (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 (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
|
||||
log_error("Failed to get tag");
|
||||
return 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(lv->vg->fid->fmt->features & FMT_TAGS)) {
|
||||
log_error("Volume group %s does not support tags",
|
||||
lv->vg->name);
|
||||
return 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!str_list_add(cmd->mem, &lv->tags, tag)) {
|
||||
log_error("Failed to add tag %s to %s/%s",
|
||||
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;
|
||||
}
|
||||
|
||||
/* store vg on disk(s) */
|
||||
if (!vg_write(vg)) {
|
||||
@ -642,6 +793,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
*/
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
if (ah)
|
||||
alloc_destroy(ah);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lvcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
@ -34,6 +34,12 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
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) {
|
||||
log_error("Can't remove locked LV %s", lv->name);
|
||||
return ECMD_FAILED;
|
||||
|
@ -110,9 +110,9 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
|
||||
int ret = 0;
|
||||
int consistent;
|
||||
|
||||
struct list *slh, *tags_arg;
|
||||
struct list *tags_arg;
|
||||
struct list *vgnames; /* VGs to process */
|
||||
struct str_list *sll;
|
||||
struct str_list *sll, *strl;
|
||||
struct volume_group *vg;
|
||||
struct list tags, lvnames;
|
||||
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) {
|
||||
vgname = list_item(slh, struct str_list)->str;
|
||||
list_iterate_items(strl, vgnames) {
|
||||
vgname = strl->str;
|
||||
if (!vgname || !*vgname)
|
||||
continue; /* FIXME Unnecessary? */
|
||||
if (!lock_vol(cmd, vgname, lock_type)) {
|
||||
|
@ -30,10 +30,10 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
|
||||
if ((lv->status & SNAPSHOT) || lv_is_cow(lv))
|
||||
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 */
|
||||
if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
|
||||
(lv->status & PVMOVE))
|
||||
((lv->status & PVMOVE) || (lv->status & MIRROR_LOG)))
|
||||
continue;
|
||||
|
||||
if (activate == CHANGE_AN) {
|
||||
|
@ -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? */
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->area[s].type != AREA_PV)
|
||||
if (seg_type(seg, s) != AREA_PV)
|
||||
continue;
|
||||
|
||||
/* 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 (!_remove_lv(cmd, lv, &list_unsafe)) {
|
||||
stack;
|
||||
|
@ -78,10 +78,10 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
/* FIXME Check AREA_LV too */
|
||||
if (seg->area[s].type != AREA_PV)
|
||||
if (seg_type(seg, s) != AREA_PV)
|
||||
continue;
|
||||
|
||||
pv = seg->area[s].u.pv.pvseg->pv;
|
||||
pv = seg_pv(seg, s);
|
||||
if (vg_with) {
|
||||
if (!pv_is_in_vg(vg_with, pv)) {
|
||||
log_error("Logical Volume %s "
|
||||
|
Loading…
Reference in New Issue
Block a user