[lvm-devel] LVM2 ./WHATS_NEW daemons/clvmd/lvm-functions.c ...
agk at sourceware.org
agk at sourceware.org
Fri Sep 19 06:42:05 UTC 2008
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: agk at sourceware.org 2008-09-19 06:42:00
Modified files:
. : WHATS_NEW
daemons/clvmd : lvm-functions.c
doc : example.conf
lib/activate : activate.c dev_manager.c
lib/commands : toolcontext.c toolcontext.h
lib/config : defaults.h
lib/display : display.c
lib/format1 : disk-rep.h format1.c import-export.c
lib/format_text: archiver.c flags.c import_vsn1.c
lib/locking : cluster_locking.c locking.h
lib/log : log.c log.h
lib/metadata : metadata-exported.h metadata.c metadata.h
lib/report : report.c
man : lvm.conf.5 vgreduce.8
tools : commands.h lvmcmdline.c lvremove.c pvcreate.c
vgcfgbackup.c vgreduce.c
Log message:
Improve the way VGs with PVs missing are handled so manual intervention
is required in fewer circumstances. (mornfall)
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.959&r2=1.960
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/lvm-functions.c.diff?cvsroot=lvm2&r1=1.44&r2=1.45
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/doc/example.conf.diff?cvsroot=lvm2&r1=1.37&r2=1.38
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/activate.c.diff?cvsroot=lvm2&r1=1.137&r2=1.138
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/dev_manager.c.diff?cvsroot=lvm2&r1=1.139&r2=1.140
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.c.diff?cvsroot=lvm2&r1=1.61&r2=1.62
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.h.diff?cvsroot=lvm2&r1=1.24&r2=1.25
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/defaults.h.diff?cvsroot=lvm2&r1=1.43&r2=1.44
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/display/display.c.diff?cvsroot=lvm2&r1=1.91&r2=1.92
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format1/disk-rep.h.diff?cvsroot=lvm2&r1=1.51&r2=1.52
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format1/format1.c.diff?cvsroot=lvm2&r1=1.107&r2=1.108
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format1/import-export.c.diff?cvsroot=lvm2&r1=1.98&r2=1.99
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/archiver.c.diff?cvsroot=lvm2&r1=1.13&r2=1.14
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/flags.c.diff?cvsroot=lvm2&r1=1.34&r2=1.35
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import_vsn1.c.diff?cvsroot=lvm2&r1=1.53&r2=1.54
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/cluster_locking.c.diff?cvsroot=lvm2&r1=1.29&r2=1.30
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/locking.h.diff?cvsroot=lvm2&r1=1.41&r2=1.42
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/log/log.c.diff?cvsroot=lvm2&r1=1.47&r2=1.48
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/log/log.h.diff?cvsroot=lvm2&r1=1.41&r2=1.42
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.52&r2=1.53
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.190&r2=1.191
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.h.diff?cvsroot=lvm2&r1=1.181&r2=1.182
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/report/report.c.diff?cvsroot=lvm2&r1=1.87&r2=1.88
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvm.conf.5.diff?cvsroot=lvm2&r1=1.22&r2=1.23
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/vgreduce.8.diff?cvsroot=lvm2&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/commands.h.diff?cvsroot=lvm2&r1=1.118&r2=1.119
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvmcmdline.c.diff?cvsroot=lvm2&r1=1.69&r2=1.70
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvremove.c.diff?cvsroot=lvm2&r1=1.54&r2=1.55
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvcreate.c.diff?cvsroot=lvm2&r1=1.74&r2=1.75
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgcfgbackup.c.diff?cvsroot=lvm2&r1=1.25&r2=1.26
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgreduce.c.diff?cvsroot=lvm2&r1=1.82&r2=1.83
--- LVM2/WHATS_NEW 2008/09/19 05:33:37 1.959
+++ LVM2/WHATS_NEW 2008/09/19 06:41:57 1.960
@@ -1,5 +1,11 @@
Version 2.02.40 -
================================
+ In VG with PVs missing, by default allow activation of LVs that are complete.
+ Track PARTIAL_LV and MISSING_PV flags internally.
+ Require --force with --removemissing in vgreduce to remove partial LVs.
+ No longer write out PARTIAL flag into metadata backups.
+ Treat new default activation/missing_stripe_filler "error" as an error target.
+ Remove internal partial_mode.
Add device/md_chunk_alignment to lvm.conf.
Pass struct physical_volume to pe_align and adjust for md chunk size.
Store sysfs location in struct cmd_context.
--- LVM2/daemons/clvmd/lvm-functions.c 2008/06/06 16:37:51 1.44
+++ LVM2/daemons/clvmd/lvm-functions.c 2008/09/19 06:41:57 1.45
@@ -413,9 +413,6 @@
}
}
- if (lock_flags & LCK_PARTIAL_MODE)
- init_partial(1);
-
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(1);
@@ -454,9 +451,6 @@
break;
}
- if (lock_flags & LCK_PARTIAL_MODE)
- init_partial(0);
-
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(0);
--- LVM2/doc/example.conf 2008/09/19 05:33:36 1.37
+++ LVM2/doc/example.conf 2008/09/19 06:41:57 1.38
@@ -271,11 +271,13 @@
}
activation {
- # Device used in place of missing stripes if activating incomplete volume.
- # For now, you need to set this up yourself first (e.g. with 'dmsetup')
- # For example, you could make it return I/O errors using the 'error'
- # target or make it return zeros.
- missing_stripe_filler = "/dev/ioerror"
+ # How to fill in missing stripes if activating an incomplete volume.
+ # Using "error" will make inaccessible parts of the device return
+ # I/O errors on access. You can instead use a device path, in which
+ # case, that device will be used to in place of missing stripes.
+ # But note that using anything other than "error" with mirrored
+ # or snapshotted volumes is likely to result in data corruption.
+ missing_stripe_filler = "error"
# How much stack (in KB) to reserve for use while devices suspended
reserved_stack = 256
--- LVM2/lib/activate/activate.c 2008/06/08 11:33:15 1.137
+++ LVM2/lib/activate/activate.c 2008/09/19 06:41:57 1.138
@@ -1027,6 +1027,12 @@
return 0;
}
+ if ((!lv->vg->cmd->partial_activate) && (lv->status & PARTIAL_LV)) {
+ log_error("Refusing activation of partial LV %s. Use --partial to override.",
+ lv->name);
+ return_0;
+ }
+
if (test_mode()) {
_skip("Activating '%s'.", lv->name);
return 1;
--- LVM2/lib/activate/dev_manager.c 2008/07/15 00:25:51 1.139
+++ LVM2/lib/activate/dev_manager.c 2008/09/19 06:41:57 1.140
@@ -47,7 +47,6 @@
struct cmd_context *cmd;
- const char *stripe_filler;
void *target_state;
uint32_t pvmove_mirror_count;
@@ -59,8 +58,6 @@
const char *old_name;
};
-static const char *stripe_filler = NULL;
-
static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *layer)
{
char *dlid;
@@ -443,13 +440,6 @@
dm->cmd = cmd;
dm->mem = mem;
- if (!stripe_filler) {
- stripe_filler = find_config_tree_str(cmd,
- "activation/missing_stripe_filler",
- DEFAULT_STRIPE_FILLER);
- }
- dm->stripe_filler = stripe_filler;
-
if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name)))
goto_bad;
@@ -699,6 +689,68 @@
return NULL;
}
+static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
+ struct lv_segment *seg, int s)
+{
+ char *id, *name;
+ char errid[32];
+ struct dm_tree_node *node;
+ struct lv_segment *seg_i;
+ int segno = -1, i = 0;;
+ uint64_t size = seg->len * seg->lv->vg->extent_size;
+
+ list_iterate_items(seg_i, &seg->lv->segments) {
+ if (seg == seg_i)
+ segno = i;
+ ++i;
+ }
+
+ if (segno < 0) {
+ log_error("_add_error_device called with bad segment");
+ return_NULL;
+ }
+
+ sprintf(errid, "missing_%d_%d", segno, s);
+
+ if (!(id = build_dlid(dm, seg->lv->lvid.s, errid)))
+ return_NULL;
+
+ if (!(name = build_dm_name(dm->mem, seg->lv->vg->name,
+ seg->lv->name, errid)))
+ return_NULL;
+ if (!(node = dm_tree_add_new_dev(dtree, name, id, 0, 0, 0, 0, 0)))
+ return_NULL;
+ if (!dm_tree_node_add_error_target(node, size))
+ return_NULL;
+
+ return id;
+}
+
+static int _add_error_area(struct dev_manager *dm, struct dm_tree_node *node,
+ struct lv_segment *seg, int s)
+{
+ char *dlid;
+ uint64_t extent_size = seg->lv->vg->extent_size;
+
+ if (!strcmp(dm->cmd->stripe_filler, "error")) {
+ /*
+ * FIXME, the tree pointer is first field of dm_tree_node, but
+ * we don't have the struct definition available.
+ */
+ struct dm_tree **tree = (struct dm_tree **) node;
+ dlid = _add_error_device(dm, *tree, seg, s);
+ if (!dlid)
+ return_0;
+ dm_tree_node_add_target_area(node, NULL, dlid,
+ extent_size * seg_le(seg, s));
+ } else {
+ dm_tree_node_add_target_area(node,
+ dm->cmd->stripe_filler,
+ NULL, UINT64_C(0));
+ }
+ return 1;
+}
+
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
struct dm_tree_node *node, uint32_t start_area,
uint32_t areas)
@@ -712,11 +764,10 @@
(!seg_pvseg(seg, s) ||
!seg_pv(seg, s) ||
!seg_dev(seg, s))) ||
- (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
- dm_tree_node_add_target_area(node,
- dm->stripe_filler,
- NULL, UINT64_C(0));
- else if (seg_type(seg, s) == AREA_PV)
+ (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s))) {
+ if (!_add_error_area(dm, node, seg, s))
+ return_0;
+ } else if (seg_type(seg, s) == AREA_PV)
dm_tree_node_add_target_area(node,
dev_name(seg_dev(seg, s)),
NULL,
--- LVM2/lib/commands/toolcontext.c 2008/09/19 03:42:37 1.61
+++ LVM2/lib/commands/toolcontext.c 2008/09/19 06:41:58 1.62
@@ -197,6 +197,7 @@
{
mode_t old_umask;
const char *read_ahead;
+ struct stat st;
/* umask */
cmd->default_settings.umask = find_config_tree_int(cmd,
@@ -263,6 +264,24 @@
return 0;
}
+ cmd->stripe_filler = find_config_tree_str(cmd,
+ "activation/missing_stripe_filler",
+ DEFAULT_STRIPE_FILLER);
+ if (strcmp(cmd->stripe_filler, "error")) {
+ if (stat(cmd->stripe_filler, &st)) {
+ log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
+ "is invalid,", cmd->stripe_filler);
+ log_warn(" stat failed: %s", strerror(errno));
+ log_warn("Falling back to \"error\" missing_stripe_filler.");
+ cmd->stripe_filler = "error";
+ } else if (!S_ISBLK(st.st_mode)) {
+ log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
+ "is not a block device.", cmd->stripe_filler);
+ log_warn("Falling back to \"error\" missing_stripe_filler.");
+ cmd->stripe_filler = "error";
+ }
+ }
+
return 1;
}
@@ -981,6 +1000,7 @@
cmd->args = the_args;
cmd->is_static = is_static;
cmd->is_long_lived = is_long_lived;
+ cmd->handles_missing_pvs = 0;
cmd->hosttags = 0;
list_init(&cmd->formats);
list_init(&cmd->segtypes);
--- LVM2/lib/commands/toolcontext.h 2008/09/19 03:42:37 1.24
+++ LVM2/lib/commands/toolcontext.h 2008/09/19 06:41:58 1.25
@@ -66,8 +66,10 @@
struct command *command;
struct arg *args;
char **argv;
- unsigned is_static; /* Static binary? */
- unsigned is_long_lived; /* Optimises persistent_filter handling */
+ unsigned is_static:1; /* Static binary? */
+ unsigned is_long_lived:1; /* Optimises persistent_filter handling */
+ unsigned handles_missing_pvs:1;
+ unsigned partial_activate:1;
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */
@@ -81,6 +83,7 @@
struct archive_params *archive_params;
struct backup_params *backup_params;
+ const char *stripe_filler;
/* List of defined tags */
struct list tags;
--- LVM2/lib/config/defaults.h 2008/09/19 05:33:37 1.43
+++ LVM2/lib/config/defaults.h 2008/09/19 06:41:58 1.44
@@ -92,7 +92,7 @@
# define DEFAULT_ACTIVATION 0
#endif
-#define DEFAULT_STRIPE_FILLER "/dev/ioerror"
+#define DEFAULT_STRIPE_FILLER "error"
#define DEFAULT_MIRROR_REGION_SIZE 512 /* KB */
#define DEFAULT_INTERVAL 15
--- LVM2/lib/display/display.c 2008/08/07 14:01:17 1.91
+++ LVM2/lib/display/display.c 2008/09/19 06:41:58 1.92
@@ -578,10 +578,7 @@
struct lv_list *lvl;
char uuid[64] __attribute((aligned(8)));
- if (vg->status & PARTIAL_VG)
- active_pvs = list_size(&vg->pvs);
- else
- active_pvs = vg->pv_count;
+ active_pvs = vg->pv_count - vg_missing_pv_count(vg);
log_print("--- Volume group ---");
log_print("VG Name %s", vg->name);
@@ -664,10 +661,7 @@
const char *access;
char uuid[64] __attribute((aligned(8)));
- if (vg->status & PARTIAL_VG)
- active_pvs = list_size(&vg->pvs);
- else
- active_pvs = vg->pv_count;
+ active_pvs = vg->pv_count - vg_missing_pv_count(vg);
list_iterate_items(lvl, &vg->lvs)
if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
--- LVM2/lib/format1/disk-rep.h 2007/08/20 20:55:25 1.51
+++ LVM2/lib/format1/disk-rep.h 2008/09/19 06:41:58 1.52
@@ -212,7 +212,7 @@
struct pv_disk *pvd, struct physical_volume *pv);
int import_vg(struct dm_pool *mem,
- struct volume_group *vg, struct disk_list *dl, int partial);
+ struct volume_group *vg, struct disk_list *dl);
int export_vg(struct vg_disk *vgd, struct volume_group *vg);
int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
--- LVM2/lib/format1/format1.c 2008/03/17 16:51:31 1.107
+++ LVM2/lib/format1/format1.c 2008/09/19 06:41:58 1.108
@@ -23,7 +23,7 @@
#include "segtype.h"
/* VG consistency checks */
-static int _check_vgs(struct list *pvs, int *partial)
+static int _check_vgs(struct list *pvs)
{
struct list *pvh, *t;
struct disk_list *dl = NULL;
@@ -33,8 +33,6 @@
uint32_t exported = 0;
int first_time = 1;
- *partial = 0;
-
/*
* If there are exported and unexported PVs, ignore exported ones.
* This means an active VG won't be affected if disks are inserted
@@ -98,10 +96,6 @@
dl->vgd.pe_total, dl->vgd.pe_allocated,
dl->vgd.pvg_total);
list_del(pvh);
- if (partial_mode()) {
- *partial = 1;
- continue;
- }
return 0;
}
pv_count++;
@@ -111,9 +105,6 @@
if (pv_count != first->vgd.pv_cur) {
log_error("%d PV(s) found for VG %s: expected %d",
pv_count, first->pvd.vg_name, first->vgd.pv_cur);
- if (!partial_mode())
- return 0;
- *partial = 1;
}
return 1;
@@ -125,7 +116,6 @@
struct dm_pool *mem = fid->fmt->cmd->mem;
struct volume_group *vg = dm_pool_alloc(mem, sizeof(*vg));
struct disk_list *dl;
- int partial;
if (!vg)
goto_bad;
@@ -142,12 +132,12 @@
list_init(&vg->lvs);
list_init(&vg->tags);
- if (!_check_vgs(pvs, &partial))
+ if (!_check_vgs(pvs))
goto_bad;
dl = list_item(pvs->n, struct disk_list);
- if (!import_vg(mem, vg, dl, partial))
+ if (!import_vg(mem, vg, dl))
goto_bad;
if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count))
--- LVM2/lib/format1/import-export.c 2008/09/19 04:27:26 1.98
+++ LVM2/lib/format1/import-export.c 2008/09/19 06:41:58 1.99
@@ -214,7 +214,7 @@
}
int import_vg(struct dm_pool *mem,
- struct volume_group *vg, struct disk_list *dl, int partial)
+ struct volume_group *vg, struct disk_list *dl)
{
struct vg_disk *vgd = &dl->vgd;
memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
@@ -236,10 +236,10 @@
if (vgd->vg_status & VG_EXTENDABLE)
vg->status |= RESIZEABLE_VG;
- if (partial || (vgd->vg_access & VG_READ))
+ if (vgd->vg_access & VG_READ)
vg->status |= LVM_READ;
- if (!partial && (vgd->vg_access & VG_WRITE))
+ if (vgd->vg_access & VG_WRITE)
vg->status |= LVM_WRITE;
if (vgd->vg_access & VG_CLUSTERED)
@@ -255,9 +255,6 @@
vg->max_pv = vgd->pv_max;
vg->alloc = ALLOC_NORMAL;
- if (partial)
- vg->status |= PARTIAL_VG;
-
return 1;
}
--- LVM2/lib/format_text/archiver.c 2008/01/30 13:59:59 1.13
+++ LVM2/lib/format_text/archiver.c 2008/09/19 06:41:58 1.14
@@ -134,10 +134,8 @@
{
int r1, r2;
- init_partial(1);
r1 = archive_list(cmd, cmd->archive_params->dir, vg_name);
r2 = backup_list(cmd, cmd->backup_params->dir, vg_name);
- init_partial(0);
return r1 && r2;
}
@@ -146,9 +144,7 @@
{
int r;
- init_partial(1);
r = archive_list_file(cmd, file);
- init_partial(0);
return r;
}
@@ -393,7 +389,7 @@
char path[PATH_MAX];
struct volume_group *vg_backup;
- if ((vg->status & PARTIAL_VG) || (vg->status & EXPORTED_VG))
+ if (vg->status & EXPORTED_VG)
return;
if (dm_snprintf(path, sizeof(path), "%s/%s",
--- LVM2/lib/format_text/flags.c 2008/07/10 11:30:57 1.34
+++ LVM2/lib/format_text/flags.c 2008/09/19 06:41:58 1.35
@@ -31,12 +31,12 @@
static struct flag _vg_flags[] = {
{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
{RESIZEABLE_VG, "RESIZEABLE", STATUS_FLAG},
- {PARTIAL_VG, "PARTIAL", STATUS_FLAG},
{PVMOVE, "PVMOVE", STATUS_FLAG},
{LVM_READ, "READ", STATUS_FLAG},
{LVM_WRITE, "WRITE", STATUS_FLAG},
{CLUSTERED, "CLUSTERED", STATUS_FLAG},
{SHARED, "SHARED", STATUS_FLAG},
+ {PARTIAL_VG, NULL, 0},
{PRECOMMITTED, NULL, 0},
{0, NULL, 0}
};
@@ -44,6 +44,7 @@
static struct flag _pv_flags[] = {
{ALLOCATABLE_PV, "ALLOCATABLE", STATUS_FLAG},
{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
+ {MISSING_PV, "MISSING", COMPATIBLE_FLAG},
{0, NULL, 0}
};
@@ -62,6 +63,8 @@
{SNAPSHOT, NULL, 0},
{ACTIVATE_EXCL, NULL, 0},
{CONVERTING, NULL, 0},
+ {PARTIAL_LV, NULL, 0},
+ {POSTORDER_FLAG, NULL, 0},
{0, NULL, 0}
};
@@ -155,7 +158,16 @@
break;
}
- if (!flags[f].description && (type & STATUS_FLAG)) {
+ if (type == VG_FLAGS && !strcmp(cv->v.str, "PARTIAL")) {
+ /*
+ * Exception: We no longer write this flag out, but it
+ * might be encountered in old backup files, so restore
+ * it in that case. It is never part of live metadata
+ * though, so only vgcfgrestore needs to be concerned
+ * by this case.
+ */
+ s |= PARTIAL_VG;
+ } else if (!flags[f].description && (type & STATUS_FLAG)) {
log_err("Unknown status flag '%s'.", cv->v.str);
return 0;
}
--- LVM2/lib/format_text/import_vsn1.c 2008/09/19 04:27:26 1.53
+++ LVM2/lib/format_text/import_vsn1.c 2008/09/19 06:41:58 1.54
@@ -194,11 +194,6 @@
else
log_error("Couldn't find device with uuid '%s'.",
buffer);
-
- if (partial_mode())
- vg->status |= PARTIAL_VG;
- else
- return 0;
}
if (!(pv->vg_name = dm_pool_strdup(mem, vg->name)))
@@ -211,6 +206,9 @@
return 0;
}
+ if (!pv->dev)
+ pv->status |= MISSING_PV;
+
/* Late addition */
_read_int64(pvn, "dev_size", &pv->size);
@@ -800,11 +798,6 @@
dm_hash_destroy(pv_hash);
- if (vg->status & PARTIAL_VG) {
- vg->status &= ~LVM_WRITE;
- vg->status |= LVM_READ;
- }
-
/*
* Finished.
*/
--- LVM2/lib/locking/cluster_locking.c 2008/05/09 18:45:15 1.29
+++ LVM2/lib/locking/cluster_locking.c 2008/09/19 06:41:58 1.30
@@ -315,9 +315,6 @@
args[0] = flags & 0x7F; /* Maskoff lock flags */
args[1] = flags & 0xC0; /* Bitmap flags */
- if (partial_mode())
- args[1] |= LCK_PARTIAL_MODE;
-
if (mirror_in_sync())
args[1] |= LCK_MIRROR_NOSYNC_MODE;
--- LVM2/lib/locking/locking.h 2008/05/09 19:26:58 1.41
+++ LVM2/lib/locking/locking.h 2008/09/19 06:41:58 1.42
@@ -83,7 +83,6 @@
/*
* Additional lock bits for cluster communication
*/
-#define LCK_PARTIAL_MODE 0x00000001U /* Running in partial mode */
#define LCK_MIRROR_NOSYNC_MODE 0x00000002U /* Mirrors don't require sync */
#define LCK_DMEVENTD_MONITOR_MODE 0x00000004U /* Register with dmeventd */
--- LVM2/lib/log/log.c 2008/06/17 14:14:00 1.47
+++ LVM2/lib/log/log.c 2008/09/19 06:41:59 1.48
@@ -29,7 +29,6 @@
static int _verbose_level = VERBOSE_BASE_LEVEL;
static int _test = 0;
-static int _partial = 0;
static int _md_filtering = 0;
static int _pvmove = 0;
static int _full_scan_done = 0; /* Restrict to one full scan during each cmd */
@@ -154,11 +153,6 @@
_test = level;
}
-void init_partial(int level)
-{
- _partial = level;
-}
-
void init_md_filtering(int level)
{
_md_filtering = level;
@@ -254,11 +248,6 @@
return _test;
}
-int partial_mode()
-{
- return _partial;
-}
-
int md_filtering()
{
return _md_filtering;
--- LVM2/lib/log/log.h 2008/06/06 19:28:34 1.41
+++ LVM2/lib/log/log.h 2008/09/19 06:41:59 1.42
@@ -64,7 +64,6 @@
void init_verbose(int level);
void init_test(int level);
-void init_partial(int level);
void init_md_filtering(int level);
void init_pvmove(int level);
void init_full_scan_done(int level);
@@ -84,7 +83,6 @@
void set_cmd_name(const char *cmd_name);
int test_mode(void);
-int partial_mode(void);
int md_filtering(void);
int pvmove_mode(void);
int full_scan_done(void);
--- LVM2/lib/metadata/metadata-exported.h 2008/09/19 04:27:27 1.52
+++ LVM2/lib/metadata/metadata-exported.h 2008/09/19 06:41:59 1.53
@@ -71,6 +71,13 @@
//#define PRECOMMITTED 0x00200000U /* VG - internal use only */
#define CONVERTING 0x00400000U /* LV */
+#define MISSING_PV 0x00800000U /* PV */
+#define PARTIAL_LV 0x01000000U /* LV - derived flag, not
+ written out in metadata*/
+
+//#define POSTORDER_FLAG 0x02000000U /* Not a real flag, reserved for
+// temporary use inside vg_read. */
+
#define LVM_READ 0x00000100U /* LV VG */
#define LVM_WRITE 0x00000200U /* LV VG */
#define CLUSTERED 0x00000400U /* VG */
@@ -564,6 +571,7 @@
uint32_t pv_pe_count(const pv_t *pv);
uint32_t pv_pe_alloc_count(const pv_t *pv);
+int vg_missing_pv_count(const vg_t *vg);
uint32_t vg_status(const vg_t *vg);
#define vg_is_clustered(vg) (vg_status((vg)) & CLUSTERED)
--- LVM2/lib/metadata/metadata.c 2008/09/19 05:33:36 1.190
+++ LVM2/lib/metadata/metadata.c 2008/09/19 06:41:59 1.191
@@ -334,9 +334,9 @@
struct pv_list *pvl;
int ret = 1;
- if (!vg || !consistent || (vg_status(vg) & PARTIAL_VG)) {
- log_error("Volume group \"%s\" not found or inconsistent.",
- vg_name);
+ if (!vg || !consistent || vg_missing_pv_count(vg)) {
+ log_error("Volume group \"%s\" not found, is inconsistent "
+ "or has PVs missing.", vg_name);
log_error("Consider vgreduce --removemissing if metadata "
"is inconsistent.");
return 0;
@@ -488,19 +488,15 @@
struct volume_group *vg;
struct dm_pool *mem = cmd->mem;
int consistent = 0;
- int old_partial;
if (!(vg = dm_pool_zalloc(mem, sizeof(*vg))))
return_NULL;
/* is this vg name already in use ? */
- old_partial = partial_mode();
- init_partial(1);
if (vg_read(cmd, vg_name, NULL, &consistent)) {
log_err("A volume group called '%s' already exists.", vg_name);
goto bad;
}
- init_partial(old_partial);
if (!id_create(&vg->id)) {
log_err("Couldn't create uuid for volume group '%s'.", vg_name);
@@ -1191,6 +1187,157 @@
return 1;
}
+struct _lv_postorder_baton {
+ int (*fn)(struct logical_volume *lv, void *data);
+ void *data;
+};
+
+static int _lv_postorder_visit(struct logical_volume *,
+ int (*fn)(struct logical_volume *lv, void *data),
+ void *data);
+
+static int _lv_postorder_level(struct logical_volume *lv, void *data)
+{
+ struct _lv_postorder_baton *baton = data;
+ int r =_lv_postorder_visit(lv, baton->fn, baton->data);
+ lv->status |= POSTORDER_FLAG;
+ return r;
+};
+
+static int _lv_each_dependency(struct logical_volume *lv,
+ int (*fn)(struct logical_volume *lv, void *data),
+ void *data)
+{
+ int i, s;
+ struct lv_segment *lvseg;
+
+ struct logical_volume *deps[] = {
+ lv->snapshot ? lv->snapshot->origin : 0,
+ lv->snapshot ? lv->snapshot->cow : 0 };
+ for (i = 0; i < sizeof(deps) / sizeof(*deps); ++i) {
+ if (deps[i] && !fn(deps[i], data))
+ return_0;
+ }
+
+ list_iterate_items(lvseg, &lv->segments) {
+ if (lvseg->log_lv && !fn(lvseg->log_lv, data))
+ return_0;
+ for (s = 0; s < lvseg->area_count; ++s) {
+ if (seg_type(lvseg, s) == AREA_LV && !fn(seg_lv(lvseg,s), data))
+ return_0;
+ }
+ }
+ return 1;
+}
+
+static int _lv_postorder_cleanup(struct logical_volume *lv, void *data)
+{
+ if (!(lv->status & POSTORDER_FLAG))
+ return 1;
+ lv->status &= ~POSTORDER_FLAG;
+
+ if (!_lv_each_dependency(lv, _lv_postorder_cleanup, data))
+ return_0;
+ return 1;
+}
+
+static int _lv_postorder_visit(struct logical_volume *lv,
+ int (*fn)(struct logical_volume *lv, void *data),
+ void *data)
+{
+ struct _lv_postorder_baton baton;
+ int r;
+
+ if (lv->status & POSTORDER_FLAG)
+ return 1;
+
+ baton.fn = fn;
+ baton.data = data;
+ r = _lv_each_dependency(lv, _lv_postorder_level, &baton);
+ if (r) {
+ r = fn(lv, data);
+ log_verbose("visited %s", lv->name);
+ }
+ return r;
+}
+
+/*
+ * This will walk the LV dependency graph in depth-first order and in the
+ * postorder, call a callback function "fn". The void *data is passed along all
+ * the calls. The callback may return zero to indicate an error and terminate
+ * the depth-first walk. The error is propagated to return value of
+ * _lv_postorder.
+ */
+static int _lv_postorder(struct logical_volume *lv,
+ int (*fn)(struct logical_volume *lv, void *data),
+ void *data)
+{
+ int r;
+ r = _lv_postorder_visit(lv, fn, data);
+ _lv_postorder_cleanup(lv, 0);
+ return r;
+}
+
+struct _lv_mark_if_partial_baton {
+ int partial;
+};
+
+static int _lv_mark_if_partial_collect(struct logical_volume *lv, void *data)
+{
+ struct _lv_mark_if_partial_baton *baton = data;
+ if (lv->status & PARTIAL_LV)
+ baton->partial = 1;
+
+ return 1;
+}
+
+static int _lv_mark_if_partial_single(struct logical_volume *lv, void *data)
+{
+ int s;
+ struct _lv_mark_if_partial_baton baton;
+ struct lv_segment *lvseg;
+
+ list_iterate_items(lvseg, &lv->segments) {
+ for (s = 0; s < lvseg->area_count; ++s) {
+ if (seg_type(lvseg, s) == AREA_PV) {
+ if (seg_pv(lvseg, s)->status & MISSING_PV)
+ lv->status |= PARTIAL_LV;
+ }
+ }
+ }
+
+ baton.partial = 0;
+ _lv_each_dependency(lv, _lv_mark_if_partial_collect, &baton);
+
+ if (baton.partial)
+ lv->status |= PARTIAL_LV;
+
+ return 1;
+}
+
+static int _lv_mark_if_partial(struct logical_volume *lv)
+{
+ return _lv_postorder(lv, _lv_mark_if_partial_single, NULL);
+}
+
+/*
+ * Mark LVs with missing PVs using PARTIAL_LV status flag. The flag is
+ * propagated transitively, so LVs referencing other LVs are marked
+ * partial as well, if any of their referenced LVs are marked partial.
+ */
+static int _vg_mark_partial_lvs(struct volume_group *vg)
+{
+ struct logical_volume *lv;
+ struct lv_list *lvl;
+
+ list_iterate_items(lvl, &vg->lvs) {
+ lv = lvl->lv;
+ if (!_lv_mark_if_partial(lv))
+ return_0;
+ }
+ return 1;
+}
+
int vg_validate(struct volume_group *vg)
{
struct pv_list *pvl, *pvl2;
@@ -1295,8 +1442,13 @@
return_0;
if (vg->status & PARTIAL_VG) {
- log_error("Cannot change metadata for partial volume group %s",
- vg->name);
+ log_error("Cannot update partial volume group %s.", vg->name);
+ return 0;
+ }
+
+ if (vg_missing_pv_count(vg) && !vg->cmd->handles_missing_pvs) {
+ log_error("Cannot update volume group %s while physical "
+ "volumes are missing.", vg->name);
return 0;
}
@@ -1495,9 +1647,20 @@
return 1;
}
+int vg_missing_pv_count(const vg_t *vg)
+{
+ int ret = 0;
+ struct pv_list *pvl;
+ list_iterate_items(pvl, &vg->pvs) {
+ if (pvl->pv->status & MISSING_PV)
+ ++ ret;
+ }
+ return ret;
+}
+
/* Caller sets consistent to 1 if it's safe for vg_read to correct
* inconsistent metadata on disk (i.e. the VG write lock is held).
- * This guarantees only consistent metadata is returned unless PARTIAL_VG.
+ * This guarantees only consistent metadata is returned.
* If consistent is 0, caller must check whether consistent == 1 on return
* and take appropriate action if it isn't (e.g. abort; get write lock
* and call vg_read again).
@@ -1536,6 +1699,11 @@
}
if ((correct_vg = lvmcache_get_vg(vgid, precommitted))) {
+ if (vg_missing_pv_count(correct_vg)) {
+ log_verbose("There are %d physical volumes missing.",
+ vg_missing_pv_count(correct_vg));
+ _vg_mark_partial_lvs(correct_vg);
+ }
*consistent = 1;
return correct_vg;
}
@@ -1631,7 +1799,8 @@
}
}
- if (list_size(&correct_vg->pvs) != list_size(pvids)) {
+ if (list_size(&correct_vg->pvs) != list_size(pvids)
+ + vg_missing_pv_count(correct_vg)) {
log_debug("Cached VG %s had incorrect PV list",
vgname);
@@ -1640,6 +1809,8 @@
else
correct_vg = NULL;
} else list_iterate_items(pvl, &correct_vg->pvs) {
+ if (pvl->pv->status & MISSING_PV)
+ continue;
if (!str_list_match_item(pvids, pvl->pv->dev->pvid)) {
log_debug("Cached VG %s had incorrect PV list",
vgname);
@@ -1722,15 +1893,6 @@
if (!*consistent)
return correct_vg;
- /* Don't touch partial volume group metadata */
- /* Should be fixed manually with vgcfgbackup/restore etc. */
- if ((correct_vg->status & PARTIAL_VG)) {
- log_error("Inconsistent metadata copies found for "
- "partial volume group %s", vgname);
- *consistent = 0;
- return correct_vg;
- }
-
/* Don't touch if vgids didn't match */
if (inconsistent_vgid) {
log_error("Inconsistent metadata UUIDs found for "
@@ -1769,6 +1931,12 @@
}
}
+ if (vg_missing_pv_count(correct_vg)) {
+ log_verbose("There are %d physical volumes missing.",
+ vg_missing_pv_count(correct_vg));
+ _vg_mark_partial_lvs(correct_vg);
+ }
+
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
log_error("WARNING: Interrupted pvmove detected in "
"volume group %s", correct_vg->name);
@@ -1828,11 +1996,10 @@
if ((vg = _vg_read(cmd, NULL, vgid,
&consistent, precommitted)) &&
!strncmp((char *)vg->id.uuid, vgid, ID_LEN)) {
+
if (!consistent) {
log_error("Volume group %s metadata is "
"inconsistent", vg->name);
- if (!partial_mode())
- return NULL;
}
return vg;
}
@@ -1860,6 +2027,7 @@
if ((vg = _vg_read(cmd, vgname, vgid, &consistent,
precommitted)) &&
!strncmp((char *)vg->id.uuid, vgid, ID_LEN)) {
+
if (!consistent) {
log_error("Volume group %s metadata is "
"inconsistent", vgname);
@@ -1993,7 +2161,6 @@
struct list *vgids;
struct volume_group *vg;
int consistent = 0;
- int old_partial;
int old_pvmove;
lvmcache_label_scan(cmd, 0);
@@ -2015,9 +2182,7 @@
/* Read every VG to ensure cache consistency */
/* Orphan VG is last on list */
- old_partial = partial_mode();
old_pvmove = pvmove_mode();
- init_partial(1);
init_pvmove(1);
list_iterate_items(strl, vgids) {
vgid = strl->str;
@@ -2042,7 +2207,6 @@
list_add(results, pvh);
}
init_pvmove(old_pvmove);
- init_partial(old_partial);
if (pvslist)
*pvslist = results;
--- LVM2/lib/metadata/metadata.h 2008/09/19 04:28:58 1.181
+++ LVM2/lib/metadata/metadata.h 2008/09/19 06:41:59 1.182
@@ -61,6 +61,14 @@
//#define MIRROR_NOTSYNCED 0x00080000U /* LV */
#define ACTIVATE_EXCL 0x00100000U /* LV - internal use only */
#define PRECOMMITTED 0x00200000U /* VG - internal use only */
+//#define CONVERTING 0x00400000U /* LV */
+
+//#define MISSING_PV 0x00800000U /* PV */
+//#define PARTIAL_LV 0x01000000U /* LV - derived flag, not
+// written out in metadata*/
+
+#define POSTORDER_FLAG 0x02000000U /* Not a real flag, reserved for
+ temporary use inside vg_read. */
//#define LVM_READ 0x00000100U /* LV VG */
//#define LVM_WRITE 0x00000200U /* LV VG */
--- LVM2/lib/report/report.c 2008/06/25 16:52:27 1.87
+++ LVM2/lib/report/report.c 2008/09/19 06:41:59 1.88
@@ -439,7 +439,7 @@
else
repstr[2] = '-';
- if (vg->status & PARTIAL_VG)
+ if (vg_missing_pv_count(vg))
repstr[3] = 'p';
else
repstr[3] = '-';
--- LVM2/man/lvm.conf.5 2008/04/10 18:50:02 1.22
+++ LVM2/man/lvm.conf.5 2008/09/19 06:41:59 1.23
@@ -300,12 +300,16 @@
.TP
\fBactivation\fP \(em Settings affecting device-mapper activation
.IP
-\fBmissing_stripe_filler\fP \(em When activating an incomplete
-logical volume in partial mode, this missing data is replaced
-with this device. It could perhaps be a block device that always
-returns an error when it is accessed, or one that always
-returns zeros. See \fBlvcreate\fP (8) for how to create
-such devices.
+\fBmissing_stripe_filler\fP \(em When activating an incomplete logical
+volume in partial mode, this option dictates how the missing data is
+replaced. A value of "error" will cause activation to create error
+mappings for the missing data, meaning that read access to missing
+portions of the volume will result in I/O errors. You can instead also
+use a device path, and in that case this device will be used in place of
+missing stripes. However, note that using anything other than
+"error" with mirrored or snapshotted volumes is likely to result in data
+corruption. For instructions on how to create a device that always
+returns zeros, see \fBlvcreate\fP (8).
.IP
\fBmirror_region_size\fP \(em Unit size in KB for copy operations
when mirroring.
--- LVM2/man/vgreduce.8 2003/01/17 21:04:26 1.3
+++ LVM2/man/vgreduce.8 2008/09/19 06:41:59 1.4
@@ -18,11 +18,13 @@
Removes all empty physical volumes if none are given on command line.
.TP
.I \-\-removemissing
-Removes all missing physical volumes from the volume group and makes
-the volume group consistent again.
+Removes all missing physical volumes from the volume group, if there are no
+logical volumes allocated on those. This resumes normal operation of the volume
+group (new logical volumes may again be created, changed and so on).
-It's a good idea to run this option with --test first to find out what it
-would remove before running it for real.
+If this is not possible (there are logical volumes referencing the missing
+physical volumes) and you cannot or do not want to remove them manually, you
+can run this option with --force to have vgreduce remove any partial LVs.
Any logical volumes and dependent snapshots that were partly on the
missing disks get removed completely. This includes those parts
--- LVM2/tools/commands.h 2008/06/24 22:48:53 1.118
+++ LVM2/tools/commands.h 2008/09/19 06:42:00 1.119
@@ -850,13 +850,15 @@
"\t[-h|--help]\n"
"\t[--mirrorsonly]\n"
"\t[--removemissing]\n"
+ "\t[-f|--force]\n"
"\t[-t|--test]\n"
"\t[-v|--verbose]\n"
"\t[--version]" "\n"
"\tVolumeGroupName\n"
"\t[PhysicalVolumePath...]\n",
- all_ARG, autobackup_ARG, mirrorsonly_ARG, removemissing_ARG, test_ARG)
+ all_ARG, autobackup_ARG, mirrorsonly_ARG, removemissing_ARG,
+ force_ARG, test_ARG)
xx(vgremove,
"Remove volume group(s)",
--- LVM2/tools/lvmcmdline.c 2008/08/01 19:51:27 1.69
+++ LVM2/tools/lvmcmdline.c 2008/09/19 06:42:00 1.70
@@ -710,13 +710,13 @@
cmd->current_settings.archive = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.archive);
cmd->current_settings.backup = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.backup);
cmd->current_settings.cache_vgmetadata = cmd->command->flags & CACHE_VGMETADATA ? 1 : 0;
+ cmd->partial_activate = 0;
if (arg_count(cmd, partial_ARG)) {
- init_partial(1);
+ cmd->partial_activate = 1;
log_print("Partial mode. Incomplete volume groups will "
"be activated read-only.");
- } else
- init_partial(0);
+ }
if (arg_count(cmd, ignorelockingfailure_ARG))
init_ignorelockingfailure(1);
@@ -826,6 +826,7 @@
cmd->fmt = arg_ptr_value(cmd, metadatatype_ARG,
cmd->current_settings.fmt);
+ cmd->handles_missing_pvs = 0;
}
static char *_copy_command_line(struct cmd_context *cmd, int argc, char **argv)
--- LVM2/tools/lvremove.c 2008/01/30 14:00:02 1.54
+++ LVM2/tools/lvremove.c 2008/09/19 06:42:00 1.55
@@ -31,6 +31,8 @@
return EINVALID_CMD_LINE;
}
+ cmd->handles_missing_pvs = 1;
+
return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, NULL,
&lvremove_single);
}
--- LVM2/tools/pvcreate.c 2008/07/29 21:05:20 1.74
+++ LVM2/tools/pvcreate.c 2008/09/19 06:42:00 1.75
@@ -49,7 +49,6 @@
/* FIXME Check partition type is LVM unless --force is given */
/* Is there a pv here already? */
- /* FIXME Use partial mode here? */
pv = pv_read(cmd, name, NULL, NULL, 0);
/*
@@ -272,13 +271,11 @@
if (arg_count(cmd, restorefile_ARG)) {
pp->restorefile = arg_str_value(cmd, restorefile_ARG, "");
/* The uuid won't already exist */
- init_partial(1);
if (!(vg = backup_read_vg(cmd, NULL, pp->restorefile))) {
log_error("Unable to read volume group from %s",
pp->restorefile);
return 0;
}
- init_partial(0);
if (!(existing_pv = find_pv_in_vg_by_uuid(vg, pp->idp))) {
log_error("Can't find uuid %s in backup file %s",
uuid, pp->restorefile);
--- LVM2/tools/vgcfgbackup.c 2008/08/13 12:44:24 1.25
+++ LVM2/tools/vgcfgbackup.c 2008/09/19 06:42:00 1.26
@@ -96,8 +96,7 @@
int ret;
char *last_filename = NULL;
- if (partial_mode())
- init_pvmove(1);
+ init_pvmove(1);
ret = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, &last_filename,
&vg_backup_single);
--- LVM2/tools/vgreduce.c 2008/09/19 03:45:34 1.82
+++ LVM2/tools/vgreduce.c 2008/09/19 06:42:00 1.83
@@ -16,7 +16,7 @@
#include "tools.h"
#include "lv_alloc.h"
-static int _remove_pv(struct volume_group *vg, struct pv_list *pvl)
+static int _remove_pv(struct volume_group *vg, struct pv_list *pvl, int silent)
{
char uuid[64] __attribute((aligned(8)));
@@ -31,8 +31,9 @@
log_verbose("Removing PV with UUID %s from VG %s", uuid, vg->name);
if (pvl->pv->pe_alloc_count) {
- log_error("LVs still present on PV with UUID %s: Can't remove "
- "from VG %s", uuid, vg->name);
+ if (!silent)
+ log_error("LVs still present on PV with UUID %s: "
+ "Can't remove from VG %s", uuid, vg->name);
return 0;
}
@@ -130,11 +131,39 @@
return 1;
}
+static int _consolidate_vg(struct cmd_context *cmd, struct volume_group *vg)
+{
+ struct pv_list *pvl;
+ struct lv_list *lvl;
+ int r = 1;
+
+ list_iterate_items(lvl, &vg->lvs)
+ if (lvl->lv->status & PARTIAL_LV) {
+ log_warn("WARNING: Partial LV %s needs to be repaired "
+ "or removed. ", lvl->lv->name);
+ r = 0;
+ }
+
+ if (!r) {
+ cmd->handles_missing_pvs = 1;
+ log_warn("WARNING: There are still partial LVs in VG %s.", vg->name);
+ log_warn("To remove them unconditionally use: vgreduce --removemissing --force.");
+ log_warn("Proceeding to remove empty missing PVs.");
+ }
+
+ list_iterate_items(pvl, &vg->pvs) {
+ if (pvl->pv->dev && !(pvl->pv->status & MISSING_PV))
+ continue;
+ if (r && !_remove_pv(vg, pvl, 0))
+ return_0;
+ }
+
+ return r;
+}
+
static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
{
- struct list *pvh, *pvht;
struct list *lvh, *lvht;
- struct pv_list *pvl;
struct lv_list *lvl, *lvl2, *lvlt;
struct logical_volume *lv;
struct physical_volume *pv;
@@ -182,20 +211,8 @@
return 0;
}
- /* Remove missing PVs */
- list_iterate_safe(pvh, pvht, &vg->pvs) {
- pvl = list_item(pvh, struct pv_list);
- if (pvl->pv->dev)
- continue;
- if (!_remove_pv(vg, pvl))
- return_0;
- }
-
- /* VG is now consistent */
- vg->status &= ~PARTIAL_VG;
- vg->status |= LVM_WRITE;
-
- init_partial(0);
+ if (!_consolidate_vg(cmd, vg))
+ return_0;
/* FIXME Recovery. For now people must clean up by hand. */
@@ -208,14 +225,11 @@
if (!test_mode()) {
/* Suspend lvs_changed */
- init_partial(1);
if (!suspend_lvs(cmd, &lvs_changed)) {
stack;
- init_partial(0);
vg_revert(vg);
return 0;
}
- init_partial(0);
}
if (!vg_commit(vg)) {
@@ -439,26 +453,26 @@
char *vg_name;
int ret = 1;
int consistent = 1;
+ int fixed = 1;
+ int repairing = arg_count(cmd, removemissing_ARG);
- if (!argc && !arg_count(cmd, removemissing_ARG)) {
+ if (!argc && !repairing) {
log_error("Please give volume group name and "
"physical volume paths");
return EINVALID_CMD_LINE;
}
-
- if (!argc && arg_count(cmd, removemissing_ARG)) {
+
+ if (!argc && repairing) {
log_error("Please give volume group name");
return EINVALID_CMD_LINE;
}
- if (arg_count(cmd, mirrorsonly_ARG) &&
- !arg_count(cmd, removemissing_ARG)) {
+ if (arg_count(cmd, mirrorsonly_ARG) && !repairing) {
log_error("--mirrorsonly requires --removemissing");
return EINVALID_CMD_LINE;
}
- if (argc == 1 && !arg_count(cmd, all_ARG)
- && !arg_count(cmd, removemissing_ARG)) {
+ if (argc == 1 && !arg_count(cmd, all_ARG) && !repairing) {
log_error("Please enter physical volume paths or option -a");
return EINVALID_CMD_LINE;
}
@@ -469,7 +483,7 @@
return EINVALID_CMD_LINE;
}
- if (argc > 1 && arg_count(cmd, removemissing_ARG)) {
+ if (argc > 1 && repairing) {
log_error("Please only specify the volume group");
return EINVALID_CMD_LINE;
}
@@ -490,8 +504,8 @@
return ECMD_FAILED;
}
- if ((!(vg = vg_read(cmd, vg_name, NULL, &consistent)) || !consistent) &&
- !arg_count(cmd, removemissing_ARG)) {
+ if ((!(vg = vg_read(cmd, vg_name, NULL, &consistent)) || !consistent)
+ && !repairing) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
@@ -502,16 +516,15 @@
return ECMD_FAILED;
}
- if (arg_count(cmd, removemissing_ARG)) {
- if (vg && consistent) {
+ if (repairing) {
+ if (vg && consistent && !vg_missing_pv_count(vg)) {
log_error("Volume group \"%s\" is already consistent",
vg_name);
unlock_vg(cmd, vg_name);
return ECMD_PROCESSED;
}
- init_partial(1);
- consistent = 0;
+ consistent = !arg_count(cmd, force_ARG);
if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) {
log_error("Volume group \"%s\" not found", vg_name);
unlock_vg(cmd, vg_name);
@@ -522,16 +535,17 @@
return ECMD_FAILED;
}
if (!archive(vg)) {
- init_partial(0);
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
}
- if (!_make_vg_consistent(cmd, vg)) {
- init_partial(0);
- unlock_vg(cmd, vg_name);
- return ECMD_FAILED;
- }
+ if (arg_count(cmd, force_ARG)) {
+ if (!_make_vg_consistent(cmd, vg)) {
+ unlock_vg(cmd, vg_name);
+ return ECMD_FAILED;
+ }
+ } else
+ fixed = _consolidate_vg(cmd, vg);
if (!vg_write(vg) || !vg_commit(vg)) {
log_error("Failed to write out a consistent VG for %s",
@@ -542,7 +556,9 @@
backup(vg);
- log_print("Wrote out consistent volume group %s", vg_name);
+ if (fixed)
+ log_print("Wrote out consistent volume group %s",
+ vg_name);
} else {
if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE | RESIZEABLE_VG)) {
More information about the lvm-devel
mailing list