1
0
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:
Alasdair Kergon 2005-06-01 16:51:55 +00:00
parent 8e6230ddd9
commit 60f13f01d2
54 changed files with 1752 additions and 1164 deletions

View File

@ -1,5 +1,16 @@
Version 2.01.11 -
==============================
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.

View File

@ -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;

View File

@ -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
View File

@ -104,8 +104,9 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
const struct format_type *fmt_from_vgname(const char *vgname)
{
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) {

View File

@ -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;

View File

@ -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"

View File

@ -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.
*/

View File

@ -196,7 +196,7 @@ static int _compare_paths(const char *path0, const char *path1)
static int _add_alias(struct device *dev, const char *path)
{
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);

View File

@ -449,29 +449,28 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
{
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);
}
}

View File

@ -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));

View File

@ -158,13 +158,11 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
static int _accept_p(struct dev_filter *f, struct device *dev)
{
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) {

View File

@ -424,11 +424,11 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
static void _add_pv_to_list(struct list *head, struct disk_list *data)
{
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;

View File

@ -46,9 +46,7 @@ static int _check_vgs(struct list *pvs, int *partial)
* This means an active VG won't be affected if disks are inserted
* 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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -57,12 +57,9 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
static void _add_pl_to_list(struct list *head, struct pool_list *data)
{
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);

View File

@ -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;

View File

@ -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;
}

View File

@ -91,7 +91,6 @@ static int _split_vg(const char *filename, char *vgname, size_t vg_size,
static void _insert_file(struct list *head, struct archive_file *b)
{
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);

View File

@ -330,7 +330,7 @@ static inline const char *_get_pv_name(struct formatter *f,
static int _print_pvs(struct formatter *f, struct volume_group *vg)
{
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) {

View File

@ -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},

View File

@ -341,8 +341,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct 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;

View File

@ -223,12 +223,9 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg)
{
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;
}

View File

@ -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

View File

@ -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))) {

View File

@ -98,14 +98,11 @@ int label_register_handler(const char *name, struct labeller *handler)
struct labeller *label_get_handler(const char *name)
{
struct 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;

View File

@ -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;

View File

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

View File

@ -22,17 +22,49 @@ struct lv_segment *alloc_lv_segment(struct pool *mem,
uint32_t le, uint32_t len,
uint32_t 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

View File

@ -58,11 +58,13 @@ int lv_merge_segments(struct logical_volume *lv)
/*
* Verify that an LV's segments are consecutive, complete and don't overlap.
*/
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;
}
}

View File

@ -139,7 +139,6 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
const char *id, struct physical_volume *pv)
{
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;

View File

@ -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

View File

@ -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))

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -32,6 +32,7 @@ FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent")
FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent")
FIELD(LVS, lv, 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")

View File

@ -154,14 +154,14 @@ static int _devices_disp(struct report_handle *rh, struct field *field,
}
for (s = 0; s < seg->area_count; s++) {
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);

View File

@ -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;
}

View File

@ -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.
*/

View File

@ -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)

View File

@ -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",

View File

@ -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))

View File

@ -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)

View File

@ -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;

View File

@ -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)) {

View File

@ -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) {

View File

@ -129,12 +129,12 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
/* Are any segments of this LV on missing PVs? */
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;

View File

@ -78,10 +78,10 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
list_iterate_items(seg, &lv->segments) {
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 "