summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2002-11-18 14:04:08 +0000
committerAlasdair Kergon <agk@redhat.com>2002-11-18 14:04:08 +0000
commit5a52dca9c26ade9f233abcf5213300560d7a13a9 (patch)
tree9afbc621c07148c96a1ba1878a262dbd8aec613a /tools
parentd1d9800ef1c7ec38a5f72b8e2586f927ab68188c (diff)
downloadlvm2-5a52dca9c26ade9f233abcf5213300560d7a13a9.tar.gz
lvm2-5a52dca9c26ade9f233abcf5213300560d7a13a9.tar.xz
lvm2-5a52dca9c26ade9f233abcf5213300560d7a13a9.zip
Some new features.
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.in2
-rw-r--r--tools/archive.c160
-rw-r--r--tools/archive.h5
-rw-r--r--tools/args.h6
-rw-r--r--tools/commands.h85
-rw-r--r--tools/lvchange.c221
-rw-r--r--tools/lvcreate.c71
-rw-r--r--tools/lvdisplay.c11
-rw-r--r--tools/lvm.c889
-rw-r--r--tools/lvmdiskscan.c4
-rw-r--r--tools/lvremove.c31
-rw-r--r--tools/lvrename.c17
-rw-r--r--tools/lvresize.c16
-rw-r--r--tools/lvscan.c82
-rw-r--r--tools/pvchange.c157
-rw-r--r--tools/pvcreate.c117
-rw-r--r--tools/pvdisplay.c105
-rw-r--r--tools/pvremove.c128
-rw-r--r--tools/pvscan.c178
-rw-r--r--tools/stub.h2
-rw-r--r--tools/toollib.c212
-rw-r--r--tools/toollib.h32
-rw-r--r--tools/tools.h62
-rw-r--r--tools/vgcfgbackup.c51
-rw-r--r--tools/vgcfgrestore.c18
-rw-r--r--tools/vgchange.c142
-rw-r--r--tools/vgck.c31
-rw-r--r--tools/vgconvert.c185
-rw-r--r--tools/vgcreate.c5
-rw-r--r--tools/vgdisplay.c88
-rw-r--r--tools/vgexport.c47
-rw-r--r--tools/vgextend.c6
-rw-r--r--tools/vgimport.c44
-rw-r--r--tools/vgmerge.c68
-rw-r--r--tools/vgreduce.c118
-rw-r--r--tools/vgremove.c52
-rw-r--r--tools/vgrename.c37
-rw-r--r--tools/vgscan.c48
-rw-r--r--tools/vgsplit.c26
39 files changed, 1859 insertions, 1700 deletions
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 800b43eb..42ae8aef 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -37,6 +37,7 @@ SOURCES=\
pvchange.c \
pvcreate.c \
pvdisplay.c \
+ pvremove.c \
pvscan.c \
toollib.c \
vgcfgbackup.c \
@@ -44,6 +45,7 @@ SOURCES=\
vgchange.c \
vgck.c \
vgcreate.c \
+ vgconvert.c \
vgdisplay.c \
vgexport.c \
vgextend.c \
diff --git a/tools/archive.c b/tools/archive.c
index 15251b51..8fdafc26 100644
--- a/tools/archive.c
+++ b/tools/archive.c
@@ -4,18 +4,8 @@
* This file is released under the GPL.
*/
-#include "log.h"
-#include "archive.h"
-#include "dbg_malloc.h"
-#include "format-text.h"
-#include "lvm-string.h"
-#include "toollib.h"
-
#include "tools.h"
-#include <unistd.h>
-#include <limits.h>
-
static struct {
int enabled;
char *dir;
@@ -97,7 +87,7 @@ int archive(struct volume_group *vg)
return 1;
if (test_mode()) {
- log_print("Test mode: Skipping archiving of volume group.");
+ log_verbose("Test mode: Skipping archiving of volume group.");
return 1;
}
@@ -113,7 +103,7 @@ int archive(struct volume_group *vg)
int archive_display(struct cmd_context *cmd, const char *vg_name)
{
- return archive_list(cmd, cmd->um, _archive_params.dir, vg_name);
+ return archive_list(cmd, _archive_params.dir, vg_name);
}
static struct {
@@ -153,11 +143,8 @@ void backup_enable(int flag)
static int __backup(struct volume_group *vg)
{
- int r;
- struct format_instance *tf;
char name[PATH_MAX];
char *desc;
- void *context;
if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 0))) {
stack;
@@ -173,20 +160,7 @@ static int __backup(struct volume_group *vg)
log_verbose("Creating volume group backup \"%s\"", name);
- if (!(context = create_text_context(vg->cmd->fmtt, name, desc)) ||
- !(tf = vg->cmd->fmtt->ops->create_instance(vg->cmd->fmtt, NULL,
- context))) {
- stack;
- return 0;
- }
-
- if (!(r = tf->fmt->ops->vg_write(tf, vg, context)) ||
- !(r = tf->fmt->ops->vg_commit(tf, vg, context)))
- stack;
-
- tf->fmt->ops->destroy_instance(tf);
-
- return r;
+ return backup_to_file(name, desc, vg);
}
int backup(struct volume_group *vg)
@@ -197,7 +171,7 @@ int backup(struct volume_group *vg)
}
if (test_mode()) {
- log_print("Test mode: Skipping volume group backup.");
+ log_verbose("Test mode: Skipping volume group backup.");
return 1;
}
@@ -227,57 +201,73 @@ int backup_remove(const char *vg_name)
return 1;
}
-static struct volume_group *_read_vg(struct cmd_context *cmd,
- const char *vg_name, const char *file)
+struct volume_group *backup_read_vg(struct cmd_context *cmd,
+ const char *vg_name, const char *file)
{
struct volume_group *vg;
struct format_instance *tf;
+ struct list *mdah;
+ struct metadata_area *mda;
void *context;
- if (!(context = create_text_context(cmd->fmtt, file,
+ if (!(context = create_text_context(cmd, file,
cmd->cmd_line)) ||
- !(tf = cmd->fmtt->ops->create_instance(cmd->fmtt, NULL, context))) {
+ !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
+ context))) {
log_error("Couldn't create text format object.");
return NULL;
}
- if (!(vg = tf->fmt->ops->vg_read(tf, vg_name, context)))
- stack;
+ list_iterate(mdah, &tf->metadata_areas) {
+ mda = list_item(mdah, struct metadata_area);
+ if (!(vg = mda->ops->vg_read(tf, vg_name, mda)))
+ stack;
+ break;
+ }
tf->fmt->ops->destroy_instance(tf);
return vg;
}
-int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
- const char *file)
+/* ORPHAN and VG locks held before calling this */
+int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
{
- struct volume_group *vg;
+ struct list *pvh;
+ struct physical_volume *pv;
+ struct cache_info *info;
/*
- * Read in the volume group.
+ * FIXME: Check that the PVs referenced in the backup are
+ * not members of other existing VGs.
*/
- if (!(vg = _read_vg(cmd, vg_name, file))) {
- stack;
+
+ /* Attempt to write out using currently active format */
+ if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
+ NULL))) {
+ log_error("Failed to allocate format instance");
return 0;
}
- /*
- * Check that those pv's referenced in the backup are
- * currently orphans or members of the vg.s
- */
- /*
- * FIXME: waiting for label code.
- */
-
- /*
- * Write the vg.
- */
-
- /* FIXME How do I find what format to write out the VG in? */
- /* Must store the format type inside the backup? */
- if (!(vg->fid = cmd->fmt1->ops->create_instance(cmd->fmt1, NULL, NULL))) {
- log_error("Failed to allocate format1 instance");
- return 0;
+ /* Add any metadata areas on the PVs */
+ list_iterate(pvh, &vg->pvs) {
+ pv = list_item(pvh, struct pv_list)->pv;
+ if (!(info = info_from_pvid(pv->dev->pvid))) {
+ log_error("PV %s missing from cache",
+ dev_name(pv->dev));
+ return 0;
+ }
+ if (cmd->fmt != info->fmt) {
+ log_error("PV %s is a different format (%s)",
+ dev_name(pv->dev), info->fmt->name);
+ return 0;
+ }
+ if (!vg->fid->fmt->ops->
+ pv_setup(vg->fid->fmt, 0, 0, 0, 0, 0,
+ &vg->fid->metadata_areas, pv, vg)) {
+ log_error("Format-specific setup for %s failed",
+ dev_name(pv->dev));
+ return 0;
+ }
}
if (!vg_write(vg)) {
@@ -288,6 +278,23 @@ int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
return 1;
}
+/* ORPHAN and VG locks held before calling this */
+int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
+ const char *file)
+{
+ struct volume_group *vg;
+
+ /*
+ * Read in the volume group from the text file.
+ */
+ if (!(vg = backup_read_vg(cmd, vg_name, file))) {
+ stack;
+ return 0;
+ }
+
+ return backup_restore_vg(cmd, vg);
+}
+
int backup_restore(struct cmd_context *cmd, const char *vg_name)
{
char path[PATH_MAX];
@@ -300,3 +307,38 @@ int backup_restore(struct cmd_context *cmd, const char *vg_name)
return backup_restore_from_file(cmd, vg_name, path);
}
+
+int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
+{
+ int r;
+ struct format_instance *tf;
+ struct list *mdah;
+ struct metadata_area *mda;
+ void *context;
+ struct cmd_context *cmd;
+
+ cmd = vg->cmd;
+
+ if (!(context = create_text_context(cmd, file, desc)) ||
+ !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
+ context))) {
+ log_error("Couldn't create backup object.");
+ return 0;
+ }
+
+ /* Write and commit the metadata area */
+ list_iterate(mdah, &tf->metadata_areas) {
+ mda = list_item(mdah, struct metadata_area);
+ if (!(r = mda->ops->vg_write(tf, vg, mda))) {
+ stack;
+ continue;
+ }
+ if (mda->ops->vg_commit &&
+ !(r = mda->ops->vg_commit(tf, vg, mda))) {
+ stack;
+ }
+ }
+
+ tf->fmt->ops->destroy_instance(tf);
+ return r;
+}
diff --git a/tools/archive.h b/tools/archive.h
index f0f34eb2..157ae805 100644
--- a/tools/archive.h
+++ b/tools/archive.h
@@ -42,8 +42,13 @@ void backup_enable(int flag);
int backup(struct volume_group *vg);
int backup_remove(const char *vg_name);
+struct volume_group *backup_read_vg(struct cmd_context *cmd,
+ const char *vg_name, const char *file);
+int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg);
int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
const char *file);
int backup_restore(struct cmd_context *cmd, const char *vg_name);
+int backup_to_file(const char *file, const char *desc, struct volume_group *vg);
+
#endif
diff --git a/tools/args.h b/tools/args.h
index ecfb1d12..15d47349 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -12,6 +12,11 @@ arg(version_ARG, '\0', "version", NULL)
arg(quiet_ARG, '\0', "quiet", NULL)
arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", size_arg)
arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", NULL)
+arg(metadatacopies_ARG, '\0', "metadatacopies", int_arg)
+arg(metadatasize_ARG, '\0', "metadatasize", size_arg)
+arg(restorefile_ARG, '\0', "restorefile", string_arg)
+arg(labelsector_ARG, '\0', "labelsector", int_arg)
+arg(driverloaded_ARG, '\0', "driverloaded", yes_no_arg)
/* Allow some variations */
arg(resizable_ARG, '\0', "resizable", yes_no_arg)
@@ -77,4 +82,3 @@ arg(zero_ARG, 'Z', "zero", yes_no_arg)
/* this should always be last */
arg(ARG_COUNT, '-', "", NULL)
-
diff --git a/tools/commands.h b/tools/commands.h
index 672cb2f2..b2e4868c 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -18,6 +18,21 @@
*
*/
+/*********** Replace with script?
+xx(e2fsadm,
+ "Resize logical volume and ext2 filesystem",
+ "e2fsadm "
+ "[-d|--debug] " "[-h|--help] " "[-n|--nofsck]" "\n"
+ "\t{[-l|--extents] [+|-]LogicalExtentsNumber |" "\n"
+ "\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtT]}" "\n"
+ "\t[-t|--test] " "\n"
+ "\t[-v|--verbose] " "\n"
+ "\t[--version] " "\n"
+ "\tLogicalVolumePath" "\n",
+
+ extents_ARG, size_ARG, nofsck_ARG, test_ARG)
+*********/
+
xx(help,
"Display help for commands",
"help <command>" "\n")
@@ -40,6 +55,7 @@ xx(lvchange,
"\t[-C/--contiguous y/n]\n"
"\t[-d/--debug]\n"
"\t[-h/-?/--help]\n"
+ "\t[--ignorelockingfailure]\n"
"\t[-M/--persistent y/n] [--minor minor]\n"
"\t[-P/--partial] " "\n"
"\t[-p/--permission r/rw]\n"
@@ -84,14 +100,14 @@ xx(lvdisplay,
"lvdisplay\n"
"\t[-c/--colon]\n"
"\t[-d/--debug]\n"
- "\t[-D/--disk]\n"
"\t[-h/-?/--help]\n"
"\t[-m/--maps]\n"
"\t[-P/--partial] " "\n"
"\t[-v/--verbose]\n"
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
- colon_ARG, disk_ARG, maps_ARG, partial_ARG, ignorelockingfailure_ARG)
+ colon_ARG, disk_ARG, maps_ARG, partial_ARG,
+ ignorelockingfailure_ARG)
xx(lvextend,
"Add space to a logical volume",
@@ -106,8 +122,8 @@ xx(lvextend,
"\t[-v/--verbose]\n"
"\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
- autobackup_ARG, extents_ARG, size_ARG, stripes_ARG, stripesize_ARG,
- test_ARG)
+ autobackup_ARG, extents_ARG, size_ARG, stripes_ARG,
+ stripesize_ARG, test_ARG)
xx(lvmchange,
"With the device mapper, this is obsolete and does nothing.",
@@ -212,7 +228,6 @@ xx(lvscan,
"lvscan " "\n"
"\t[-b|--blockdevice] " "\n"
"\t[-d|--debug] " "\n"
- "\t[-D|--disk]" "\n"
"\t[-h|--help] " "\n"
"\t[-P|--partial] " "\n"
"\t[-v|--verbose] " "\n"
@@ -237,18 +252,25 @@ xx(pvchange,
xx(pvcreate,
"Initialize physical volume(s) for use by LVM",
"pvcreate " "\n"
+ "\t[--restorefile file]\n"
"\t[-d|--debug]" "\n"
"\t[-f[f]|--force [--force]] " "\n"
"\t[-h|--help] " "\n"
- "\t[-y|--yes]" "\n"
- "\t[-s|--size PhysicalVolumeSize[kKmMgGtT]" "\n"
+ "\t[--labelsector sector] " "\n"
+ "\t[-M|--metadatatype 1|2]" "\n"
+ "\t[--metadatacopies #copies]" "\n"
+ "\t[--metadatasize MetadataSize[kKmMgGtT]]" "\n"
+ "\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtT]" "\n"
"\t[-t|--test] " "\n"
"\t[-u|--uuid uuid] " "\n"
"\t[-v|--verbose] " "\n"
+ "\t[-y|--yes]" "\n"
"\t[--version] " "\n"
"\tPhysicalVolume [PhysicalVolume...]\n",
- force_ARG, test_ARG, physicalvolumesize_ARG, uuidstr_ARG, yes_ARG)
+ force_ARG, test_ARG, labelsector_ARG, metadatatype_ARG, metadatacopies_ARG,
+ metadatasize_ARG, physicalvolumesize_ARG, restorefile_ARG, uuidstr_ARG,
+ yes_ARG)
xx(pvdata,
"Display the on-disk metadata for physical volume(s)",
@@ -297,9 +319,26 @@ xx(pvmove,
autobackup_ARG, force_ARG, name_ARG, test_ARG)
+xx(pvremove,
+ "Remove LVM label(s) from physical volume(s)",
+ "pvremove " "\n"
+ "\t[-d|--debug]" "\n"
+ "\t[-f[f]|--force [--force]] " "\n"
+ "\t[-h|--help] " "\n"
+ "\t[-y|--yes]" "\n"
+ "\t[-t|--test] " "\n"
+ "\t[-v|--verbose] " "\n"
+ "\t[-y|--yes]" "\n"
+ "\t[--version] " "\n"
+ "\tPhysicalVolume [PhysicalVolume...]\n",
+
+ force_ARG, test_ARG, yes_ARG)
+
xx(pvresize,
"Resize a physical volume in use by a volume group",
- "pvmove "
+ "Not implemented. Use pvcreate options.",
+/***
+ "pvresize "
"[-A|--autobackup {y|n}] "
"[-d|--debug] "
"[-h|--help]\n\t"
@@ -307,7 +346,7 @@ xx(pvresize,
"[-v|--verbose] "
"[--version]\n\t"
"\tPhysicalVolumePath [PhysicalVolumePath...]\n",
-
+***/
autobackup_ARG, physicalvolumesize_ARG)
xx(pvscan,
@@ -343,6 +382,7 @@ xx(vgcfgrestore,
"\t[-d|--debug] " "\n"
"\t[-f|--file filename] " "\n"
"\t[-l[l]|--list [--list]]" "\n"
+ "\t[-M|--metadatatype 1|2]" "\n"
"\t[-n|--name VolumeGroupName] " "\n"
"\t[-h|--help]" "\n"
"\t[-t|--test] " "\n"
@@ -350,7 +390,7 @@ xx(vgcfgrestore,
"\t[--version] " "\n"
"\tVolumeGroupName",
- file_ARG, list_ARG, name_ARG, test_ARG)
+ file_ARG, list_ARG, metadatatype_ARG, name_ARG, test_ARG)
xx(vgchange,
"Change volume group attributes",
@@ -379,6 +419,23 @@ xx(vgck,
"\t[-v/--verbose]\n"
"\t[VolumeGroupName...]\n" )
+xx(vgconvert,
+ "Change volume group metadata format",
+ "vgconvert " "\n"
+ "\t[-d|--debug]" "\n"
+ "\t[-h|--help] " "\n"
+ "\t[--labelsector sector] " "\n"
+ "\t[-M|--metadatatype 1|2]" "\n"
+ "\t[--metadatacopies #copies]" "\n"
+ "\t[--metadatasize MetadataSize[kKmMgGtT]]" "\n"
+ "\t[-t|--test] " "\n"
+ "\t[-v|--verbose] " "\n"
+ "\t[--version] " "\n"
+ "\tVolumeGroupName [VolumeGroupName...]\n",
+
+ force_ARG, test_ARG, labelsector_ARG, metadatatype_ARG, metadatacopies_ARG,
+ metadatasize_ARG )
+
xx(vgcreate,
"Create a volume group",
"vgcreate" "\n"
@@ -386,7 +443,7 @@ xx(vgcreate,
"\t[-d|--debug]" "\n"
"\t[-h|--help]" "\n"
"\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
- "\t[-M|--metadatatype lvm1/text] " "\n"
+ "\t[-M|--metadatatype 1|2] " "\n"
"\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n"
"\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtT]] " "\n"
"\t[-t|--test] " "\n"
@@ -403,6 +460,7 @@ xx(vgdisplay,
"\t[-c|--colon | -s|--short | -v|--verbose]" "\n"
"\t[-d|--debug] " "\n"
"\t[-h|--help] " "\n"
+ "\t[--ignorelockingfailure]" "\n"
"\t[-P|--partial] " "\n"
"\t[-A|--activevolumegroups | [-D|--disk]" "\n"
"\t[--version]" "\n"
@@ -499,7 +557,6 @@ xx(vgrename,
"vgrename\n"
"\t[-A/--autobackup y/n]\n"
"\t[-d/--debug]\n"
- "\t[-f/--force]\n"
"\t[-h/-?/--help]\n"
"\t[-t/--test]\n"
"\t[-v/--verbose]\n"
@@ -524,7 +581,7 @@ xx(vgsplit,
"\t[-d|--debug] " "\n"
"\t[-h|--help] " "\n"
"\t[-l|--list]" "\n"
- "\t[-M|--metadatatype lvm1/text] " "\n"
+ "\t[-M|--metadatatype 1|2] " "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version]" "\n"
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 59d5901c..24cc73d0 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -20,120 +20,6 @@
#include "tools.h"
-static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv);
-static int lvchange_permission(struct cmd_context *cmd,
- struct logical_volume *lv);
-static int lvchange_availability(struct cmd_context *cmd,
- struct logical_volume *lv);
-static int lvchange_contiguous(struct cmd_context *cmd,
- struct logical_volume *lv);
-static int lvchange_readahead(struct cmd_context *cmd,
- struct logical_volume *lv);
-static int lvchange_persistent(struct cmd_context *cmd,
- struct logical_volume *lv);
-
-int lvchange(struct cmd_context *cmd, int argc, char **argv)
-{
- if (!arg_count(cmd, available_ARG) && !arg_count(cmd, contiguous_ARG)
- && !arg_count(cmd, permission_ARG) && !arg_count(cmd, readahead_ARG)
- && !arg_count(cmd, minor_ARG) && !arg_count(cmd, persistent_ARG)) {
- log_error("One or more of -a, -C, -m, -M, -p or -r required");
- return EINVALID_CMD_LINE;
- }
-
- if (arg_count(cmd, ignorelockingfailure_ARG) &&
- (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
- arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG))) {
- log_error("Only -a permitted with --ignorelockingfailure");
- return EINVALID_CMD_LINE;
- }
-
- if (!argc) {
- log_error("Please give logical volume path(s)");
- return EINVALID_CMD_LINE;
- }
-
- if (arg_count(cmd, minor_ARG) && argc != 1) {
- log_error("Only give one logical volume when specifying minor");
- return EINVALID_CMD_LINE;
- }
-
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, &lvchange_single);
-}
-
-static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv)
-{
- int doit = 0;
- int archived = 0;
-
- if (!(lv->vg->status & LVM_WRITE) &&
- (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
- arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG))) {
- log_error("Only -a permitted with read-only volume "
- "group \"%s\"", lv->vg->name);
- return EINVALID_CMD_LINE;
- }
-
- if (lv_is_origin(lv) &&
- (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
- arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG))) {
- log_error("Can't change logical volume \"%s\" under snapshot",
- lv->name);
- return ECMD_FAILED;
- }
-
- if (lv_is_cow(lv)) {
- log_error("Can't change snapshot logical volume \"%s\"",
- lv->name);
- return ECMD_FAILED;
- }
-
- /* access permission change */
- if (arg_count(cmd, permission_ARG)) {
- if (!archive(lv->vg))
- return ECMD_FAILED;
- archived = 1;
- doit += lvchange_permission(cmd, lv);
- }
-
- /* allocation policy change */
- if (arg_count(cmd, contiguous_ARG)) {
- if (!archived && !archive(lv->vg))
- return ECMD_FAILED;
- archived = 1;
- doit += lvchange_contiguous(cmd, lv);
- }
-
- /* read ahead sector change */
- if (arg_count(cmd, readahead_ARG)) {
- if (!archived && !archive(lv->vg))
- return ECMD_FAILED;
- archived = 1;
- doit += lvchange_readahead(cmd, lv);
- }
-
- /* read ahead sector change */
- if (arg_count(cmd, persistent_ARG)) {
- if (!archived && !archive(lv->vg))
- return ECMD_FAILED;
- archived = 1;
- doit += lvchange_persistent(cmd, lv);
- }
-
- if (doit)
- log_print("Logical volume \"%s\" changed", lv->name);
-
- /* availability change */
- if (arg_count(cmd, available_ARG))
- if (!lvchange_availability(cmd, lv))
- return ECMD_FAILED;
-
- return 0;
-}
-
static int lvchange_permission(struct cmd_context *cmd,
struct logical_volume *lv)
{
@@ -234,7 +120,7 @@ static int lvchange_contiguous(struct cmd_context *cmd,
}
/******** FIXME lv_check_contiguous?
- if ((lv_allocation & ALLOC_CONTIGUOUS)
+ if (want_contiguous)
&& (ret = lv_check_contiguous(vg, lv_index + 1)) == FALSE) {
log_error("No contiguous logical volume \"%s\"", lv->name);
return 0;
@@ -245,8 +131,8 @@ static int lvchange_contiguous(struct cmd_context *cmd,
log_verbose("Setting contiguous allocation policy for \"%s\"",
lv->name);
} else {
- lv->alloc = ALLOC_NEXT_FREE;
- log_verbose("Removing contiguous allocation policy for \"%s\"",
+ lv->alloc = ALLOC_DEFAULT;
+ log_verbose("Reverting to default allocation policy for \"%s\"",
lv->name);
}
@@ -371,3 +257,104 @@ static int lvchange_persistent(struct cmd_context *cmd,
return 1;
}
+
+static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
+{
+ int doit = 0;
+ int archived = 0;
+
+ if (!(lv->vg->status & LVM_WRITE) &&
+ (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
+ arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG))) {
+ log_error("Only -a permitted with read-only volume "
+ "group \"%s\"", lv->vg->name);
+ return EINVALID_CMD_LINE;
+ }
+
+ if (lv_is_origin(lv) &&
+ (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
+ arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG))) {
+ log_error("Can't change logical volume \"%s\" under snapshot",
+ lv->name);
+ return ECMD_FAILED;
+ }
+
+ if (lv_is_cow(lv)) {
+ log_error("Can't change snapshot logical volume \"%s\"",
+ lv->name);
+ return ECMD_FAILED;
+ }
+
+ /* access permission change */
+ if (arg_count(cmd, permission_ARG)) {
+ if (!archive(lv->vg))
+ return ECMD_FAILED;
+ archived = 1;
+ doit += lvchange_permission(cmd, lv);
+ }
+
+ /* allocation policy change */
+ if (arg_count(cmd, contiguous_ARG)) {
+ if (!archived && !archive(lv->vg))
+ return ECMD_FAILED;
+ archived = 1;
+ doit += lvchange_contiguous(cmd, lv);
+ }
+
+ /* read ahead sector change */
+ if (arg_count(cmd, readahead_ARG)) {
+ if (!archived && !archive(lv->vg))
+ return ECMD_FAILED;
+ archived = 1;
+ doit += lvchange_readahead(cmd, lv);
+ }
+
+ /* read ahead sector change */
+ if (arg_count(cmd, persistent_ARG)) {
+ if (!archived && !archive(lv->vg))
+ return ECMD_FAILED;
+ archived = 1;
+ doit += lvchange_persistent(cmd, lv);
+ }
+
+ if (doit)
+ log_print("Logical volume \"%s\" changed", lv->name);
+
+ /* availability change */
+ if (arg_count(cmd, available_ARG))
+ if (!lvchange_availability(cmd, lv))
+ return ECMD_FAILED;
+
+ return 0;
+}
+
+int lvchange(struct cmd_context *cmd, int argc, char **argv)
+{
+ if (!arg_count(cmd, available_ARG) && !arg_count(cmd, contiguous_ARG)
+ && !arg_count(cmd, permission_ARG) && !arg_count(cmd, readahead_ARG)
+ && !arg_count(cmd, minor_ARG) && !arg_count(cmd, persistent_ARG)) {
+ log_error("One or more of -a, -C, -m, -M, -p or -r required");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, ignorelockingfailure_ARG) &&
+ (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
+ arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG))) {
+ log_error("Only -a permitted with --ignorelockingfailure");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (!argc) {
+ log_error("Please give logical volume path(s)");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, minor_ARG) && argc != 1) {
+ log_error("Only give one logical volume when specifying minor");
+ return EINVALID_CMD_LINE;
+ }
+
+ return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, NULL,
+ &lvchange_single);
+}
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 3065806c..59e9ed0a 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -90,7 +90,7 @@ static int _read_name_params(struct lvcreate_params *lp,
if (lp->lv_name && strchr(lp->lv_name, '/')) {
if (!(lp->vg_name =
extract_vgname(cmd, lp->lv_name)))
- return 0;
+ return 0;
if (strcmp(lp->vg_name, argv[0])) {
log_error("Inconsistent volume group "
@@ -109,6 +109,13 @@ static int _read_name_params(struct lvcreate_params *lp,
if (lp->lv_name && (ptr = strrchr(lp->lv_name, '/')))
lp->lv_name = ptr + 1;
+ /* FIXME Remove this restriction eventually */
+ if (lp->lv_name && !strncmp(lp->lv_name, "snapshot", 8)) {
+ log_error("Names starting \"snapshot\" are reserved. "
+ "Please choose a different LV name.");
+ return 0;
+ }
+
return 1;
}
@@ -312,20 +319,21 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
{
uint32_t size_rest;
uint32_t status = 0;
- alloc_policy_t alloc = ALLOC_NEXT_FREE;
+ alloc_policy_t alloc = ALLOC_DEFAULT;
struct volume_group *vg;
struct logical_volume *lv, *org;
struct list *pvh;
+ int consistent = 1;
if (lp->contiguous)
alloc = ALLOC_CONTIGUOUS;
- status |= lp->permission;
+ status |= lp->permission | VISIBLE_LV;
/* does VG exist? */
log_verbose("Finding volume group \"%s\"", lp->vg_name);
- if (!(vg = vg_read(cmd, lp->vg_name))) {
+ if (!(vg = vg_read(cmd, lp->vg_name, &consistent))) {
log_error("Volume group \"%s\" doesn't exist", lp->vg_name);
return 0;
}
@@ -391,20 +399,30 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
lp->extents = lp->extents - size_rest + lp->stripes;
}
- if (lp->snapshot && !(org = find_lv(vg, lp->origin))) {
- log_err("Couldn't find origin volume '%s'.", lp->origin);
+ if (!activation()) {
+ if (lp->snapshot)
+ log_error("Can't create snapshot without using "
+ "device-mapper kernel driver");
return 0;
}
- /*
- * For now all logical volumes are visible.
- */
- status |= VISIBLE_LV;
-
+ if (lp->snapshot) {
+ if (!(org = find_lv(vg, lp->origin))) {
+ log_err("Couldn't find origin volume '%s'.",
+ lp->origin);
+ return 0;
+ }
+ if (lv_is_cow(org)) {
+ log_error("Snapshots of snapshots are not supported "
+ "yet.");
+ return 0;
+ }
+ }
if (!(lv = lv_create(vg->fid, lp->lv_name, status, alloc,
lp->stripes, lp->stripe_size, lp->extents,
- vg, pvh))) return 0;
+ vg, pvh)))
+ return 0;
if (lp->read_ahead) {
log_verbose("Setting read ahead sectors");
@@ -421,16 +439,28 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0;
/* store vg on disk(s) */
- if (!vg_write(vg))
+ if (!vg_write(vg)) {
return 0;
+ }
- if (!lock_vol(cmd, lv->lvid.s, LCK_LV_ACTIVATE))
+ if (!lock_vol(cmd, lv->lvid.s, LCK_LV_ACTIVATE)) {
+ /* FIXME Remove the failed lv we just added */
+ log_error("Aborting. Failed to wipe snapshot "
+ "exception store. Remove new LV and retry.");
return 0;
+ }
- if (lp->zero || lp->snapshot)
- _zero_lv(cmd, lv);
- else
- log_print("WARNING: \"%s\" not zeroed", lv->name);
+ if ((lp->zero || lp->snapshot) && activation()) {
+ if (!_zero_lv(cmd, lv) && lp->snapshot) {
+ /* FIXME Remove the failed lv we just added */
+ log_error("Aborting. Failed to wipe snapshot "
+ "exception store. Remove new LV and retry.");
+ return 0;
+ }
+ } else {
+ log_error("WARNING: \"%s\" not zeroed", lv->name);
+ /* FIXME Remove the failed lv we just added */
+ }
if (lp->snapshot) {
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_DEACTIVATE)) {
@@ -443,7 +473,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0;
}
- if (!vg_add_snapshot(org, lv, 1, lp->chunk_size)) {
+ if (!vg_add_snapshot(org, lv, 1, NULL, lp->chunk_size)) {
log_err("Couldn't create snapshot.");
return 0;
}
@@ -480,9 +510,6 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
if (!_read_params(&lp, cmd, argc, argv))
return -EINVALID_CMD_LINE;
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
if (!lock_vol(cmd, lp.vg_name, LCK_VG_WRITE)) {
log_error("Can't get lock for %s", lp.vg_name);
return 0;
diff --git a/tools/lvdisplay.c b/tools/lvdisplay.c
index d421327c..69971b1b 100644
--- a/tools/lvdisplay.c
+++ b/tools/lvdisplay.c
@@ -20,12 +20,13 @@
#include "tools.h"
-int lvdisplay_single(struct cmd_context *cmd, struct logical_volume *lv)
+int lvdisplay_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
{
if (arg_count(cmd, colon_ARG))
lvdisplay_colons(lv);
else {
- lvdisplay_full(cmd, lv);
+ lvdisplay_full(cmd, lv, handle);
if (arg_count(cmd, maps_ARG))
lvdisplay_segments(lv);
}
@@ -42,8 +43,6 @@ int lvdisplay(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- return process_each_lv(cmd, argc, argv, LCK_VG_READ, &lvdisplay_single);
+ return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+ &lvdisplay_single);
}
diff --git a/tools/lvm.c b/tools/lvm.c
index 366b906b..526c1847 100644
--- a/tools/lvm.c
+++ b/tools/lvm.c
@@ -5,9 +5,7 @@
*/
#include "tools.h"
-#include "archive.h"
#include "defaults.h"
-#include "lvm1_label.h"
#include "label.h"
#include "version.h"
@@ -19,10 +17,7 @@
#include <syslog.h>
#include <libgen.h>
#include <sys/stat.h>
-#include <ctype.h>
#include <time.h>
-#include <stdlib.h>
-#include <locale.h>
#ifdef READLINE_SUPPORT
#include <readline/readline.h>
@@ -46,136 +41,10 @@ struct arg the_args[ARG_COUNT + 1] = {
static int _array_size;
static int _num_commands;
static struct command *_commands;
-struct cmd_context *cmd;
-
-/* Whether or not to dump persistent filter state */
-static int _dump_filter;
static int _interactive;
-static FILE *_log;
-
-/* lvm1 label handler */
-static struct labeller *_lvm1_label;
-
-/*
- * This structure only contains those options that
- * can have a default and per command setting.
- */
-struct config_info {
- int debug;
- int verbose;
- int test;
- int syslog;
- const char *msg_prefix;
- int cmd_name; /* Show command name? */
-
- int archive; /* should we archive ? */
- int backup; /* should we backup ? */
-
- struct format_type *fmt;
-
- mode_t umask;
-};
-
-static struct config_info _default_settings;
-static struct config_info _current_settings;
-
-/*
- * The lvm_sys_dir contains:
- *
- * o The lvm configuration (lvm.conf)
- * o The persistent filter cache (.cache)
- * o Volume group backups (/backup)
- * o Archive of old vg configurations (/archive)
- */
-static char _sys_dir[PATH_MAX] = "/etc/lvm";
-static char _dev_dir[PATH_MAX];
-static char _proc_dir[PATH_MAX];
-
-/* static functions */
-static void register_commands(void);
-static struct command *find_command(const char *name);
-static void register_command(const char *name, command_fn fn,
- const char *desc, const char *usage, ...);
-static void create_new_command(const char *name, command_fn command,
- const char *desc, const char *usage,
- int nargs, int *args);
-
-static void alloc_command(void);
-static void add_getopt_arg(int arg, char **ptr, struct option **o);
-static int process_command_line(struct command *com, int *argc, char ***argv);
-static struct arg *find_arg(struct command *com, int a);
-static int process_common_commands(struct command *com);
-static int run_command(int argc, char **argv);
-static int init(void);
-static void fin(void);
-static int run_script(int argc, char **argv);
-
-#ifdef READLINE_SUPPORT
-static int shell(void);
-#endif
-
-static void display_help(void);
-
-int main(int argc, char **argv)
-{
- char *namebase, *base;
- int ret, alias = 0;
-
- if (!init())
- return -1;
-
- namebase = strdup(argv[0]);
- base = basename(namebase);
- while (*base == '/')
- base++;
- if (strcmp(base, "lvm"))
- alias = 1;
- free(namebase);
-
- register_commands();
-
-#ifdef READLINE_SUPPORT
- if (!alias && argc == 1) {
- ret = shell();
- goto out;
- }
-#endif
-
- if (!alias) {
- if (argc < 2) {
- log_fatal("Please supply an LVM command.");
- display_help();
- ret = EINVALID_CMD_LINE;
- goto out;
- }
-
- argc--;
- argv++;
- }
- ret = run_command(argc, argv);
- if ((ret == ENO_SUCH_CMD) && (!alias))
- ret = run_script(argc, argv);
- if (ret == ENO_SUCH_CMD)
- log_error("No such command. Try 'help'.");
-
- out:
- fin();
- return ret;
-}
-
-void usage(const char *name)
-{
- struct command *com = find_command(name);
-
- if (!com)
- return;
-
- log_error("%s: %s\n\n%s", com->name, com->desc, com->usage);
-}
-
-int yes_no_arg(struct arg *a)
+int yes_no_arg(struct cmd_context *cmd, struct arg *a)
{
a->sign = SIGN_NONE;
@@ -191,18 +60,26 @@ int yes_no_arg(struct arg *a)
return 1;
}
-int metadatatype_arg(struct arg *a)
+int metadatatype_arg(struct cmd_context *cmd, struct arg *a)
{
- if (!strcasecmp(a->value, cmd->fmtt->name))
- a->ptr = cmd->fmtt;
+ struct format_type *fmt;
+ struct list *fmth;
- else if (!strcasecmp(a->value, cmd->fmt1->name))
- a->ptr = cmd->fmt1;
+ char *format;
- else
- return 0;
+ format = a->value;
- return 1;
+ list_iterate(fmth, &cmd->formats) {
+ fmt = list_item(fmth, struct format_type);
+ if (!strcasecmp(fmt->name, format) ||
+ !strcasecmp(fmt->name + 3, format) ||
+ (fmt->alias && !strcasecmp(fmt->alias, format))) {
+ a->ptr = fmt;
+ return 1;
+ }
+ }
+
+ return 0;
}
int _get_int_arg(struct arg *a, char **ptr)
@@ -236,7 +113,7 @@ int _get_int_arg(struct arg *a, char **ptr)
return 1;
}
-int size_arg(struct arg *a)
+int size_arg(struct cmd_context *cmd, struct arg *a)
{
char *ptr;
int i;
@@ -283,7 +160,7 @@ int size_arg(struct arg *a)
return 1;
}
-int int_arg(struct arg *a)
+int int_arg(struct cmd_context *cmd, struct arg *a)
{
char *ptr;
@@ -293,7 +170,7 @@ int int_arg(struct arg *a)
return 1;
}
-int int_arg_with_sign(struct arg *a)
+int int_arg_with_sign(struct cmd_context *cmd, struct arg *a)
{
char *ptr;
@@ -303,7 +180,7 @@ int int_arg_with_sign(struct arg *a)
return 1;
}
-int minor_arg(struct arg *a)
+int minor_arg(struct cmd_context *cmd, struct arg *a)
{
char *ptr;
@@ -318,12 +195,12 @@ int minor_arg(struct arg *a)
return 1;
}
-int string_arg(struct arg *a)
+int string_arg(struct cmd_context *cmd, struct arg *a)
{
return 1;
}
-int permission_arg(struct arg *a)
+int permission_arg(struct cmd_context *cmd, struct arg *a)
{
a->sign = SIGN_NONE;
@@ -358,18 +235,45 @@ char yes_no_prompt(const char *prompt, ...)
return c;
}
-static void register_commands()
+static void __alloc(int size)
+{
+ if (!(_commands = dbg_realloc(_commands, sizeof(*_commands) * size))) {
+ log_fatal("Couldn't allocate memory.");
+ exit(ECMD_FAILED);
+ }
+
+ _array_size = size;
+}
+
+static void _alloc_command(void)
{
-#define xx(a, b, c...) register_command(# a, a, b, ## c, \
- debug_ARG, help_ARG, \
- version_ARG, verbose_ARG, \
- quiet_ARG, -1);
-#include "commands.h"
-#undef xx
+ if (!_array_size)
+ __alloc(32);
+
+ if (_array_size <= _num_commands)
+ __alloc(2 * _array_size);
}
-static void register_command(const char *name, command_fn fn,
- const char *desc, const char *usage, ...)
+static void _create_new_command(const char *name, command_fn command,
+ const char *desc, const char *usage,
+ int nargs, int *args)
+{
+ struct command *nc;
+
+ _alloc_command();
+
+ nc = _commands + _num_commands++;
+
+ nc->name = name;
+ nc->desc = desc;
+ nc->usage = usage;
+ nc->fn = command;
+ nc->num_args = nargs;
+ nc->valid_args = args;
+}
+
+static void _register_command(const char *name, command_fn fn,
+ const char *desc, const char *usage, ...)
{
int nargs = 0, i;
int *args;
@@ -394,10 +298,21 @@ static void register_command(const char *name, command_fn fn,
va_end(ap);
/* enter the command in the register */
- create_new_command(name, fn, desc, usage, nargs, args);
+ _create_new_command(name, fn, desc, usage, nargs, args);
+}
+
+static void _register_commands()
+{
+#define xx(a, b, c...) _register_command(# a, a, b, ## c, \
+ driverloaded_ARG, \
+ debug_ARG, help_ARG, \
+ version_ARG, verbose_ARG, \
+ quiet_ARG, -1);
+#include "commands.h"
+#undef xx
}
-static struct command *find_command(const char *name)
+static struct command *_find_command(const char *name)
{
int i;
char *namebase, *base;
@@ -418,41 +333,14 @@ static struct command *find_command(const char *name)
return _commands + i;
}
-static void create_new_command(const char *name, command_fn command,
- const char *desc, const char *usage,
- int nargs, int *args)
-{
- struct command *nc;
-
- alloc_command();
-
- nc = _commands + _num_commands++;
-
- nc->name = name;
- nc->desc = desc;
- nc->usage = usage;
- nc->fn = command;
- nc->num_args = nargs;
- nc->valid_args = args;
-}
-
-static void __alloc(int size)
+void usage(const char *name)
{
- if (!(_commands = dbg_realloc(_commands, sizeof(*_commands) * size))) {
- log_fatal("Couldn't allocate memory.");
- exit(ECMD_FAILED);
- }
-
- _array_size = size;
-}
+ struct command *com = _find_command(name);
-static void alloc_command(void)
-{
- if (!_array_size)
- __alloc(32);
+ if (!com)
+ return;
- if (_array_size <= _num_commands)
- __alloc(2 * _array_size);
+ log_error("%s: %s\n\n%s", com->name, com->desc, com->usage);
}
/*
@@ -464,7 +352,7 @@ static void alloc_command(void)
* we have only 1 ATM (--version) I think we can
* live with this restriction.
*/
-static void add_getopt_arg(int arg, char **ptr, struct option **o)
+static void _add_getopt_arg(int arg, char **ptr, struct option **o)
{
struct arg *a = the_args + arg;
@@ -484,7 +372,29 @@ static void add_getopt_arg(int arg, char **ptr, struct option **o)
}
}
-static int process_command_line(struct command *com, int *argc, char ***argv)
+static struct arg *_find_arg(struct command *com, int opt)
+{
+ struct arg *a;
+ int i, arg;
+
+ for (i = 0; i < com->num_args; i++) {
+ arg = com->valid_args[i];
+ a = the_args + arg;
+
+ /*
+ * opt should equal either the
+ * short arg, or the index into
+ * 'the_args'.
+ */
+ if ((a->short_arg && (opt == a->short_arg)) || (opt == arg))
+ return a;
+ }
+
+ return 0;
+}
+
+static int _process_command_line(struct cmd_context *cmd, int *argc,
+ char ***argv)
{
int i, opt;
char str[((ARG_COUNT + 1) * 2) + 1], *ptr = str;
@@ -501,8 +411,8 @@ static int process_command_line(struct command *com, int *argc, char ***argv)
}
/* fill in the short and long opts */
- for (i = 0; i < com->num_args; i++)
- add_getopt_arg(com->valid_args[i], &ptr, &o);
+ for (i = 0; i < cmd->command->num_args; i++)
+ _add_getopt_arg(cmd->command->valid_args[i], &ptr, &o);
*ptr = '\0';
memset(o, 0, sizeof(*o));
@@ -512,7 +422,7 @@ static int process_command_line(struct command *com, int *argc, char ***argv)
optind = 0;
while ((opt = getopt_long(*argc, *argv, str, opts, NULL)) >= 0) {
- a = find_arg(com, opt);
+ a = _find_arg(cmd->command, opt);
if (!a) {
log_fatal("Unrecognised option.");
@@ -528,7 +438,7 @@ static int process_command_line(struct command *com, int *argc, char ***argv)
a->value = optarg;
- if (!a->fn(a)) {
+ if (!a->fn(cmd, a)) {
log_error("Invalid argument %s", optarg);
return 0;
}
@@ -542,28 +452,7 @@ static int process_command_line(struct command *com, int *argc, char ***argv)
return 1;
}
-static struct arg *find_arg(struct command *com, int opt)
-{
- struct arg *a;
- int i, arg;
-
- for (i = 0; i < com->num_args; i++) {
- arg = com->valid_args[i];
- a = the_args + arg;
-
- /*
- * opt should equal either the
- * short arg, or the index into
- * 'the_args'.
- */
- if ((a->short_arg && (opt == a->short_arg)) || (opt == arg))
- return a;
- }
-
- return 0;
-}
-
-static int merge_synonym(int oldarg, int newarg)
+static int _merge_synonym(struct cmd_context *cmd, int oldarg, int newarg)
{
struct arg *old, *new;
@@ -600,37 +489,34 @@ int version(struct cmd_context *cmd, int argc, char **argv)
return ECMD_PROCESSED;
}
-static int process_common_commands(struct command *com)
+static int _get_settings(struct cmd_context *cmd)
{
- _current_settings = _default_settings;
+ cmd->current_settings = cmd->default_settings;
if (arg_count(cmd, debug_ARG))
- _current_settings.debug = _LOG_FATAL +
+ cmd->current_settings.debug = _LOG_FATAL +
(arg_count(cmd, debug_ARG) - 1);
if (arg_count(cmd, verbose_ARG))
- _current_settings.verbose = arg_count(cmd, verbose_ARG);
+ cmd->current_settings.verbose = arg_count(cmd, verbose_ARG);
if (arg_count(cmd, quiet_ARG)) {
- _current_settings.debug = 0;
- _current_settings.verbose = 0;
+ cmd->current_settings.debug = 0;
+ cmd->current_settings.verbose = 0;
}
if (arg_count(cmd, test_ARG))
- _current_settings.test = arg_count(cmd, test_ARG);
+ cmd->current_settings.test = arg_count(cmd, test_ARG);
- if (arg_count(cmd, help_ARG)) {
- usage(com->name);
- return ECMD_PROCESSED;
- }
-
- if (arg_count(cmd, version_ARG)) {
- return version(cmd, 0, (char **) NULL);
+ if (arg_count(cmd, driverloaded_ARG)) {
+ cmd->current_settings.activation =
+ arg_int_value(cmd, driverloaded_ARG,
+ cmd->default_settings.activation);
}
if (arg_count(cmd, autobackup_ARG)) {
- _current_settings.archive = 1;
- _current_settings.backup = 1;
+ cmd->current_settings.archive = 1;
+ cmd->current_settings.backup = 1;
}
if (arg_count(cmd, partial_ARG)) {
@@ -646,29 +532,31 @@ static int process_common_commands(struct command *com)
init_ignorelockingfailure(0);
/* Handle synonyms */
- if (!merge_synonym(resizable_ARG, resizeable_ARG) ||
- !merge_synonym(allocation_ARG, allocatable_ARG) ||
- !merge_synonym(allocation_ARG, resizeable_ARG))
- return ECMD_FAILED;
+ if (!_merge_synonym(cmd, resizable_ARG, resizeable_ARG) ||
+ !_merge_synonym(cmd, allocation_ARG, allocatable_ARG) ||
+ !_merge_synonym(cmd, allocation_ARG, resizeable_ARG))
+ return EINVALID_CMD_LINE;
- /* Zero indicates it's OK to continue processing this command */
+ /* Zero indicates success */
return 0;
}
-int help(struct cmd_context *cmd, int argc, char **argv)
+static int _process_common_commands(struct cmd_context *cmd)
{
- if (!argc)
- display_help();
- else {
- int i;
- for (i = 0; i < argc; i++)
- usage(argv[i]);
+ if (arg_count(cmd, help_ARG)) {
+ usage(cmd->command->name);
+ return ECMD_PROCESSED;
}
+ if (arg_count(cmd, version_ARG)) {
+ return version(cmd, 0, (char **) NULL);
+ }
+
+ /* Zero indicates it's OK to continue processing this command */
return 0;
}
-static void display_help(void)
+static void _display_help(void)
{
int i;
@@ -683,22 +571,38 @@ static void display_help(void)
}
}
-static void _use_settings(struct config_info *settings)
+int help(struct cmd_context *cmd, int argc, char **argv)
+{
+ if (!argc)
+ _display_help();
+ else {
+ int i;
+ for (i = 0; i < argc; i++)
+ usage(argv[i]);
+ }
+
+ return 0;
+}
+
+static void _apply_settings(struct cmd_context *cmd)
{
- init_debug(settings->debug);
- init_verbose(settings->verbose);
- init_test(settings->test);
+ init_debug(cmd->current_settings.debug);
+ init_verbose(cmd->current_settings.verbose);
+ init_test(cmd->current_settings.test);
+
+ init_msg_prefix(cmd->default_settings.msg_prefix);
+ init_cmd_name(cmd->default_settings.cmd_name);
- init_msg_prefix(_default_settings.msg_prefix);
- init_cmd_name(_default_settings.cmd_name);
+ archive_enable(cmd->current_settings.archive);
+ backup_enable(cmd->current_settings.backup);
- archive_enable(settings->archive);
- backup_enable(settings->backup);
+ set_activation(cmd->current_settings.activation);
- cmd->fmt = arg_ptr_value(cmd, metadatatype_ARG, settings->fmt);
+ cmd->fmt = arg_ptr_value(cmd, metadatatype_ARG,
+ cmd->current_settings.fmt);
}
-static char *_copy_command_line(struct pool *mem, int argc, char **argv)
+static char *_copy_command_line(struct cmd_context *cmd, int argc, char **argv)
{
int i;
@@ -720,59 +624,68 @@ static char *_copy_command_line(struct pool *mem, int argc, char **argv)
/*
* Terminate.
*/
- if (!pool_grow_object(mem, "\0", 1))
+ if (!pool_grow_object(cmd->mem, "\0", 1))
goto bad;
- return pool_end_object(mem);
+ return pool_end_object(cmd->mem);
bad:
log_err("Couldn't copy command line.");
- pool_abandon_object(mem);
+ pool_abandon_object(cmd->mem);
return NULL;
}
-static int run_command(int argc, char **argv)
+static int _run_command(struct cmd_context *cmd, int argc, char **argv)
{
int ret = 0;
int locking_type;
- if (!(cmd->cmd_line = _copy_command_line(cmd->mem, argc, argv)))
+ if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv)))
return ECMD_FAILED;
- if (!(cmd->command = find_command(argv[0])))
+ if (!(cmd->command = _find_command(argv[0])))
return ENO_SUCH_CMD;
- if (!process_command_line(cmd->command, &argc, &argv)) {
+ if (!_process_command_line(cmd, &argc, &argv)) {
log_error("Error during parsing of command line.");
return EINVALID_CMD_LINE;
}
set_cmd_name(cmd->command->name);
- if ((ret = process_common_commands(cmd->command)))
- return ret;
+ if (reload_config_file(&cmd->cf)) {
+ ;
+ /* FIXME Reinitialise various settings inc. logging, filters */
+ }
- _use_settings(&_current_settings);
+ if ((ret = _get_settings(cmd)))
+ goto out;
+ _apply_settings(cmd);
+
+ if ((ret = _process_common_commands(cmd)))
+ goto out;
locking_type = find_config_int(cmd->cf->root, "global/locking_type",
'/', 1);
if (!init_locking(locking_type, cmd->cf)) {
log_error("Locking type %d initialisation failed.",
locking_type);
- return 0;
+ ret = ECMD_FAILED;
+ goto out;
}
ret = cmd->command->fn(cmd, argc, argv);
fin_locking();
- /*
- * set the debug and verbose levels back
- * to the global default. We have to do
- * this so the logging levels get set
- * correctly for program exit.
- */
- _use_settings(&_default_settings);
+ out:
+ if (test_mode()) {
+ log_verbose("Test mode: Wiping internal cache");
+ cache_destroy();
+ }
+
+ cmd->current_settings = cmd->default_settings;
+ _apply_settings(cmd);
/*
* free off any memory the command used.
@@ -785,7 +698,7 @@ static int run_command(int argc, char **argv)
return ret;
}
-static int split(char *str, int *argc, char **argv, int max)
+static int _split(char *str, int *argc, char **argv, int max)
{
char *b = str, *e;
*argc = 0;
@@ -818,62 +731,13 @@ static void _init_rand(void)
srand((unsigned int) time(NULL) + (unsigned int) getpid());
}
-static void __init_log(struct config_file *cf)
-{
- char *open_mode = "a";
-
- const char *log_file;
-
- _default_settings.syslog =
- find_config_int(cf->root, "log/syslog", '/', 1);
- if (_default_settings.syslog != 1)
- fin_syslog();
-
- if (_default_settings.syslog > 1)
- init_syslog(_default_settings.syslog);
-
- _default_settings.debug =
- find_config_int(cf->root, "log/level", '/', 0);
- init_debug(_default_settings.debug);
-
- _default_settings.verbose =
- find_config_int(cf->root, "log/verbose", '/', 0);
- init_verbose(_default_settings.verbose);
-
- init_indent(find_config_int(cf->root, "log/indent", '/', 1));
-
- _default_settings.msg_prefix = find_config_str(cf->root, "log/prefix",
- '/', DEFAULT_MSG_PREFIX);
- init_msg_prefix(_default_settings.msg_prefix);
-
- _default_settings.cmd_name = find_config_int(cf->root,
- "log/command_names", '/',
- DEFAULT_CMD_NAME);
- init_cmd_name(_default_settings.cmd_name);
-
- _default_settings.test = find_config_int(cf->root, "global/test",
- '/', 0);
- if (find_config_int(cf->root, "log/overwrite", '/', 0))
- open_mode = "w";
-
- log_file = find_config_str(cf->root, "log/file", '/', 0);
- if (log_file) {
- /* set up the logging */
- if (!(_log = fopen(log_file, open_mode)))
- log_error("Couldn't open log file %s", log_file);
- else
- init_log(_log);
- }
-
-}
-
-static int _init_backup(struct config_file *cf)
+static int _init_backup(struct cmd_context *cmd, struct config_tree *cf)
{
int days, min;
char default_dir[PATH_MAX];
const char *dir;
- if (!_sys_dir) {
+ if (!cmd->sys_dir) {
log_warn("WARNING: Metadata changes will NOT be backed up");
backup_init("");
archive_init("", 0, 0);
@@ -881,7 +745,7 @@ static int _init_backup(struct config_file *cf)
}
/* set up archiving */
- _default_settings.archive =
+ cmd->default_settings.archive =
find_config_bool(cmd->cf->root, "backup/archive", '/',
DEFAULT_ARCHIVE_ENABLED);
@@ -891,10 +755,11 @@ static int _init_backup(struct config_file *cf)
min = find_config_int(cmd->cf->root, "backup/retain_min", '/',
DEFAULT_ARCHIVE_NUMBER);
- if (lvm_snprintf(default_dir, sizeof(default_dir), "%s/%s", _sys_dir,
- DEFAULT_ARCHIVE_SUBDIR) == -1) {
+ if (lvm_snprintf
+ (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
+ DEFAULT_ARCHIVE_SUBDIR) == -1) {
log_err("Couldn't create default archive path '%s/%s'.",
- _sys_dir, DEFAULT_ARCHIVE_SUBDIR);
+ cmd->sys_dir, DEFAULT_ARCHIVE_SUBDIR);
return 0;
}
@@ -907,14 +772,15 @@ static int _init_backup(struct config_file *cf)
}
/* set up the backup */
- _default_settings.backup =
+ cmd->default_settings.backup =
find_config_bool(cmd->cf->root, "backup/backup", '/',
DEFAULT_BACKUP_ENABLED);
- if (lvm_snprintf(default_dir, sizeof(default_dir), "%s/%s", _sys_dir,
- DEFAULT_BACKUP_SUBDIR) == -1) {
+ if (lvm_snprintf
+ (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
+ DEFAULT_BACKUP_SUBDIR) == -1) {
log_err("Couldn't create default backup path '%s/%s'.",
- _sys_dir, DEFAULT_BACKUP_SUBDIR);
+ cmd->sys_dir, DEFAULT_BACKUP_SUBDIR);
return 0;
}
@@ -929,269 +795,26 @@ static int _init_backup(struct config_file *cf)
return 1;
}
-static int dev_cache_setup(struct config_file *cf)
-{
- struct config_node *cn;
- struct config_value *cv;
-
- if (!dev_cache_init()) {
- stack;
- return 0;
- }
-
- if (!(cn = find_config_node(cf->root, "devices/scan", '/'))) {
- if (!dev_cache_add_dir("/dev")) {
- log_error("Failed to add /dev to internal "
- "device cache");
- return 0;
- }
- log_verbose
- ("device/scan not in config file: Defaulting to /dev");
- return 1;
- }
-
- for (cv = cn->v; cv; cv = cv->next) {
- if (cv->type != CFG_STRING) {
- log_error("Invalid string in config file: "
- "devices/scan");
- return 0;
- }
-
- if (!dev_cache_add_dir(cv->v.str)) {
- log_error("Failed to add %s to internal device cache",
- cv->v.str);
- return 0;
- }
- }
-
- return 1;
-}
-
-static struct dev_filter *filter_components_setup(struct config_file *cf)
-{
- struct config_node *cn;
- struct dev_filter *f1, *f2, *f3;
-
- if (!(f2 = lvm_type_filter_create(_proc_dir)))
- return 0;
-
- if (!(cn = find_config_node(cf->root, "devices/filter", '/'))) {
- log_debug("devices/filter not found in config file: no regex "
- "filter installed");
- return f2;
- }
-
- if (!(f1 = regex_filter_create(cn->v))) {
- log_error("Failed to create regex device filter");
- return f2;
- }
-
- if (!(f3 = composite_filter_create(2, f1, f2))) {
- log_error("Failed to create composite device filter");
- return f2;
- }
-
- return f3;
-}
-
-static struct dev_filter *filter_setup(struct config_file *cf)
-{
- const char *lvm_cache;
- struct dev_filter *f3, *f4;
- struct stat st;
- char cache_file[PATH_MAX];
-
- _dump_filter = 0;
-
- if (!(f3 = filter_components_setup(cmd->cf)))
- return 0;
-
- if (lvm_snprintf(cache_file, sizeof(cache_file),
- "%s/.cache", _sys_dir) < 0) {
- log_error("Persistent cache filename too long ('%s/.cache').",
- _sys_dir);
- return 0;
- }
-
- lvm_cache = find_config_str(cf->root, "devices/cache", '/', cache_file);
-
- if (!(f4 = persistent_filter_create(f3, lvm_cache))) {
- log_error("Failed to create persistent device filter");
- return 0;
- }
-
- /* Should we ever dump persistent filter state? */
- if (find_config_int(cf->root, "devices/write_cache_state", '/', 1))
- _dump_filter = 1;
-
- if (!*_sys_dir)
- _dump_filter = 0;
-
- if (!stat(lvm_cache, &st) && !persistent_filter_load(f4))
- log_verbose("Failed to load existing device cache from %s",
- lvm_cache);
-
- return f4;
-}
-
-static struct uuid_map *_init_uuid_map(struct dev_filter *filter)
-{
- label_init();
-
- /* add in the lvm1 labeller */
- if (!(_lvm1_label = lvm1_labeller_create())) {
- log_err("Couldn't create lvm1 label handler.");
- return 0;
- }
-
- if (!(label_register_handler("lvm1", _lvm1_label))) {
- log_err("Couldn't register lvm1 label handler.");
- return 0;
- }
-
- return uuid_map_create(filter);
-}
-
-static void _exit_uuid_map(void)
-{
- uuid_map_destroy(cmd->um);
- label_exit();
- _lvm1_label->ops->destroy(_lvm1_label);
- _lvm1_label = NULL;
-}
-
-static int _get_env_vars(void)
-{
- const char *e;
-
- /* Set to "" to avoid using any system directory */
- if ((e = getenv("LVM_SYSTEM_DIR"))) {
- if (lvm_snprintf(_sys_dir, sizeof(_sys_dir), "%s", e) < 0) {
- log_error("LVM_SYSTEM_DIR environment variable "
- "is too long.");
- return 0;
- }
- }
-
- return 1;
-}
-
-static int init(void)
+static struct cmd_context *_init(void)
{
- struct stat info;
- char config_file[PATH_MAX] = "";
- const char *format;
- mode_t old_umask;
-
- if (!setlocale(LC_ALL, ""))
- log_error("setlocale failed");
-
- if (!_get_env_vars())
- return 0;
+ struct cmd_context *cmd;
- /* Create system directory if it doesn't already exist */
- if (!create_dir(_sys_dir))
- return 0;
-
- if (!(cmd = dbg_malloc(sizeof(*cmd)))) {
- log_error("Failed to allocate command context");
- return 0;
- }
-
- cmd->args = &the_args[0];
-
- if (!(cmd->cf = create_config_file())) {
+ if (!(cmd = create_toolcontext(&the_args[0]))) {
stack;
- return 0;
+ return NULL;
}
- /* Use LOG_USER for syslog messages by default */
- init_syslog(LOG_USER);
-
_init_rand();
- if (*_sys_dir && lvm_snprintf(config_file, sizeof(config_file),
- "%s/lvm.conf", _sys_dir) < 0) {
- log_error("lvm_sys_dir was too long");
- return 0;
- }
-
- if (stat(config_file, &info) != -1 &&
- !read_config(cmd->cf, config_file)) {
- log_error("Failed to load config file %s", config_file);
- return 0;
- }
-
- __init_log(cmd->cf);
-
- _default_settings.umask = find_config_int(cmd->cf->root,
- "global/umask", '/',
- DEFAULT_UMASK);
-
- if ((old_umask = umask((mode_t) _default_settings.umask)) !=
- (mode_t) _default_settings.umask)
- log_verbose("Set umask to %04o", _default_settings.umask);
-
- if (lvm_snprintf(_dev_dir, sizeof(_dev_dir), "%s/",
- find_config_str(cmd->cf->root, "devices/dir",
- '/', DEFAULT_DEV_DIR)) < 0) {
- log_error("Device directory given in config file too long");
- return 0;
- }
-
- cmd->dev_dir = _dev_dir;
- dm_set_dev_dir(cmd->dev_dir);
-
- dm_log_init(print_log);
-
- if (lvm_snprintf(_proc_dir, sizeof(_proc_dir), "%s",
- find_config_str(cmd->cf->root, "global/proc",
- '/', DEFAULT_PROC_DIR)) < 0) {
- log_error("Device directory given in config file too long");
- return 0;
- }
+ if (!_init_backup(cmd, cmd->cf))
+ return NULL;
- if (!_init_backup(cmd->cf))
- return 0;
+ _apply_settings(cmd);
- if (!dev_cache_setup(cmd->cf))
- return 0;
-
- if (!(cmd->filter = filter_setup(cmd->cf))) {
- log_error("Failed to set up internal device filters");
- return 0;
- }
-
- /* the uuid map uses the filter */
- if (!(cmd->um = _init_uuid_map(cmd->filter))) {
- log_err("Failed to set up the uuid map.");
- return 0;
- }
-
- if (!(cmd->mem = pool_create(4 * 1024))) {
- log_error("Command pool creation failed");
- return 0;
- }
-
- /* FIXME Replace with list, dynamic libs etc. */
- if (!(cmd->fmt1 = create_lvm1_format(cmd)))
- return 0;
-
- if (!(cmd->fmtt = create_text_format(cmd)))
- return 0;
-
- format = find_config_str(cmd->cf->root, "global/format", '/',
- DEFAULT_FORMAT);
- if (!strcasecmp(format, "text"))
- _default_settings.fmt = cmd->fmtt;
- else /* "lvm1" */
- _default_settings.fmt = cmd->fmt1;
-
- _use_settings(&_default_settings);
- return 1;
+ return cmd;
}
-static void __fin_commands(void)
+static void _fin_commands(struct cmd_context *cmd)
{
int i;
@@ -1201,33 +824,16 @@ static void __fin_commands(void)
dbg_free(_commands);
}
-static void fin(void)
+static void _fin(struct cmd_context *cmd)
{
- if (_dump_filter)
- persistent_filter_dump(cmd->filter);
-
- cmd->fmt1->ops->destroy(cmd->fmt1);
- cmd->fmtt->ops->destroy(cmd->fmtt);
- cmd->filter->destroy(cmd->filter);
- pool_destroy(cmd->mem);
- vgcache_destroy();
- dev_cache_exit();
- destroy_config_file(cmd->cf);
archive_exit();
backup_exit();
- _exit_uuid_map();
- dbg_free(cmd);
- __fin_commands();
+ _fin_commands(cmd);
- dump_memory();
- fin_log();
- fin_syslog();
-
- if (_log)
- fclose(_log);
+ destroy_toolcontext(cmd);
}
-static int run_script(int argc, char **argv)
+static int _run_script(struct cmd_context *cmd, int argc, char **argv)
{
FILE *script;
@@ -1253,7 +859,7 @@ static int run_script(int argc, char **argv)
ret = EINVALID_CMD_LINE;
break;
}
- if (split(buffer, &argc, argv, MAX_ARGS) == MAX_ARGS) {
+ if (_split(buffer, &argc, argv, MAX_ARGS) == MAX_ARGS) {
buffer[50] = '\0';
log_error("Too many arguments: %s", buffer);
ret = EINVALID_CMD_LINE;
@@ -1263,7 +869,7 @@ static int run_script(int argc, char **argv)
continue;
if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit"))
break;
- run_command(argc, argv);
+ _run_command(cmd, argc, argv);
}
fclose(script);
@@ -1337,7 +943,7 @@ static char *_list_args(const char *text, int state)
char c;
if (!(c = (the_args +
com->valid_args[match_no++])->short_arg))
- continue;
+ continue;
sprintf(s, "-%c", c);
if (!strncmp(text, s, len))
@@ -1394,7 +1000,7 @@ static int _hist_file(char *buffer, size_t size)
return 1;
}
-static void _read_history(void)
+static void _read_history(struct cmd_context *cmd)
{
char hist_file[PATH_MAX];
@@ -1420,7 +1026,7 @@ static void _write_history(void)
log_very_verbose("Couldn't write history to %s.", hist_file);
}
-static int shell(void)
+static int _shell(struct cmd_context *cmd)
{
int argc, ret;
char *input = NULL, *args[MAX_ARGS], **argv;
@@ -1428,7 +1034,7 @@ static int shell(void)
rl_readline_name = "lvm";
rl_attempted_completion_function = (CPPFunction *) _completion;
- _read_history();
+ _read_history(cmd);
_interactive = 1;
while (1) {
@@ -1449,7 +1055,7 @@ static int shell(void)
argv = args;
- if (split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
+ if (_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
log_error("Too many arguments, sorry.");
continue;
}
@@ -1468,14 +1074,65 @@ static int shell(void)
break;
}
- ret = run_command(argc, argv);
+ ret = _run_command(cmd, argc, argv);
if (ret == ENO_SUCH_CMD)
log_error("No such command '%s'. Try 'help'.",
argv[0]);
+
+ _write_history();
}
- _write_history();
free(input);
return 0;
}
+
#endif
+
+int main(int argc, char **argv)
+{
+ char *namebase, *base;
+ int ret, alias = 0;
+ struct cmd_context *cmd;
+
+ if (!(cmd = _init()))
+ return -1;
+
+ namebase = strdup(argv[0]);
+ base = basename(namebase);
+ while (*base == '/')
+ base++;
+ if (strcmp(base, "lvm"))
+ alias = 1;
+ free(namebase);
+
+ _register_commands();
+
+#ifdef READLINE_SUPPORT
+ if (!alias && argc == 1) {
+ ret = _shell(cmd);
+ goto out;
+ }
+#endif
+
+ if (!alias) {
+ if (argc < 2) {
+ log_fatal("Please supply an LVM command.");
+ _display_help();
+ ret = EINVALID_CMD_LINE;
+ goto out;
+ }
+
+ argc--;
+ argv++;
+ }
+
+ ret = _run_command(cmd, argc, argv);
+ if ((ret == ENO_SUCH_CMD) && (!alias))
+ ret = _run_script(cmd, argc, argv);
+ if (ret == ENO_SUCH_CMD)
+ log_error("No such command. Try 'help'.");
+
+ out:
+ _fin(cmd);
+ return ret;
+}
diff --git a/tools/lvmdiskscan.c b/tools/lvmdiskscan.c
index c573517a..e65f80af 100644
--- a/tools/lvmdiskscan.c
+++ b/tools/lvmdiskscan.c
@@ -29,7 +29,7 @@ int lvmdiskscan(struct cmd_context *cmd, int argc, char **argv)
uint64_t size;
struct dev_iter *iter;
struct device *dev;
- struct physical_volume *pv;
+ struct label *label;
if (arg_count(cmd, lvmpartition_ARG))
log_print("WARNING: only considering LVM devices");
@@ -44,7 +44,7 @@ int lvmdiskscan(struct cmd_context *cmd, int argc, char **argv)
/* Do scan */
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
/* Try if it is a PV first */
- if ((pv = pv_read(cmd, dev_name(dev)))) {
+ if ((label_read(dev, &label))) {
if (!dev_get_size(dev, &size)) {
log_error("Couldn't get size of \"%s\"",
dev_name(dev));
diff --git a/tools/lvremove.c b/tools/lvremove.c
index 0e93866e..a41c1e59 100644
--- a/tools/lvremove.c
+++ b/tools/lvremove.c
@@ -20,22 +20,8 @@
#include "tools.h"
-static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv);
-
-int lvremove(struct cmd_context *cmd, int argc, char **argv)
-{
- if (!argc) {
- log_error("Please enter one or more logical volume paths");
- return EINVALID_CMD_LINE;
- }
-
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- return process_each_lv(cmd, argc, argv, LCK_VG_READ, &lvremove_single);
-}
-
-static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv)
+static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
{
struct volume_group *vg;
struct dm_info info;
@@ -95,7 +81,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv)
}
/* store it on disks */
- if (vg_write(vg))
+ if (!vg_write(vg))
return ECMD_FAILED;
backup(vg);
@@ -103,3 +89,14 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv)
log_print("Logical volume \"%s\" successfully removed", lv->name);
return 0;
}
+
+int lvremove(struct cmd_context *cmd, int argc, char **argv)
+{
+ if (!argc) {
+ log_error("Please enter one or more logical volume paths");
+ return EINVALID_CMD_LINE;
+ }
+
+ return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+ &lvremove_single);
+}
diff --git a/tools/lvrename.c b/tools/lvrename.c
index e84e3c91..b061abd8 100644
--- a/tools/lvrename.c
+++ b/tools/lvrename.c
@@ -26,6 +26,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
char *lv_name_old, *lv_name_new;
char *vg_name, *vg_name_new, *vg_name_old;
char *st;
+ int consistent = 1;
struct volume_group *vg;
struct logical_volume *lv;
@@ -53,7 +54,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- if (!is_valid_chars(vg_name)) {
+ if (!validate_vgname(vg_name)) {
log_error("Please provide a valid volume group name");
return EINVALID_CMD_LINE;
}
@@ -86,7 +87,14 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!is_valid_chars(lv_name_new)) {
+ /* FIXME Remove this restriction eventually */
+ if (!strncmp(lv_name_new, "snapshot", 8)) {
+ log_error("Names starting \"snapshot\" are reserved. "
+ "Please choose a different LV name.");
+ return ECMD_FAILED;
+ }
+
+ if (!validate_vgname(lv_name_new)) {
log_error
("New logical volume name \"%s\" has invalid characters",
lv_name_new);
@@ -98,9 +106,6 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
log_verbose("Checking for existing volume group \"%s\"", vg_name);
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
@@ -108,7 +113,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!(vg = vg_read(cmd, vg_name))) {
+ if (!(vg = vg_read(cmd, vg_name, &consistent))) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
goto error;
}
diff --git a/tools/lvresize.c b/tools/lvresize.c
index 974c29b8..b058d8f5 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -39,6 +39,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
struct list *pvh, *segh;
struct lv_list *lvl;
int opt = 0;
+ int consistent = 1;
enum {
LV_ANY = 0,
@@ -94,9 +95,6 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
if ((st = strrchr(lv_name, '/')))
lv_name = st + 1;
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
/* does VG exist? */
log_verbose("Finding volume group %s", vg_name);
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
@@ -104,7 +102,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!(vg = vg_read(cmd, vg_name))) {
+ if (!(vg = vg_read(cmd, vg_name, &consistent))) {
log_error("Volume group %s doesn't exist", vg_name);
goto error;
}
@@ -193,10 +191,10 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
if (extents > lv->le_count &&
!(stripes == 1 || (stripes > 1 && stripesize))) {
list_iterate(segh, &lv->segments) {
- struct stripe_segment *seg;
+ struct lv_segment *seg;
uint32_t sz, str;
- seg = list_item(segh, struct stripe_segment);
+ seg = list_item(segh, struct lv_segment);
sz = seg->stripe_size;
str = seg->stripes;
@@ -237,10 +235,10 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
"when reducing");
list_iterate(segh, &lv->segments) {
- struct stripe_segment *seg;
+ struct lv_segment *seg;
uint32_t seg_extents;
- seg = list_item(segh, struct stripe_segment);
+ seg = list_item(segh, struct lv_segment);
seg_extents = seg->len;
seg_stripesize = seg->stripe_size;
@@ -261,7 +259,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
log_error("Stripesize for striped segment should not be 0!");
goto error_cmdline;
}
-
+
if ((stripes > 1)) {
if (!(stripesize_extents = stripesize / vg->extent_size))
stripesize_extents = 1;
diff --git a/tools/lvscan.c b/tools/lvscan.c
index 044e2e6b..d0449288 100644
--- a/tools/lvscan.c
+++ b/tools/lvscan.c
@@ -20,41 +20,8 @@
#include "tools.h"
-static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv);
-
-int lvscan(struct cmd_context *cmd, int argc, char **argv)
-{
- if (argc) {
- log_error("No additional command line arguments allowed");
- return EINVALID_CMD_LINE;
- }
-
- return process_each_lv(cmd, argc, argv, LCK_VG_READ, &lvscan_single);
-
-/*********** FIXME Count! Add private struct to process_each*
-* if (!lv_total)
-* log_print("no logical volumes found");
-* else {
-* log_print
-* ("%d logical volumes with %s total in %d volume group%s",
-* lv_total, (dummy =
-* display_size(lv_capacity_total / 2, SIZE_SHORT)),
-* vg_total, vg_total == 1 ? "" : "s");
-* dbg_free(dummy);
-* dummy = NULL;
-* if (lv_active > 0)
-* printf("%d active", lv_active);
-* if (lv_active > 0 && lv_total - lv_active > 0)
-* printf(" / ");
-* if (lv_total - lv_active > 0)
-* printf("%d inactive", lv_total - lv_active);
-* printf(" logical volumes\n");
-* }
-*************/
-
-}
-
-static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv)
+static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,
+ void *handle)
{
struct dm_info info;
int lv_total = 0;
@@ -63,7 +30,6 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv)
char *dummy;
const char *active_str, *snapshot_str;
-/* FIXME Add -D arg to skip this! */
if (lv_info(lv, &info) && info.exists)
active_str = "ACTIVE ";
else
@@ -76,48 +42,28 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv)
else
snapshot_str = " ";
-/********** FIXME Snapshot
- if (lv->status & SNAPSHOT)
- dummy =
- display_size(lv->lv_remap_end *
- lv->lv_chunk_size / 2,
- SIZE_SHORT);
- else
-***********/
dummy = display_size(lv->size / 2, SIZE_SHORT);
- log_print("%s%s '%s%s/%s' [%s]%s", active_str, snapshot_str,
+ log_print("%s%s '%s%s/%s' [%s] %s", active_str, snapshot_str,
cmd->dev_dir, lv->vg->name, lv->name, dummy,
get_alloc_string(lv->alloc));
dbg_free(dummy);
- /* FIXME sprintf? */
-
-/*********** FIXME Handle segments?
- if (lv->segments[0]->stripes > 1 && !(lv->status & SNAPSHOT))
- log_print(" striped[%u]", lv->segments[0]->stripes);
-****************/
-
-/******** FIXME Device number display & Snapshot
- if (arg_count(cmd,blockdevice_ARG))
- printf(" %d:%d",
- MAJOR(lv->lv_dev),
- MINOR(lv->lv_dev));
- else
- if (lv->status & SNAPSHOT)
- printf(" of %s", lv->lv_snapshot_org->name);
-*****************/
-
lv_total++;
-/******** FIXME Snapshot
- if (lv->status & SNAPSHOT)
- lv_capacity_total +=
- lv->lv_remap_end * lv->lv_chunk_size
- else
-********/
lv_capacity_total += lv->size;
return 0;
}
+
+int lvscan(struct cmd_context *cmd, int argc, char **argv)
+{
+ if (argc) {
+ log_error("No additional command line arguments allowed");
+ return EINVALID_CMD_LINE;
+ }
+
+ return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
+ &lvscan_single);
+}
diff --git a/tools/pvchange.c b/tools/pvchange.c
index b509f007..189c94d3 100644
--- a/tools/pvchange.c
+++ b/tools/pvchange.c
@@ -20,76 +20,19 @@
#include "tools.h"
-int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv);
+/* FIXME Locking. PVs in VG. */
-int pvchange(struct cmd_context *cmd, int argc, char **argv)
-{
- int opt = 0;
- int done = 0;
- int total = 0;
-
- struct physical_volume *pv;
- char *pv_name;
-
- struct list *pvh, *pvs;
-
- if (arg_count(cmd, allocatable_ARG) == 0) {
- log_error("Please give the x option");
- return EINVALID_CMD_LINE;
- }
-
- if (!(arg_count(cmd, all_ARG)) && !argc) {
- log_error("Please give a physical volume path");
- return EINVALID_CMD_LINE;
- }
-
- if (arg_count(cmd, all_ARG) && argc) {
- log_error("Option a and PhysicalVolumePath are exclusive");
- return EINVALID_CMD_LINE;
- }
-
- if (argc) {
- log_verbose("Using physical volume(s) on command line");
- for (; opt < argc; opt++) {
- pv_name = argv[opt];
- if (!(pv = pv_read(cmd, pv_name))) {
- log_error
- ("Failed to read physical volume \"%s\"",
- pv_name);
- continue;
- }
- total++;
- done += pvchange_single(cmd, pv);
- }
- } else {
- log_verbose("Scanning for physical volume names");
- if (!(pvs = get_pvs(cmd))) {
- return ECMD_FAILED;
- }
-
- list_iterate(pvh, pvs) {
- total++;
- done += pvchange_single(cmd,
- list_item(pvh,
- struct pv_list)->pv);
- }
- }
-
- log_print("%d physical volume%s changed / %d physical volume%s "
- "not changed",
- done, done > 1 ? "s" : "",
- total - done, total - done > 1 ? "s" : "");
-
- return 0;
-}
-
-int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
+int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
+ void *handle)
{
struct volume_group *vg = NULL;
struct pv_list *pvl;
+ struct list mdas;
+ uint64_t sector;
const char *pv_name = dev_name(pv->dev);
+ int consistent = 1;
int allocatable =
!strcmp(arg_str_value(cmd, allocatable_ARG, "n"), "y");
@@ -103,7 +46,7 @@ int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
return ECMD_FAILED;
}
- if (!(vg = vg_read(cmd, pv->vg_name))) {
+ if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) {
unlock_vg(cmd, pv->vg_name);
log_error("Unable to find volume group of \"%s\"",
pv_name);
@@ -132,6 +75,18 @@ int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
pv = pvl->pv;
if (!archive(vg))
return 0;
+ } else {
+ if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) {
+ log_error("Can't get lock for orphans");
+ return ECMD_FAILED;
+ }
+
+ if (!(pv = pv_read(cmd, pv_name, &mdas, &sector))) {
+ unlock_vg(cmd, ORPHAN);
+ log_error("Unable to read PV \"%s\"", pv_name);
+ return 0;
+ }
+
}
/* change allocatability for a PV */
@@ -140,6 +95,8 @@ int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
pv_name);
if (*pv->vg_name)
unlock_vg(cmd, pv->vg_name);
+ else
+ unlock_vg(cmd, ORPHAN);
return 0;
}
@@ -148,6 +105,8 @@ int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
pv_name);
if (*pv->vg_name)
unlock_vg(cmd, pv->vg_name);
+ else
+ unlock_vg(cmd, ORPHAN);
return 0;
}
@@ -172,14 +131,82 @@ int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
backup(vg);
unlock_vg(cmd, pv->vg_name);
} else {
- if (!(pv_write(cmd, pv))) {
+ if (!(pv_write(cmd, pv, &mdas, sector))) {
+ unlock_vg(cmd, ORPHAN);
log_error("Failed to store physical volume \"%s\"",
pv_name);
return 0;
}
+ unlock_vg(cmd, ORPHAN);
}
log_print("Physical volume \"%s\" changed", pv_name);
return 1;
}
+
+int pvchange(struct cmd_context *cmd, int argc, char **argv)
+{
+ int opt = 0;
+ int done = 0;
+ int total = 0;
+
+ struct physical_volume *pv;
+ char *pv_name;
+
+ struct list *pvh, *pvs;
+ struct list mdas;
+
+ list_init(&mdas);
+
+ if (arg_count(cmd, allocatable_ARG) == 0) {
+ log_error("Please give the x option");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (!(arg_count(cmd, all_ARG)) && !argc) {
+ log_error("Please give a physical volume path");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, all_ARG) && argc) {
+ log_error("Option a and PhysicalVolumePath are exclusive");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (argc) {
+ log_verbose("Using physical volume(s) on command line");
+ for (; opt < argc; opt++) {
+ pv_name = argv[opt];
+ /* FIXME Read VG instead - pv_read will fail */
+ if (!(pv = pv_read(cmd, pv_name, &mdas, NULL))) {
+ log_error
+ ("Failed to read physical volume \"%s\"",
+ pv_name);
+ continue;
+ }
+ total++;
+ done += pvchange_single(cmd, pv, NULL);
+ }
+ } else {
+ log_verbose("Scanning for physical volume names");
+ if (!(pvs = get_pvs(cmd))) {
+ return ECMD_FAILED;
+ }
+
+ list_iterate(pvh, pvs) {
+ total++;
+ done += pvchange_single(cmd,
+ list_item(pvh,
+ struct pv_list)->pv,
+ NULL);
+ }
+ }
+
+ log_print("%d physical volume%s changed / %d physical volume%s "
+ "not changed",
+ done, done > 1 ? "s" : "",
+ total - done, total - done > 1 ? "s" : "");
+
+ return 0;
+}
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index 0cc1d95f..7ca11ede 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -19,6 +19,7 @@
*/
#include "tools.h"
+#include "defaults.h"
const char _really_init[] =
"Really INITIALIZE physical volume \"%s\" of volume group \"%s\" [y/n]? ";
@@ -39,7 +40,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
}
/* is there a pv here already */
- if (!(pv = pv_read(cmd, name)))
+ if (!(pv = pv_read(cmd, name, NULL, NULL)))
return 1;
/* orphan ? */
@@ -72,20 +73,28 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
return 1;
}
-static void pvcreate_single(struct cmd_context *cmd, const char *pv_name)
+static void pvcreate_single(struct cmd_context *cmd, const char *pv_name,
+ void *handle)
{
- struct physical_volume *pv;
- struct format_instance *fid;
+ struct physical_volume *pv, *existing_pv;
struct id id, *idp = NULL;
char *uuid;
uint64_t size = 0;
struct device *dev;
+ struct list mdas;
+ int pvmetadatacopies;
+ uint64_t pvmetadatasize;
+ struct volume_group *vg;
+ char *restorefile;
+ uint64_t pe_start = 0;
+ uint32_t extent_count = 0, extent_size = 0;
if (arg_count(cmd, uuidstr_ARG)) {
uuid = arg_str_value(cmd, uuidstr_ARG, "");
if (!id_read_format(&id, uuid))
return;
- if ((dev = uuid_map_lookup(cmd->um, &id))) {
+ if ((dev = device_from_pvid(cmd, &id)) &&
+ (dev != dev_cache_get(pv_name, cmd->filter))) {
log_error("uuid %s already in use on \"%s\"", uuid,
dev_name(dev));
return;
@@ -93,32 +102,84 @@ static void pvcreate_single(struct cmd_context *cmd, const char *pv_name)
idp = &id;
}
- if (!pvcreate_check(cmd, pv_name))
+ if (arg_count(cmd, restorefile_ARG)) {
+ restorefile = arg_str_value(cmd, restorefile_ARG, "");
+ /* The uuid won't already exist */
+ init_partial(1);
+ if (!(vg = backup_read_vg(cmd, NULL, restorefile))) {
+ log_error("Unable to read volume group from %s",
+ restorefile);
+ return;
+ }
+ init_partial(0);
+ if (!(existing_pv = find_pv_in_vg_by_uuid(vg, idp))) {
+ log_error("Can't find uuid %s in backup file %s",
+ uuid, restorefile);
+ return;
+ }
+ pe_start = existing_pv->pe_start;
+ extent_size = existing_pv->pe_size;
+ extent_count = existing_pv->pe_count;
+ }
+
+ if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
+ log_error("Can't get lock for orphan PVs");
return;
+ }
+
+ if (!pvcreate_check(cmd, pv_name))
+ goto error;
size = arg_int64_value(cmd, physicalvolumesize_ARG, 0) * 2;
- /* FIXME Use config file/cmd line to specify format */
- if (!(fid = cmd->fmt1->ops->create_instance(cmd->fmt1, NULL, NULL))) {
- log_error("Failed to create format1 instance");
- return;
+ pvmetadatasize = arg_int64_value(cmd, metadatasize_ARG, 0) * 2;
+ if (!pvmetadatasize)
+ pvmetadatasize = find_config_int(cmd->cf->root,
+ "metadata/pvmetadatasize",
+ '/', DEFAULT_PVMETADATASIZE);
+
+ pvmetadatacopies = arg_int_value(cmd, metadatacopies_ARG, -1);
+ if (pvmetadatacopies < 0)
+ pvmetadatacopies = find_config_int(cmd->cf->root,
+ "metadata/pvmetadatacopies",
+ '/',
+ DEFAULT_PVMETADATACOPIES);
+
+ if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
+ log_error("%s: Couldn't find device.", pv_name);
+ goto error;
}
- if (!(pv = pv_create(fid, pv_name, idp, size))) {
+
+ list_init(&mdas);
+ if (!(pv = pv_create(cmd->fmt, dev, idp, size, pe_start,
+ extent_count, extent_size,
+ pvmetadatacopies, pvmetadatasize, &mdas))) {
log_error("Failed to setup physical volume \"%s\"", pv_name);
- return;
+ goto error;
}
log_verbose("Set up physical volume for \"%s\" with %" PRIu64
- " sectors", pv_name, pv->size);
+ " available sectors", pv_name, pv->size);
+
+ /* Wipe existing label first */
+ if (!label_remove(pv->dev)) {
+ log_error("Failed to wipe existing label on %s", pv_name);
+ goto error;
+ }
log_very_verbose("Writing physical volume data to disk \"%s\"",
pv_name);
- if (!(pv_write(cmd, pv))) {
+ if (!(pv_write(cmd, pv, &mdas, arg_int_value(cmd, labelsector_ARG,
+ DEFAULT_LABELSECTOR)))) {
log_error("Failed to write physical volume \"%s\"", pv_name);
- return;
+ goto error;
}
log_print("Physical volume \"%s\" successfully created", pv_name);
+
+ error:
+ unlock_vg(cmd, "");
+ return;
}
int pvcreate(struct cmd_context *cmd, int argc, char **argv)
@@ -130,6 +191,11 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (arg_count(cmd, restorefile_ARG) && !arg_count(cmd, uuidstr_ARG)) {
+ log_error("--uuid is required with --restorefile");
+ return EINVALID_CMD_LINE;
+ }
+
if (arg_count(cmd, uuidstr_ARG) && argc != 1) {
log_error("Can only set uuid on one volume at once");
return EINVALID_CMD_LINE;
@@ -140,8 +206,27 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
+ if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) {
+ log_error("labelsector must be less than %lu",
+ LABEL_SCAN_SECTORS);
+ return EINVALID_CMD_LINE;
+ }
+
+ if (!(cmd->fmt->features & FMT_MDAS) &&
+ (arg_count(cmd, metadatacopies_ARG) ||
+ arg_count(cmd, metadatasize_ARG))) {
+ log_error("Metadata parameters only apply to text format");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, metadatacopies_ARG) &&
+ arg_int_value(cmd, metadatacopies_ARG, -1) > 2) {
+ log_error("Metadatacopies may only be 0, 1 or 2");
+ return EINVALID_CMD_LINE;
+ }
+
for (i = 0; i < argc; i++) {
- pvcreate_single(cmd, argv[i]);
+ pvcreate_single(cmd, argv[i], NULL);
pool_empty(cmd->mem);
}
diff --git a/tools/pvdisplay.c b/tools/pvdisplay.c
index b526cc9b..ff4d121a 100644
--- a/tools/pvdisplay.c
+++ b/tools/pvdisplay.c
@@ -20,44 +20,8 @@
#include "tools.h"
-void pvdisplay_single(struct cmd_context *cmd, struct physical_volume *pv);
-
-int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
-{
- int opt = 0;
-
- struct list *pvh, *pvs;
- struct physical_volume *pv;
-
- if (arg_count(cmd, colon_ARG) && arg_count(cmd, maps_ARG)) {
- log_error("Option -v not allowed with option -c");
- return EINVALID_CMD_LINE;
- }
-
- if (argc) {
- log_very_verbose("Using physical volume(s) on command line");
-
- for (; opt < argc; opt++) {
- if (!(pv = pv_read(cmd, argv[opt]))) {
- log_error("Failed to read physical "
- "volume \"%s\"", argv[opt]);
- continue;
- }
- pvdisplay_single(cmd, pv);
- }
- } else {
- log_verbose("Scanning for physical volume names");
- if (!(pvs = get_pvs(cmd)))
- return ECMD_FAILED;
-
- list_iterate(pvh, pvs)
- pvdisplay_single(cmd, list_item(pvh, struct pv_list)->pv);
- }
-
- return 0;
-}
-
-void pvdisplay_single(struct cmd_context *cmd, struct physical_volume *pv)
+void pvdisplay_single(struct cmd_context *cmd, struct physical_volume *pv,
+ void *handle)
{
char *sz;
uint64_t size;
@@ -80,50 +44,57 @@ void pvdisplay_single(struct cmd_context *cmd, struct physical_volume *pv)
log_print("Physical volume \"%s\" of volume group \"%s\" "
"is exported", pv_name, pv->vg_name);
-/********* FIXME
- log_error("no physical volume identifier on \"%s\"" , pv_name);
-*********/
-
if (!pv->vg_name) {
log_print("\"%s\" is a new physical volume of \"%s\"",
pv_name, (sz = display_size(size / 2, SIZE_SHORT)));
dbg_free(sz);
}
-/* FIXME: Check active - no point?
- log_very_verbose("checking physical volume activity" );
- pv_check_active ( pv->vg_name, pv->pv_name)
- pv_status ( pv->vg_name, pv->pv_name, &pv)
-*/
-
-/* FIXME: Check consistency - do this when reading metadata BUT trigger mesgs
- log_very_verbose("checking physical volume consistency" );
- ret = pv_check_consistency (pv)
-*/
-
if (arg_count(cmd, colon_ARG)) {
pvdisplay_colons(pv);
return;
}
- pvdisplay_full(pv);
+ pvdisplay_full(pv, handle);
if (!arg_count(cmd, maps_ARG))
return;
-/******* FIXME
- if (pv->pe_alloc_count) {
- if (!(pv->pe = pv_read_pe(pv_name, pv)))
- goto pvdisplay_device_out;
- if (!(lvs = pv_read_lvs(pv))) {
- log_error("Failed to read LVs on \"%s\"", pv->pv_name);
- goto pvdisplay_device_out;
+ return;
+}
+
+int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
+{
+ int opt = 0;
+
+ struct list *pvh, *pvs;
+ struct physical_volume *pv;
+
+ if (arg_count(cmd, colon_ARG) && arg_count(cmd, maps_ARG)) {
+ log_error("Option -v not allowed with option -c");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (argc) {
+ log_very_verbose("Using physical volume(s) on command line");
+
+ for (; opt < argc; opt++) {
+ if (!(pv = pv_read(cmd, argv[opt], NULL, NULL))) {
+ log_error("Failed to read physical "
+ "volume \"%s\"", argv[opt]);
+ continue;
+ }
+ pvdisplay_single(cmd, pv, NULL);
}
- pv_display_pe_text(pv, pv->pe, lvs);
- } else
- log_print("no logical volume on physical volume \"%s\"",
- pv_name);
-**********/
+ } else {
+ log_verbose("Scanning for physical volume names");
+ if (!(pvs = get_pvs(cmd)))
+ return ECMD_FAILED;
- return;
+ list_iterate(pvh, pvs)
+ pvdisplay_single(cmd, list_item(pvh, struct pv_list)->pv,
+ NULL);
+ }
+
+ return 0;
}
diff --git a/tools/pvremove.c b/tools/pvremove.c
new file mode 100644
index 00000000..3410378f
--- /dev/null
+++ b/tools/pvremove.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2002 Sistina Software
+ *
+ * pvcreate is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * pvcreate is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LVM; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "tools.h"
+#include "defaults.h"
+
+const char _really_wipe[] =
+ "Really WIPE LABELS from physical volume \"%s\" of volume group \"%s\" [y/n]? ";
+
+/*
+ * Decide whether it is "safe" to wipe the labels on this device.
+ * 0 indicates we may not.
+ */
+static int pvremove_check(struct cmd_context *cmd, const char *name)
+{
+ struct physical_volume *pv;
+
+ /* is the partition type set correctly ? */
+ if ((arg_count(cmd, force_ARG) < 1) && !is_lvm_partition(name)) {
+ log_error("%s: Not LVM partition type: use -f to override",
+ name);
+ return 0;
+ }
+
+ /* is there a pv here already */
+ if (!(pv = pv_read(cmd, name, NULL, NULL)))
+ return 1;
+
+ /* orphan ? */
+ if (!pv->vg_name[0])
+ return 1;
+
+ /* Allow partial & exported VGs to be destroyed. */
+ /* we must have -ff to overwrite a non orphan */
+ if (arg_count(cmd, force_ARG) < 2) {
+ log_error("Can't pvremove physical volume \"%s\" of "
+ "volume group \"%s\" without -ff", name, pv->vg_name);
+ return 0;
+ }
+
+ /* prompt */
+ if (!arg_count(cmd, yes_ARG) &&
+ yes_no_prompt(_really_wipe, name, pv->vg_name) == 'n') {
+ log_print("%s: physical volume label not removed", name);
+ return 0;
+ }
+
+ if (arg_count(cmd, force_ARG)) {
+ log_print("WARNING: Wiping physical volume label from "
+ "%s%s%s%s", name,
+ pv->vg_name[0] ? " of volume group \"" : "",
+ pv->vg_name[0] ? pv->vg_name : "",
+ pv->vg_name[0] ? "\"" : "");
+ }
+
+ return 1;
+}
+
+static void pvremove_single(struct cmd_context *cmd, const char *pv_name,
+ void *handle)
+{
+ struct device *dev;
+
+ if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
+ log_error("Can't get lock for orphan PVs");
+ return;
+ }
+
+ if (!pvremove_check(cmd, pv_name))
+ goto error;
+
+ if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
+ log_error("%s: Couldn't find device.", pv_name);
+ goto error;
+ }
+
+ /* Wipe existing label(s) */
+ if (!label_remove(dev)) {
+ log_error("Failed to wipe existing label(s) on %s", pv_name);
+ goto error;
+ }
+
+ log_print("Labels on physical volume \"%s\" successfully wiped",
+ pv_name);
+
+ error:
+ unlock_vg(cmd, "");
+ return;
+}
+
+int pvremove(struct cmd_context *cmd, int argc, char **argv)
+{
+ int i;
+
+ if (!argc) {
+ log_error("Please enter a physical volume path");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, yes_ARG) && !arg_count(cmd, force_ARG)) {
+ log_error("Option y can only be given with option f");
+ return EINVALID_CMD_LINE;
+ }
+
+ for (i = 0; i < argc; i++) {
+ pvremove_single(cmd, argv[i], NULL);
+ pool_empty(cmd->mem);
+ }
+
+ return 0;
+}
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 868dea47..3f3b2f1b 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -20,11 +20,95 @@
#include "tools.h"
-void pvscan_display_single(struct cmd_context *cmd, struct physical_volume *pv);
-
int pv_max_name_len = 0;
int vg_max_name_len = 0;
+void pvscan_display_single(struct cmd_context *cmd, struct physical_volume *pv,
+ void *handle)
+{
+ char uuid[64];
+ int vg_name_len = 0;
+
+ char *s1, *s2;
+
+ char pv_tmp_name[NAME_LEN] = { 0, };
+ char vg_tmp_name[NAME_LEN] = { 0, };
+ char vg_name_this[NAME_LEN] = { 0, };
+
+ /* short listing? */
+ if (arg_count(cmd, short_ARG) > 0) {
+ log_print("%s", dev_name(pv->dev));
+ return;
+ }
+
+ if (arg_count(cmd, verbose_ARG) > 1) {
+ /* FIXME As per pv_display! Drop through for now. */
+ /* pv_show(pv); */
+
+ /* FIXME - Moved to Volume Group structure */
+ /* log_print("System Id %s", pv->vg->system_id); */
+
+ /* log_print(" "); */
+ /* return; */
+ }
+
+ memset(pv_tmp_name, 0, sizeof(pv_tmp_name));
+
+ vg_name_len = strlen(pv->vg_name) + 1;
+
+ if (arg_count(cmd, uuid_ARG)) {
+ if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
+ stack;
+ return;
+ }
+
+ sprintf(pv_tmp_name, "%-*s with UUID %s",
+ pv_max_name_len - 2, dev_name(pv->dev), uuid);
+ } else {
+ sprintf(pv_tmp_name, "%s", dev_name(pv->dev));
+ }
+
+ if (!*pv->vg_name) {
+ log_print("PV %-*s %-*s %s [%s]",
+ pv_max_name_len, pv_tmp_name,
+ vg_max_name_len, " ",
+ pv->fmt ? pv->fmt->name : " ",
+ (s1 = display_size(pv->size / 2, SIZE_SHORT)));
+ dbg_free(s1);
+ return;
+ }
+
+ if (pv->status & EXPORTED_VG) {
+ strncpy(vg_name_this, pv->vg_name, vg_name_len);
+ log_print("PV %-*s is in exported VG %s "
+ "[%s / %s free]",
+ pv_max_name_len, pv_tmp_name,
+ vg_name_this, (s1 =
+ display_size(pv->pe_count *
+ pv->pe_size / 2,
+ SIZE_SHORT)),
+ (s2 = display_size((pv->pe_count - pv->pe_alloc_count)
+ * pv->pe_size / 2, SIZE_SHORT)));
+ dbg_free(s1);
+ dbg_free(s2);
+ return;
+ }
+
+ sprintf(vg_tmp_name, "%s", pv->vg_name);
+ log_print
+ ("PV %-*s VG %-*s %s [%s / %s free]", pv_max_name_len,
+ pv_tmp_name, vg_max_name_len, vg_tmp_name,
+ pv->fmt ? pv->fmt->name : " ",
+ (s1 = display_size(pv->pe_count * pv->pe_size / 2, SIZE_SHORT)),
+ (s2 =
+ display_size((pv->pe_count - pv->pe_alloc_count) * pv->pe_size /
+ 2, SIZE_SHORT)));
+ dbg_free(s1);
+ dbg_free(s2);
+
+ return;
+}
+
int pvscan(struct cmd_context *cmd, int argc, char **argv)
{
int new_pvs_found = 0;
@@ -56,6 +140,9 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
log_verbose("Wiping cache of LVM-capable devices");
persistent_filter_wipe(cmd->filter);
+ log_verbose("Wiping internal cache");
+ cache_destroy();
+
log_verbose("Walking through all physical volumes");
if (!(pvs = get_pvs(cmd)))
return ECMD_FAILED;
@@ -108,7 +195,8 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
vg_max_name_len += 2;
list_iterate(pvh, pvs)
- pvscan_display_single(cmd, list_item(pvh, struct pv_list)->pv);
+ pvscan_display_single(cmd, list_item(pvh, struct pv_list)->pv,
+ NULL);
if (!pvs_found) {
log_print("No matching physical volumes found");
@@ -128,87 +216,3 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
return 0;
}
-
-void pvscan_display_single(struct cmd_context *cmd, struct physical_volume *pv)
-{
- char uuid[64];
- int vg_name_len = 0;
-
- char *s1, *s2;
-
- char pv_tmp_name[NAME_LEN] = { 0, };
- char vg_tmp_name[NAME_LEN] = { 0, };
- char vg_name_this[NAME_LEN] = { 0, };
-
- /* short listing? */
- if (arg_count(cmd, short_ARG) > 0) {
- log_print("%s", dev_name(pv->dev));
- return;
- }
-
- if (arg_count(cmd, verbose_ARG) > 1) {
- /* FIXME As per pv_display! Drop through for now. */
- /* pv_show(pv); */
-
- /* FIXME - Moved to Volume Group structure */
- /* log_print("System Id %s", pv->vg->system_id); */
-
- /* log_print(" "); */
- /* return; */
- }
-
- memset(pv_tmp_name, 0, sizeof(pv_tmp_name));
-
- vg_name_len = strlen(pv->vg_name) + 1;
-
- if (arg_count(cmd, uuid_ARG)) {
- if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
- stack;
- return;
- }
-
- sprintf(pv_tmp_name, "%-*s with UUID %s",
- pv_max_name_len - 2, dev_name(pv->dev), uuid);
- } else {
- sprintf(pv_tmp_name, "%s", dev_name(pv->dev));
- }
-
- if (!*pv->vg_name) {
- log_print("PV %-*s %-*s [%s]",
- pv_max_name_len, pv_tmp_name,
- vg_max_name_len, " ",
- (s1 = display_size(pv->size / 2, SIZE_SHORT)));
- dbg_free(s1);
- return;
- }
-
- if (pv->status & EXPORTED_VG) {
- strncpy(vg_name_this, pv->vg_name, vg_name_len);
- log_print("PV %-*s is in exported VG %s "
- "[%s / %s free]",
- pv_max_name_len, pv_tmp_name,
- vg_name_this, (s1 =
- display_size(pv->pe_count *
- pv->pe_size / 2,
- SIZE_SHORT)),
- (s2 = display_size((pv->pe_count - pv->pe_alloc_count)
- * pv->pe_size / 2, SIZE_SHORT)));
- dbg_free(s1);
- dbg_free(s2);
- return;
- }
-
- sprintf(vg_tmp_name, "%s", pv->vg_name);
- log_print
- ("PV %-*s VG %-*s %s [%s / %s free]", pv_max_name_len,
- pv_tmp_name, vg_max_name_len, vg_tmp_name,
- pv->fid ? pv->fid->fmt->name : " ",
- (s1 = display_size(pv->pe_count * pv->pe_size / 2, SIZE_SHORT)),
- (s2 =
- display_size((pv->pe_count - pv->pe_alloc_count) * pv->pe_size /
- 2, SIZE_SHORT)));
- dbg_free(s1);
- dbg_free(s2);
-
- return;
-}
diff --git a/tools/stub.h b/tools/stub.h
index 185535c0..8ffefe13 100644
--- a/tools/stub.h
+++ b/tools/stub.h
@@ -6,10 +6,10 @@
#define unimplemented \
{ log_error("Command not implemented yet."); return ECMD_FAILED;}
+/*int e2fsadm(struct cmd_context *cmd, int argc, char **argv) unimplemented*/
int lvmsadc(struct cmd_context *cmd, int argc, char **argv) unimplemented
int lvmsar(struct cmd_context *cmd, int argc, char **argv) unimplemented
int pvdata(struct cmd_context *cmd, int argc, char **argv) unimplemented
int pvmove(struct cmd_context *cmd, int argc, char **argv) unimplemented
int pvresize(struct cmd_context *cmd, int argc, char **argv) unimplemented
int vgmknodes(struct cmd_context *cmd, int argc, char **argv) unimplemented
-
diff --git a/tools/toollib.c b/tools/toollib.c
index 9b628ab0..917b4ff0 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -9,8 +9,10 @@
#include <sys/stat.h>
int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
+ void *handle,
int (*process_single) (struct cmd_context * cmd,
- struct logical_volume * lv))
+ struct logical_volume * lv,
+ void *handle))
{
int ret_max = 0;
int ret = 0;
@@ -25,7 +27,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
- ret = process_single(cmd, lv);
+ ret = process_single(cmd, lv, handle);
if (ret > ret_max)
ret_max = ret;
}
@@ -34,94 +36,163 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
}
+struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname,
+ int lock_type)
+{
+ int consistent = 1;
+
+ lock_type &= ~LCK_TYPE_MASK;
+ lock_type |= LCK_WRITE;
+
+ if (!lock_vol(cmd, vgname, lock_type)) {
+ log_error("Can't lock %s for metadata recovery: skipping",
+ vgname);
+ return NULL;
+ }
+
+ return vg_read(cmd, vgname, &consistent);
+}
+
int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
- int lock_type,
+ int lock_type, void *handle,
int (*process_single) (struct cmd_context * cmd,
- struct logical_volume * lv))
+ struct logical_volume * lv,
+ void *handle))
{
int opt = 0;
int ret_max = 0;
int ret = 0;
int vg_count = 0;
+ int consistent;
- struct list *vgh, *vgs;
+ struct list *slh, *vgnames;
struct volume_group *vg;
struct logical_volume *lv;
struct lv_list *lvl;
- char *vg_name;
+ char *vgname;
if (argc) {
log_verbose("Using logical volume(s) on command line");
for (; opt < argc; opt++) {
char *lv_name = argv[opt];
-
- /* does VG exist? */
- if (!(vg_name = extract_vgname(cmd, lv_name))) {
- if (ret_max < ECMD_FAILED)
- ret_max = ECMD_FAILED;
- continue;
+ int vgname_provided = 1;
+
+ /* Do we have a vgname or lvname? */
+ vgname = lv_name;
+ if (!strncmp(vgname, cmd->dev_dir,
+ strlen(cmd->dev_dir)))
+ vgname += strlen(cmd->dev_dir);
+ if (strchr(vgname, '/')) {
+ /* Must be an LV */
+ vgname_provided = 0;
+ if (!(vgname = extract_vgname(cmd, lv_name))) {
+ if (ret_max < ECMD_FAILED)
+ ret_max = ECMD_FAILED;
+ continue;
+ }
}
- log_verbose("Finding volume group \"%s\"", vg_name);
- if (!lock_vol(cmd, vg_name, lock_type)) {
- log_error("Can't lock %s: skipping", vg_name);
+ log_verbose("Finding volume group \"%s\"", vgname);
+ if (!lock_vol(cmd, vgname, lock_type)) {
+ log_error("Can't lock %s: skipping", vgname);
continue;
}
- if (!(vg = vg_read(cmd, vg_name))) {
- log_error("Volume group \"%s\" doesn't exist",
- vg_name);
- if (ret_max < ECMD_FAILED)
- ret_max = ECMD_FAILED;
- unlock_vg(cmd, vg_name);
- continue;
+ if (lock_type & LCK_WRITE)
+ consistent = 1;
+ else
+ consistent = 0;
+ if (!(vg = vg_read(cmd, vgname, &consistent)) ||
+ !consistent) {
+ unlock_vg(cmd, vgname);
+ if (!vg)
+ log_error("Volume group \"%s\" "
+ "not found", vgname);
+ else
+ log_error("Volume group \"%s\" "
+ "inconsistent", vgname);
+ if (!vg || !(vg =
+ recover_vg(cmd, vgname,
+ lock_type))) {
+ unlock_vg(cmd, vgname);
+ if (ret_max < ECMD_FAILED)
+ ret_max = ECMD_FAILED;
+ continue;
+ }
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported",
vg->name);
- unlock_vg(cmd, vg_name);
+ unlock_vg(cmd, vgname);
return ECMD_FAILED;
}
+ if (vgname_provided) {
+ if ((ret =
+ process_each_lv_in_vg(cmd, vg, handle,
+ process_single)) >
+ ret_max)
+ ret_max = ret;
+ unlock_vg(cmd, vgname);
+ continue;
+ }
+
if (!(lvl = find_lv_in_vg(vg, lv_name))) {
log_error("Can't find logical volume \"%s\" "
"in volume group \"%s\"",
- lv_name, vg_name);
+ lv_name, vgname);
if (ret_max < ECMD_FAILED)
ret_max = ECMD_FAILED;
- unlock_vg(cmd, vg_name);
+ unlock_vg(cmd, vgname);
continue;
}
lv = lvl->lv;
- if ((ret = process_single(cmd, lv)) > ret_max)
+ if ((ret = process_single(cmd, lv, handle)) > ret_max)
ret_max = ret;
- unlock_vg(cmd, vg_name);
+ unlock_vg(cmd, vgname);
}
} else {
log_verbose("Finding all logical volumes");
- if (!(vgs = get_vgs(cmd))) {
+ if (!(vgnames = get_vgs(cmd, 0))) {
log_error("No volume groups found");
return ECMD_FAILED;
}
- list_iterate(vgh, vgs) {
- vg_name = list_item(vgh, struct name_list)->name;
- if (!lock_vol(cmd, vg_name, lock_type)) {
- log_error("Can't lock %s: skipping", vg_name);
+ list_iterate(slh, vgnames) {
+ vgname = list_item(slh, struct str_list)->str;
+ if (!vgname || !*vgname)
+ continue; /* FIXME Unnecessary? */
+ if (!lock_vol(cmd, vgname, lock_type)) {
+ log_error("Can't lock %s: skipping", vgname);
continue;
}
- if (!(vg = vg_read(cmd, vg_name))) {
- log_error("Volume group \"%s\" not found",
- vg_name);
- if (ret_max < ECMD_FAILED)
- ret_max = ECMD_FAILED;
- unlock_vg(cmd, vg_name);
- continue;
+ if (lock_type & LCK_WRITE)
+ consistent = 1;
+ else
+ consistent = 0;
+ if (!(vg = vg_read(cmd, vgname, &consistent)) ||
+ !consistent) {
+ unlock_vg(cmd, vgname);
+ if (!vg)
+ log_error("Volume group \"%s\" "
+ "not found", vgname);
+ else
+ log_error("Volume group \"%s\" "
+ "inconsistent", vgname);
+ if (!vg || !(vg =
+ recover_vg(cmd, vgname,
+ lock_type))) {
+ unlock_vg(cmd, vgname);
+ if (ret_max < ECMD_FAILED)
+ ret_max = ECMD_FAILED;
+ continue;
+ }
}
- ret = process_each_lv_in_vg(cmd, vg, process_single);
- unlock_vg(cmd, vg_name);
+ ret = process_each_lv_in_vg(cmd, vg, handle,
+ process_single);
+ unlock_vg(cmd, vgname);
if (ret > ret_max)
ret_max = ret;
vg_count++;
@@ -132,16 +203,18 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
}
int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- int lock_type,
+ int lock_type, int consistent, void *handle,
int (*process_single) (struct cmd_context * cmd,
- const char *vg_name))
+ const char *vg_name,
+ struct volume_group * vg,
+ int consistent, void *handle))
{
int opt = 0;
int ret_max = 0;
int ret = 0;
- struct list *vgh;
- struct list *vgs;
+ struct list *slh, *vgnames;
+ struct volume_group *vg;
char *vg_name;
char *dev_dir = cmd->dev_dir;
@@ -161,24 +234,32 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
log_error("Can't lock %s: skipping", vg_name);
continue;
}
- if ((ret = process_single(cmd, vg_name)) > ret_max)
+ log_verbose("Finding volume group \"%s\"", vg_name);
+ vg = vg_read(cmd, vg_name, &consistent);
+ if ((ret = process_single(cmd, vg_name, vg, consistent,
+ handle))
+ > ret_max)
ret_max = ret;
unlock_vg(cmd, vg_name);
}
} else {
log_verbose("Finding all volume groups");
- if (!(vgs = get_vgs(cmd))) {
+ if (!(vgnames = get_vgs(cmd, 0)) || list_empty(vgnames)) {
log_error("No volume groups found");
return ECMD_FAILED;
}
- list_iterate(vgh, vgs) {
- vg_name = list_item(vgh, struct name_list)->name;
+ list_iterate(slh, vgnames) {
+ vg_name = list_item(slh, struct str_list)->str;
+ if (!vg_name || !*vg_name)
+ continue; /* FIXME Unnecessary? */
if (!lock_vol(cmd, vg_name, lock_type)) {
log_error("Can't lock %s: skipping", vg_name);
continue;
}
- ret = process_single(cmd, vg_name);
-
+ log_verbose("Finding volume group \"%s\"", vg_name);
+ vg = vg_read(cmd, vg_name, &consistent);
+ ret = process_single(cmd, vg_name, vg, consistent,
+ handle);
if (ret > ret_max)
ret_max = ret;
unlock_vg(cmd, vg_name);
@@ -189,9 +270,11 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
}
int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
+ void *handle,
int (*process_single) (struct cmd_context * cmd,
struct volume_group * vg,
- struct physical_volume * pv))
+ struct physical_volume * pv,
+ void *handle))
{
int ret_max = 0;
int ret = 0;
@@ -201,7 +284,7 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
- if ((ret = process_single(cmd, vg, pv)) > ret_max)
+ if ((ret = process_single(cmd, vg, pv, handle)) > ret_max)
ret_max = ret;
}
@@ -209,10 +292,11 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
}
int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
- struct volume_group *vg,
+ struct volume_group *vg, void *handle,
int (*process_single) (struct cmd_context * cmd,
struct volume_group * vg,
- struct physical_volume * pv))
+ struct physical_volume * pv,
+ void *handle))
{
int opt = 0;
int ret_max = 0;
@@ -229,32 +313,18 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
vg->name);
continue;
}
- ret = process_single(cmd, vg, pvl->pv);
+ ret = process_single(cmd, vg, pvl->pv, handle);
if (ret > ret_max)
ret_max = ret;
}
} else {
log_verbose("Using all physical volume(s) in volume group");
- process_each_pv_in_vg(cmd, vg, process_single);
+ process_each_pv_in_vg(cmd, vg, handle, process_single);
}
return ret_max;
}
-int is_valid_chars(char *n)
-{
- register char c;
-
- /* Hyphen used as VG-LV separator - ambiguity if LV starts with it */
- if (*n == '-')
- return 0;
-
- while ((c = *n++))
- if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+')
- return 0;
- return 1;
-}
-
char *extract_vgname(struct cmd_context *cmd, char *lv_name)
{
char *vg_name = lv_name;
diff --git a/tools/toollib.h b/tools/toollib.h
index 49f06fbe..8b5ef7ed 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -29,30 +29,42 @@ int autobackup_init(const char *backup_dir, int keep_days, int keep_number,
int autobackup);
int autobackup(struct volume_group *vg);
+struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname,
+ int lock_type);
+
int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- int lock_type,
+ int lock_type, int consistent, void *handle,
int (*process_single) (struct cmd_context * cmd,
- const char *vg_name));
+ const char *vg_name,
+ struct volume_group *vg,
+ int consistent,
+ void *handle));
int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
- struct volume_group *vg,
+ struct volume_group *vg, void *handle,
int (*process_single) (struct cmd_context * cmd,
struct volume_group * vg,
- struct physical_volume * pv));
+ struct physical_volume * pv,
+ void *handle));
+
int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
- int lock_type,
+ int lock_type, void *handle,
int (*process_single) (struct cmd_context * cmd,
- struct logical_volume * lv));
+ struct logical_volume * lv,
+ void *handle));
int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
+ void *handle,
int (*process_single) (struct cmd_context * cmd,
struct volume_group * vg,
- struct physical_volume * pv));
+ struct physical_volume * pv,
+ void *handle));
+
int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
+ void *handle,
int (*process_single) (struct cmd_context * cmd,
- struct logical_volume * lv));
-
-int is_valid_chars(char *n);
+ struct logical_volume * lv,
+ void *handle));
char *default_vgname(struct cmd_context *cmd);
char *extract_vgname(struct cmd_context *cmd, char *lv_name);
diff --git a/tools/tools.h b/tools/tools.h
index cd148967..2f253204 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -7,39 +7,40 @@
#ifndef _LVM_TOOLS_H
#define _LVM_TOOLS_H
-#include "pool.h"
-#include "dbg_malloc.h"
-#include "list.h"
-#include "log.h"
-#include "lvm-string.h"
-#include "lvm-file.h"
-#include "metadata.h"
+#define _GNU_SOURCE
+
+#include "activate.h"
+#include "archive.h"
+#include "cache.h"
#include "config.h"
+#include "dbg_malloc.h"
#include "dev-cache.h"
#include "device.h"
-#include "vgcache.h"
#include "display.h"
#include "errors.h"
#include "filter.h"
-#include "filter-persistent.h"
#include "filter-composite.h"
+#include "filter-persistent.h"
#include "filter-regex.h"
-#include "format1.h"
#include "format-text.h"
-#include "toollib.h"
-#include "activate.h"
-#include "archive.h"
+#include "metadata.h"
+#include "list.h"
#include "locking.h"
+#include "log.h"
+#include "lvm-file.h"
+#include "lvm-string.h"
+#include "pool.h"
#include "toolcontext.h"
+#include "toollib.h"
-#include <stdio.h>
+#include <ctype.h>
+#include <limits.h>
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/types.h>
-#include <ctype.h>
-#include <string.h>
-#include <limits.h>
#define CMD_LEN 256
#define MAX_ARGS 64
@@ -68,7 +69,7 @@ typedef enum {
struct arg {
char short_arg;
char *long_arg;
- int (*fn) (struct arg * a);
+ int (*fn) (struct cmd_context * cmd, struct arg * a);
int count;
char *value;
@@ -92,14 +93,14 @@ struct command {
void usage(const char *name);
/* the argument verify/normalise functions */
-int yes_no_arg(struct arg *a);
-int size_arg(struct arg *a);
-int int_arg(struct arg *a);
-int int_arg_with_sign(struct arg *a);
-int minor_arg(struct arg *a);
-int string_arg(struct arg *a);
-int permission_arg(struct arg *a);
-int metadatatype_arg(struct arg *a);
+int yes_no_arg(struct cmd_context *cmd, struct arg *a);
+int size_arg(struct cmd_context *cmd, struct arg *a);
+int int_arg(struct cmd_context *cmd, struct arg *a);
+int int_arg_with_sign(struct cmd_context *cmd, struct arg *a);
+int minor_arg(struct cmd_context *cmd, struct arg *a);
+int string_arg(struct cmd_context *cmd, struct arg *a);
+int permission_arg(struct cmd_context *cmd, struct arg *a);
+int metadatatype_arg(struct cmd_context *cmd, struct arg *a);
char yes_no_prompt(const char *prompt, ...);
@@ -151,13 +152,4 @@ static inline const char *command_name(struct cmd_context *cmd)
return cmd->command->name;
}
-static inline int driver_is_loaded(void)
-{
- int i = driver_version(NULL, 0);
-
- if (!i)
- log_error("device-mapper driver/module not loaded?");
- return i;
-}
-
#endif
diff --git a/tools/vgcfgbackup.c b/tools/vgcfgbackup.c
index a7801589..46f90ec6 100644
--- a/tools/vgcfgbackup.c
+++ b/tools/vgcfgbackup.c
@@ -6,44 +6,29 @@
#include "tools.h"
-#include <stdio.h>
-
-static int _backup_to_file(const char *file, struct volume_group *vg)
-{
- int r;
- struct format_instance *tf;
- void *context;
-
- if (!(context = create_text_context(vg->cmd->fmtt, file,
- vg->cmd->cmd_line)) ||
- !(tf = vg->cmd->fmtt->ops->create_instance(vg->cmd->fmtt, NULL,
- context))) {
- log_error("Couldn't create backup object.");
- return 0;
- }
-
- if (!(r = tf->fmt->ops->vg_write(tf, vg, context)) ||
- !(r = tf->fmt->ops->vg_commit(tf, vg, context)))
- stack;
-
- tf->fmt->ops->destroy_instance(tf);
- return r;
-}
-
-static int vg_backup_single(struct cmd_context *cmd, const char *vg_name)
+static int vg_backup_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
{
- struct volume_group *vg;
-
- log_verbose("Checking for volume group \"%s\"", vg_name);
- if (!(vg = vg_read(cmd, vg_name))) {
+ if (!vg) {
log_error("Volume group \"%s\" not found", vg_name);
return ECMD_FAILED;
}
+ if (!consistent)
+ log_error("Warning: Volume group \"%s\" inconsistent", vg_name);
+
if (arg_count(cmd, file_ARG)) {
- _backup_to_file(arg_value(cmd, file_ARG), vg);
+ backup_to_file(arg_value(cmd, file_ARG), vg->cmd->cmd_line, vg);
} else {
+ if (!consistent) {
+ log_error("No backup taken: specify filename with -f "
+ "to backup an inconsistent VG");
+ stack;
+ return ECMD_FAILED;
+ }
+
/* just use the normal backup code */
backup_enable(1); /* force a backup */
if (!backup(vg)) {
@@ -58,8 +43,6 @@ static int vg_backup_single(struct cmd_context *cmd, const char *vg_name)
int vgcfgbackup(struct cmd_context *cmd, int argc, char **argv)
{
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- return process_each_vg(cmd, argc, argv, LCK_VG_READ, &vg_backup_single);
+ return process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
+ &vg_backup_single);
}
diff --git a/tools/vgcfgrestore.c b/tools/vgcfgrestore.c
index fe497816..2c38ed64 100644
--- a/tools/vgcfgrestore.c
+++ b/tools/vgcfgrestore.c
@@ -13,9 +13,6 @@ int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
/*
* FIXME: overloading the -l arg for now to display a
* list of archive files for a particular vg
@@ -27,13 +24,28 @@ int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv)
return 0;
}
+ if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) {
+ log_error("Unable to lock orphans");
+ return ECMD_FAILED;
+ }
+
+ if (!lock_vol(cmd, argv[0], LCK_VG_WRITE | LCK_NONBLOCK)) {
+ log_error("Unable to lock volume group %s", argv[0]);
+ unlock_vg(cmd, ORPHAN);
+ return ECMD_FAILED;
+ }
+
if (!(arg_count(cmd, file_ARG) ?
backup_restore_from_file(cmd, argv[0],
arg_str_value(cmd, file_ARG, "")) :
backup_restore(cmd, argv[0]))) {
+ unlock_vg(cmd, argv[0]);
+ unlock_vg(cmd, ORPHAN);
log_err("Restore failed.");
return ECMD_FAILED;
}
+ unlock_vg(cmd, argv[0]);
+ unlock_vg(cmd, ORPHAN);
return 0;
}
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 3165ba88..9579bef3 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -20,11 +20,6 @@
#include "tools.h"
-static int vgchange_single(struct cmd_context *cmd, const char *vg_name);
-void vgchange_available(struct cmd_context *cmd, struct volume_group *vg);
-void vgchange_resizeable(struct cmd_context *cmd, struct volume_group *vg);
-void vgchange_logicalvolume(struct cmd_context *cmd, struct volume_group *vg);
-
static int _activate_lvs_in_vg(struct cmd_context *cmd,
struct volume_group *vg, int lock)
{
@@ -48,72 +43,6 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
return count;
}
-int vgchange(struct cmd_context *cmd, int argc, char **argv)
-{
- if (!
- (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
- arg_count(cmd, resizeable_ARG))) {
- log_error("One of -a, -l or -x options required");
- return EINVALID_CMD_LINE;
- }
-
- if (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
- arg_count(cmd, resizeable_ARG) > 1) {
- log_error("Only one of -a, -l or -x options allowed");
- return EINVALID_CMD_LINE;
- }
-
- if (arg_count(cmd, ignorelockingfailure_ARG) &&
- !arg_count(cmd, available_ARG)) {
- log_error("--ignorelockingfailure only available with -a");
- return EINVALID_CMD_LINE;
- }
-
- if (arg_count(cmd, available_ARG) == 1
- && arg_count(cmd, autobackup_ARG)) {
- log_error("-A option not necessary with -a option");
- return EINVALID_CMD_LINE;
- }
-
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- return process_each_vg(cmd, argc, argv,
- (arg_count(cmd, available_ARG)) ?
- LCK_VG_READ : LCK_VG_WRITE, &vgchange_single);
-}
-
-static int vgchange_single(struct cmd_context *cmd, const char *vg_name)
-{
- struct volume_group *vg;
-
- if (!(vg = vg_read(cmd, vg_name))) {
- log_error("Unable to find volume group \"%s\"", vg_name);
- return ECMD_FAILED;
- }
-
- if (!(vg->status & LVM_WRITE) && !arg_count(cmd, available_ARG)) {
- log_error("Volume group \"%s\" is read-only", vg->name);
- return ECMD_FAILED;
- }
-
- if (vg->status & EXPORTED_VG) {
- log_error("Volume group \"%s\" is exported", vg_name);
- return ECMD_FAILED;
- }
-
- if (arg_count(cmd, available_ARG))
- vgchange_available(cmd, vg);
-
- if (arg_count(cmd, resizeable_ARG))
- vgchange_resizeable(cmd, vg);
-
- if (arg_count(cmd, logicalvolume_ARG))
- vgchange_logicalvolume(cmd, vg);
-
- return 0;
-}
-
void vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
{
int lv_open, active;
@@ -208,3 +137,74 @@ void vgchange_logicalvolume(struct cmd_context *cmd, struct volume_group *vg)
return;
}
+
+static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
+{
+ if (!vg) {
+ log_error("Unable to find volume group \"%s\"", vg_name);
+ return ECMD_FAILED;
+ }
+
+ if (!consistent) {
+ unlock_vg(cmd, vg_name);
+ log_error("Volume group \"%s\" inconsistent", vg_name);
+ if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
+ return ECMD_FAILED;
+ }
+
+ if (!(vg->status & LVM_WRITE) && !arg_count(cmd, available_ARG)) {
+ log_error("Volume group \"%s\" is read-only", vg->name);
+ return ECMD_FAILED;
+ }
+
+ if (vg->status & EXPORTED_VG) {
+ log_error("Volume group \"%s\" is exported", vg_name);
+ return ECMD_FAILED;
+ }
+
+ if (arg_count(cmd, available_ARG))
+ vgchange_available(cmd, vg);
+
+ if (arg_count(cmd, resizeable_ARG))
+ vgchange_resizeable(cmd, vg);
+
+ if (arg_count(cmd, logicalvolume_ARG))
+ vgchange_logicalvolume(cmd, vg);
+
+ return 0;
+}
+
+int vgchange(struct cmd_context *cmd, int argc, char **argv)
+{
+ if (!
+ (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
+ arg_count(cmd, resizeable_ARG))) {
+ log_error("One of -a, -l or -x options required");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
+ arg_count(cmd, resizeable_ARG) > 1) {
+ log_error("Only one of -a, -l or -x options allowed");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, ignorelockingfailure_ARG) &&
+ !arg_count(cmd, available_ARG)) {
+ log_error("--ignorelockingfailure only available with -a");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, available_ARG) == 1
+ && arg_count(cmd, autobackup_ARG)) {
+ log_error("-A option not necessary with -a option");
+ return EINVALID_CMD_LINE;
+ }
+
+ return process_each_vg(cmd, argc, argv,
+ (arg_count(cmd, available_ARG)) ?
+ LCK_VG_READ : LCK_VG_WRITE, 0, NULL,
+ &vgchange_single);
+}
diff --git a/tools/vgck.c b/tools/vgck.c
index e90f5317..6a6eb1ec 100644
--- a/tools/vgck.c
+++ b/tools/vgck.c
@@ -20,20 +20,15 @@
#include "tools.h"
-static int vgck_single(struct cmd_context *cmd, const char *vg_name);
-
-int vgck(struct cmd_context *cmd, int argc, char **argv)
+static int vgck_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent, void *handle)
{
- return process_each_vg(cmd, argc, argv, LCK_VG_READ, &vgck_single);
-}
-
-static int vgck_single(struct cmd_context *cmd, const char *vg_name)
-{
- struct volume_group *vg;
-
- log_verbose("Checking volume group \"%s\"", vg_name);
+ if (!consistent) {
+ log_error("Volume group \"%s\" inconsistent", vg_name);
+ return ECMD_FAILED;
+ }
- if (!(vg = vg_read(cmd, vg_name))) {
+ if (!vg) {
log_error("Volume group \"%s\" not found", vg_name);
return ECMD_FAILED;
}
@@ -43,12 +38,12 @@ static int vgck_single(struct cmd_context *cmd, const char *vg_name)
return ECMD_FAILED;
}
-/******* FIXME Must be caught and logged by vg_read
- log_error("not all physical volumes of volume group \"%s\" online",
- log_error("volume group \"%s\" has physical volumes with ",
- "invalid version",
-********/
-
/* FIXME: free */
return 0;
}
+
+int vgck(struct cmd_context *cmd, int argc, char **argv)
+{
+ return process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
+ &vgck_single);
+}
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
new file mode 100644
index 00000000..91bd8886
--- /dev/null
+++ b/tools/vgconvert.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2001 Sistina Software
+ *
+ * pvcreate is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * pvcreate is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LVM; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "tools.h"
+#include "defaults.h"
+
+static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
+{
+ struct physical_volume *pv, *existing_pv;
+ uint64_t size = 0;
+ struct list mdas;
+ int pvmetadatacopies = 0;
+ uint64_t pvmetadatasize = 0;
+ uint64_t pe_end = 0, pe_start = 0;
+ struct list *pvh;
+
+ if (!vg) {
+ log_error("Unable to find volume group \"%s\"", vg_name);
+ return ECMD_FAILED;
+ }
+
+ if (!consistent) {
+ unlock_vg(cmd, vg_name);
+ log_error("Volume group \"%s\" inconsistent", vg_name);
+ if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
+ return ECMD_FAILED;
+ }
+
+ if (!(vg->status & LVM_WRITE)) {
+ log_error("Volume group \"%s\" is read-only", vg->name);
+ return ECMD_FAILED;
+ }
+
+ if (vg->status & EXPORTED_VG) {
+ log_error("Volume group \"%s\" is exported", vg_name);
+ return ECMD_FAILED;
+ }
+
+ if (vg->fid->fmt == cmd->fmt) {
+ log_error("Volume group \"%s\" already uses format %s",
+ vg_name, cmd->fmt->name);
+ return ECMD_FAILED;
+ }
+
+ if (cmd->fmt->features & FMT_MDAS) {
+ pvmetadatasize = arg_int64_value(cmd, metadatasize_ARG, 0) * 2;
+ if (!pvmetadatasize)
+ pvmetadatasize =
+ find_config_int(cmd->cf->root,
+ "metadata/pvmetadatasize",
+ '/', DEFAULT_PVMETADATASIZE);
+
+ pvmetadatacopies = arg_int_value(cmd, metadatacopies_ARG, -1);
+ if (pvmetadatacopies < 0)
+ pvmetadatacopies =
+ find_config_int(cmd->cf->root,
+ "metadata/pvmetadatacopies",
+ '/', DEFAULT_PVMETADATACOPIES);
+ }
+
+ if (!archive(vg)) {
+ log_error("Archive of \"%s\" metadata failed.", vg_name);
+ return ECMD_FAILED;
+ }
+
+ list_iterate(pvh, &vg->pvs) {
+ existing_pv = list_item(pvh, struct pv_list)->pv;
+
+ pe_start = existing_pv->pe_start;
+ pe_end = existing_pv->pe_count * existing_pv->pe_size
+ + pe_start - 1;
+
+ list_init(&mdas);
+ if (!(pv = pv_create(cmd->fmt, existing_pv->dev,
+ &existing_pv->id, size,
+ pe_start, existing_pv->pe_count,
+ existing_pv->pe_size, pvmetadatacopies,
+ pvmetadatasize, &mdas))) {
+ log_error("Failed to setup physical volume \"%s\"",
+ dev_name(existing_pv->dev));
+ log_error("Use pvcreate and vgcfgrestore to repair "
+ "from archived metadata.");
+ return ECMD_FAILED;
+ }
+
+ log_verbose("Set up physical volume for \"%s\" with %" PRIu64
+ " available sectors", dev_name(pv->dev), pv->size);
+
+ /* Wipe existing label first */
+ if (!label_remove(pv->dev)) {
+ log_error("Failed to wipe existing label on %s",
+ dev_name(pv->dev));
+ log_error("Use pvcreate and vgcfgrestore to repair "
+ "from archived metadata.");
+ return ECMD_FAILED;
+ }
+
+ log_very_verbose("Writing physical volume data to disk \"%s\"",
+ dev_name(pv->dev));
+ if (!(pv_write(cmd, pv, &mdas,
+ arg_int_value(cmd, labelsector_ARG,
+ DEFAULT_LABELSECTOR)))) {
+ log_error("Failed to write physical volume \"%s\"",
+ dev_name(pv->dev));
+ log_error("Use pvcreate and vgcfgrestore to repair "
+ "from archived metadata.");
+ return ECMD_FAILED;
+ }
+ log_verbose("Physical volume \"%s\" successfully created",
+ dev_name(pv->dev));
+
+ }
+
+ log_verbose("Deleting existing metadata for VG %s", vg_name);
+ if (!vg_remove(vg)) {
+ log_error("Removal of existing metadata for %s failed.",
+ vg_name);
+ log_error("Use pvcreate and vgcfgrestore to repair "
+ "from archived metadata.");
+ return ECMD_FAILED;
+ }
+
+ log_verbose("Writing metadata for VG %s using format %s", vg_name,
+ cmd->fmt->name);
+ if (!backup_restore_vg(cmd, vg)) {
+ log_error("Conversion failed for volume group %s.", vg_name);
+ log_error("Use pvcreate and vgcfgrestore to repair from "
+ "archived metadata.");
+ return ECMD_FAILED;
+ }
+ log_print("Volume group %s successfully converted", vg_name);
+
+ backup(vg);
+
+ return 0;
+}
+
+int vgconvert(struct cmd_context *cmd, int argc, char **argv)
+{
+ if (!argc) {
+ log_error("Please enter volume group(s)");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) {
+ log_error("labelsector must be less than %lu",
+ LABEL_SCAN_SECTORS);
+ return EINVALID_CMD_LINE;
+ }
+
+ if (!(cmd->fmt->features & FMT_MDAS) &&
+ (arg_count(cmd, metadatacopies_ARG) ||
+ arg_count(cmd, metadatasize_ARG))) {
+ log_error("Metadata parameters only apply to text format");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(cmd, metadatacopies_ARG) &&
+ arg_int_value(cmd, metadatacopies_ARG, -1) > 2) {
+ log_error("Metadatacopies may only be 0, 1 or 2");
+ return EINVALID_CMD_LINE;
+ }
+
+ return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 0, NULL,
+ &vgconvert_single);
+}
diff --git a/tools/vgcreate.c b/tools/vgcreate.c
index 7c092e0b..23a8389c 100644
--- a/tools/vgcreate.c
+++ b/tools/vgcreate.c
@@ -73,15 +73,12 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!is_valid_chars(vg_name)) {
+ if (!validate_vgname(vg_name)) {
log_error("New volume group name \"%s\" has invalid characters",
vg_name);
return ECMD_FAILED;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
/* Create the new VG */
if (!(vg = vg_create(cmd, vg_name, extent_size, max_pv, max_lv,
argc - 1, argv + 1)))
diff --git a/tools/vgdisplay.c b/tools/vgdisplay.c
index 13f30112..72bc3b38 100644
--- a/tools/vgdisplay.c
+++ b/tools/vgdisplay.c
@@ -20,7 +20,45 @@
#include "tools.h"
-static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name);
+static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
+{
+ /* FIXME Do the active check here if activevolumegroups_ARG ? */
+ if (!vg) {
+ log_error("Volume group \"%s\" doesn't exist", vg_name);
+ return ECMD_FAILED;
+ }
+
+ if (!consistent)
+ log_error("WARNING: Volume group \"%s\" inconsistent", vg_name);
+
+ if (vg->status & EXPORTED_VG)
+ log_print("WARNING: volume group \"%s\" is exported", vg_name);
+
+ if (arg_count(cmd, colon_ARG)) {
+ vgdisplay_colons(vg);
+ return 0;
+ }
+
+ if (arg_count(cmd, short_ARG)) {
+ vgdisplay_short(vg);
+ return 0;
+ }
+
+ vgdisplay_full(vg); /* was vg_show */
+
+ if (arg_count(cmd, verbose_ARG)) {
+ vgdisplay_extents(vg);
+
+ process_each_lv_in_vg(cmd, vg, NULL, &lvdisplay_full);
+
+ log_print("--- Physical volumes ---");
+ process_each_pv_in_vg(cmd, vg, NULL, &pvdisplay_short);
+ }
+
+ return 0;
+}
int vgdisplay(struct cmd_context *cmd, int argc, char **argv)
{
@@ -34,11 +72,6 @@ int vgdisplay(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- /* FIXME -D disk_ARG is now redundant */
-
/********* FIXME: Do without this - or else 2(+) passes!
Figure out longest volume group name
for (c = opt; opt < argc; opt++) {
@@ -48,7 +81,8 @@ int vgdisplay(struct cmd_context *cmd, int argc, char **argv)
}
**********/
- process_each_vg(cmd, argc, argv, LCK_VG_READ, &vgdisplay_single);
+ process_each_vg(cmd, argc, argv, LCK_VG_READ, 0, NULL,
+ &vgdisplay_single);
/******** FIXME Need to count number processed
Add this to process_each_vg if arg_count(cmd,activevolumegroups_ARG) ?
@@ -64,43 +98,3 @@ int vgdisplay(struct cmd_context *cmd, int argc, char **argv)
return 0;
}
-
-static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name)
-{
-
- struct volume_group *vg;
-
- /* FIXME Do the active check here if activevolumegroups_ARG ? */
-
- log_very_verbose("Finding volume group \"%s\"", vg_name);
- if (!(vg = vg_read(cmd, vg_name))) {
- log_error("Volume group \"%s\" doesn't exist", vg_name);
- return ECMD_FAILED;
- }
-
- if (vg->status & EXPORTED_VG)
- log_print("WARNING: volume group \"%s\" is exported", vg_name);
-
- if (arg_count(cmd, colon_ARG)) {
- vgdisplay_colons(vg);
- return 0;
- }
-
- if (arg_count(cmd, short_ARG)) {
- vgdisplay_short(vg);
- return 0;
- }
-
- vgdisplay_full(vg); /* was vg_show */
-
- if (arg_count(cmd, verbose_ARG)) {
- vgdisplay_extents(vg);
-
- process_each_lv_in_vg(cmd, vg, &lvdisplay_full);
-
- log_print("--- Physical volumes ---");
- process_each_pv_in_vg(cmd, vg, &pvdisplay_short);
- }
-
- return 0;
-}
diff --git a/tools/vgexport.c b/tools/vgexport.c
index 50fe605f..5e521f01 100644
--- a/tools/vgexport.c
+++ b/tools/vgexport.c
@@ -20,32 +20,17 @@
#include "tools.h"
-static int vgexport_single(struct cmd_context *cmd, const char *vg_name);
-
-int vgexport(struct cmd_context *cmd, int argc, char **argv)
+static int vgexport_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
{
- if (!argc && !arg_count(cmd, all_ARG)) {
- log_error("Please supply volume groups or use -a for all.");
- return ECMD_FAILED;
- }
-
- if (argc && arg_count(cmd, all_ARG)) {
- log_error("No arguments permitted when using -a for all.");
- return ECMD_FAILED;
+ if (!vg) {
+ log_error("Unable to find volume group \"%s\"", vg_name);
+ goto error;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- return process_each_vg(cmd, argc, argv, LCK_VG_READ, &vgexport_single);
-}
-
-static int vgexport_single(struct cmd_context *cmd, const char *vg_name)
-{
- struct volume_group *vg;
-
- if (!(vg = vg_read(cmd, vg_name))) {
- log_error("Unable to find volume group \"%s\"", vg_name);
+ if (!consistent) {
+ log_error("Volume group %s inconsistent", vg_name);
goto error;
}
@@ -82,3 +67,19 @@ static int vgexport_single(struct cmd_context *cmd, const char *vg_name)
error:
return ECMD_FAILED;
}
+
+int vgexport(struct cmd_context *cmd, int argc, char **argv)
+{
+ if (!argc && !arg_count(cmd, all_ARG)) {
+ log_error("Please supply volume groups or use -a for all.");
+ return ECMD_FAILED;
+ }
+
+ if (argc && arg_count(cmd, all_ARG)) {
+ log_error("No arguments permitted when using -a for all.");
+ return ECMD_FAILED;
+ }
+
+ return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 1, NULL,
+ &vgexport_single);
+}
diff --git a/tools/vgextend.c b/tools/vgextend.c
index 6b5adb9a..0cb9f073 100644
--- a/tools/vgextend.c
+++ b/tools/vgextend.c
@@ -24,6 +24,7 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
{
char *vg_name;
struct volume_group *vg = NULL;
+ int consistent = 1;
if (!argc) {
log_error("Please enter volume group name and "
@@ -36,9 +37,6 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
vg_name = argv[0];
argc--;
argv++;
@@ -55,7 +53,7 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
goto error;
}
- if (!(vg = vg_read(cmd, vg_name))) {
+ if (!(vg = vg_read(cmd, vg_name, &consistent)) || !consistent) {
log_error("Volume group \"%s\" not found.", vg_name);
goto error;
}
diff --git a/tools/vgimport.c b/tools/vgimport.c
index bb72d7a7..d515caad 100644
--- a/tools/vgimport.c
+++ b/tools/vgimport.c
@@ -20,31 +20,11 @@
#include "tools.h"
-static int vgimport_single(struct cmd_context *cmd, const char *vg_name);
-
-int vgimport(struct cmd_context *cmd, int argc, char **argv)
-{
- if (!argc && !arg_count(cmd, all_ARG)) {
- log_error("Please supply volume groups or use -a for all.");
- return ECMD_FAILED;
- }
-
- if (argc && arg_count(cmd, all_ARG)) {
- log_error("No arguments permitted when using -a for all.");
- return ECMD_FAILED;
- }
-
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, &vgimport_single);
-}
-
-static int vgimport_single(struct cmd_context *cmd, const char *vg_name)
+static int vgimport_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
{
- struct volume_group *vg;
-
- if (!(vg = vg_read(cmd, vg_name))) {
+ if (!vg || !consistent) {
log_error("Unable to find exported volume group \"%s\"",
vg_name);
goto error;
@@ -77,3 +57,19 @@ static int vgimport_single(struct cmd_context *cmd, const char *vg_name)
error:
return ECMD_FAILED;
}
+
+int vgimport(struct cmd_context *cmd, int argc, char **argv)
+{
+ if (!argc && !arg_count(cmd, all_ARG)) {
+ log_error("Please supply volume groups or use -a for all.");
+ return ECMD_FAILED;
+ }
+
+ if (argc && arg_count(cmd, all_ARG)) {
+ log_error("No arguments permitted when using -a for all.");
+ return ECMD_FAILED;
+ }
+
+ return process_each_vg(cmd, argc, argv, LCK_VG_WRITE, 1, NULL,
+ &vgimport_single);
+}
diff --git a/tools/vgmerge.c b/tools/vgmerge.c
index 8d6e7b44..6a705658 100644
--- a/tools/vgmerge.c
+++ b/tools/vgmerge.c
@@ -21,41 +21,12 @@
#include "tools.h"
int vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
- const char *vg_name_from);
-
-int vgmerge(struct cmd_context *cmd, int argc, char **argv)
-{
- char *vg_name_to;
- int opt = 0;
- int ret = 0, ret_max = 0;
-
- if (argc < 2) {
- log_error("Please enter 2 or more volume groups to merge");
- return EINVALID_CMD_LINE;
- }
-
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- vg_name_to = argv[0];
- argc--;
- argv++;
-
- for (; opt < argc; opt++) {
- ret = vgmerge_single(cmd, vg_name_to, argv[opt]);
- if (ret > ret_max)
- ret_max = ret;
- }
-
- return ret_max;
-}
-
-int vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
const char *vg_name_from)
{
struct volume_group *vg_to, *vg_from;
struct list *lvh1, *lvh2;
int active;
+ int consistent = 1;
if (!strcmp(vg_name_to, vg_name_from)) {
log_error("Duplicate volume group name \"%s\"", vg_name_from);
@@ -68,7 +39,7 @@ int vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
return ECMD_FAILED;
}
- if (!(vg_to = vg_read(cmd, vg_name_to))) {
+ if (!(vg_to = vg_read(cmd, vg_name_to, &consistent)) || !consistent) {
log_error("Volume group \"%s\" doesn't exist", vg_name_to);
unlock_vg(cmd, vg_name_to);
return ECMD_FAILED;
@@ -93,7 +64,8 @@ int vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
return ECMD_FAILED;
}
- if (!(vg_from = vg_read(cmd, vg_name_from))) {
+ consistent = 1;
+ if (!(vg_from = vg_read(cmd, vg_name_from, &consistent)) || !consistent) {
log_error("Volume group \"%s\" doesn't exist", vg_name_from);
goto error;
}
@@ -178,6 +150,14 @@ int vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
list_del(lvh);
list_add(&vg_to->lvs, lvh);
}
+
+ while (!list_empty(&vg_from->fid->metadata_areas)) {
+ struct list *mdah = vg_from->fid->metadata_areas.n;
+
+ list_del(mdah);
+ list_add(&vg_to->fid->metadata_areas, mdah);
+ }
+
vg_to->lv_count += vg_from->lv_count;
vg_to->extent_count += vg_from->extent_count;
@@ -205,3 +185,27 @@ int vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
unlock_vg(cmd, vg_name_to);
return ECMD_FAILED;
}
+
+int vgmerge(struct cmd_context *cmd, int argc, char **argv)
+{
+ char *vg_name_to;
+ int opt = 0;
+ int ret = 0, ret_max = 0;
+
+ if (argc < 2) {
+ log_error("Please enter 2 or more volume groups to merge");
+ return EINVALID_CMD_LINE;
+ }
+
+ vg_name_to = argv[0];
+ argc--;
+ argv++;
+
+ for (; opt < argc; opt++) {
+ ret = vgmerge_single(cmd, vg_name_to, argv[opt]);
+ if (ret > ret_max)
+ ret_max = ret;
+ }
+
+ return ret_max;
+}
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index b2bd476b..a0855731 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -20,14 +20,64 @@
#include "tools.h"
+/* Or take pv_name instead? */
static int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
- struct physical_volume *pv);
+ struct physical_volume *pv, void *handle)
+{
+ struct pv_list *pvl;
+ const char *name = dev_name(pv->dev);
+
+ if (pv->pe_alloc_count) {
+ log_error("Physical volume \"%s\" still in use", name);
+ return ECMD_FAILED;
+ }
+
+ if (vg->pv_count == 1) {
+ log_error("Can't remove final physical volume \"%s\" from "
+ "volume group \"%s\"", name, vg->name);
+ return ECMD_FAILED;
+ }
+
+ pvl = find_pv_in_vg(vg, name);
+
+ if (!archive(vg))
+ return ECMD_FAILED;
+ log_verbose("Removing \"%s\" from volume group \"%s\"", name, vg->name);
+
+ if (pvl)
+ list_del(&pvl->list);
+
+ *pv->vg_name = '\0';
+ vg->pv_count--;
+ vg->free_count -= pv->pe_count - pv->pe_alloc_count;
+ vg->extent_count -= pv->pe_count;
+
+ if (!vg_write(vg)) {
+ log_error("Removal of physical volume \"%s\" from "
+ "\"%s\" failed", name, vg->name);
+ return ECMD_FAILED;
+ }
+
+ if (!pv_write(cmd, pv, NULL, -1)) {
+ log_error("Failed to clear metadata from physical "
+ "volume \"%s\" "
+ "after removal from \"%s\"", name, vg->name);
+ return ECMD_FAILED;
+ }
+
+ backup(vg);
+
+ log_print("Removed \"%s\" from volume group \"%s\"", name, vg->name);
+
+ return 0;
+}
int vgreduce(struct cmd_context *cmd, int argc, char **argv)
{
struct volume_group *vg;
char *vg_name;
int ret;
+ int consistent = 1;
if (!argc) {
log_error("Please give volume group name and "
@@ -46,9 +96,6 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
vg_name = argv[0];
argv++;
argc--;
@@ -59,7 +106,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!(vg = vg_read(cmd, vg_name))) {
+ if (!(vg = vg_read(cmd, vg_name, &consistent)) || !consistent) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
@@ -85,7 +132,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
/* FIXME: Pass private structure through to all these functions */
/* and update in batch here? */
- ret = process_each_pv(cmd, argc, argv, vg, vgreduce_single);
+ ret = process_each_pv(cmd, argc, argv, vg, NULL, vgreduce_single);
unlock_vg(cmd, vg_name);
@@ -107,62 +154,3 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
********/
}
-
-/* Or take pv_name instead? */
-static int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
- struct physical_volume *pv)
-{
- struct pv_list *pvl;
- const char *name = dev_name(pv->dev);
-
- if (pv->pe_alloc_count) {
- log_error("Physical volume \"%s\" still in use", name);
- return ECMD_FAILED;
- }
-
-/********* FIXME: Is this unnecessary after checking pe_alloc_count?
- if (pv->lv_cur > 0) {
- log_error ("can't reduce volume group \"%s\" by used physical volume \"%s\"", vg_name, error_pv_name);
- }
-*********/
-
- if (vg->pv_count == 1) {
- log_error("Can't remove final physical volume \"%s\" from "
- "volume group \"%s\"", name, vg->name);
- return ECMD_FAILED;
- }
-
- pvl = find_pv_in_vg(vg, name);
-
- if (!archive(vg))
- return ECMD_FAILED;
-
- log_verbose("Removing \"%s\" from volume group \"%s\"", name, vg->name);
-
- if (pvl)
- list_del(&pvl->list);
-
- *pv->vg_name = '\0';
- vg->pv_count--;
- vg->free_count -= pv->pe_count - pv->pe_alloc_count;
- vg->extent_count -= pv->pe_count;
-
- if (!vg_write(vg)) {
- log_error("Removal of physical volume \"%s\" from "
- "\"%s\" failed", name, vg->name);
- return ECMD_FAILED;
- }
-
- if (!pv_write(cmd, pv)) {
- log_error("Failed to clear metadata from physical "
- "volume \"%s\" "
- "after removal from \"%s\"", name, vg->name);
- return ECMD_FAILED;
- }
-
- backup(vg);
-
- log_print("Removed \"%s\" from volume group \"%s\"", name, vg->name);
-
- return 0;
-}
diff --git a/tools/vgremove.c b/tools/vgremove.c
index 018976f7..14a0fcf3 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -20,38 +20,15 @@
#include "tools.h"
-static int vgremove_single(struct cmd_context *cmd, const char *vg_name);
-
-int vgremove(struct cmd_context *cmd, int argc, char **argv)
-{
- int ret;
-
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
- if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
- log_error("Can't get lock for orphan PVs");
- return ECMD_FAILED;
- }
-
- ret = process_each_vg(cmd, argc, argv,
- LCK_VG | LCK_WRITE | LCK_NONBLOCK,
- &vgremove_single);
-
- unlock_vg(cmd, "");
-
- return ret;
-}
-
-static int vgremove_single(struct cmd_context *cmd, const char *vg_name)
+static int vgremove_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent,
+ void *handle)
{
- struct volume_group *vg;
struct physical_volume *pv;
struct list *pvh;
int ret = 0;
- log_verbose("Checking for volume group \"%s\"", vg_name);
- if (!(vg = vg_read(cmd, vg_name))) {
+ if (!vg || !consistent) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
return ECMD_FAILED;
}
@@ -87,7 +64,8 @@ static int vgremove_single(struct cmd_context *cmd, const char *vg_name)
log_verbose("Removing physical volume \"%s\" from "
"volume group \"%s\"", dev_name(pv->dev), vg_name);
*pv->vg_name = '\0';
- if (!pv_write(cmd, pv)) {
+ /* FIXME Write to same sector label was read from */
+ if (!pv_write(cmd, pv, NULL, -1)) {
log_error("Failed to remove physical volume \"%s\""
" from volume group \"%s\"",
dev_name(pv->dev), vg_name);
@@ -104,3 +82,21 @@ static int vgremove_single(struct cmd_context *cmd, const char *vg_name)
return ret;
}
+
+int vgremove(struct cmd_context *cmd, int argc, char **argv)
+{
+ int ret;
+
+ if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
+ log_error("Can't get lock for orphan PVs");
+ return ECMD_FAILED;
+ }
+
+ ret = process_each_vg(cmd, argc, argv,
+ LCK_VG | LCK_WRITE | LCK_NONBLOCK, 1, NULL,
+ &vgremove_single);
+
+ unlock_vg(cmd, "");
+
+ return ret;
+}
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 4ec3d985..50c04512 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -24,6 +24,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
{
char *dev_dir;
int length;
+ int consistent = 1;
char *vg_name_old, *vg_name_new;
@@ -56,7 +57,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!is_valid_chars(vg_name_new)) {
+ if (!validate_vgname(vg_name_new)) {
log_error("New volume group name \"%s\" has invalid characters",
vg_name_new);
return ECMD_FAILED;
@@ -67,9 +68,6 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
log_verbose("Checking for existing volume group \"%s\"", vg_name_old);
if (!lock_vol(cmd, vg_name_old, LCK_VG_WRITE)) {
@@ -77,7 +75,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!(vg_old = vg_read(cmd, vg_name_old))) {
+ if (!(vg_old = vg_read(cmd, vg_name_old, &consistent)) || !consistent) {
log_error("Volume group \"%s\" doesn't exist", vg_name_old);
unlock_vg(cmd, vg_name_old);
return ECMD_FAILED;
@@ -115,7 +113,8 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if ((vg_new = vg_read(cmd, vg_name_new))) {
+ consistent = 0;
+ if ((vg_new = vg_read(cmd, vg_name_new, &consistent))) {
log_error("New volume group \"%s\" already exists",
vg_name_new);
goto error;
@@ -133,18 +132,14 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
vg_name_new);
}
-/********** FIXME: Check within vg_write now
- log_error("A new logical volume path exceeds "
- "maximum of %d!", NAME_LEN - 2);
- goto error;
-*************/
-
sprintf(old_path, "%s%s", dev_dir, vg_name_old);
sprintf(new_path, "%s%s", dev_dir, vg_name_new);
if (dir_exists(old_path)) {
log_verbose("Renaming \"%s\" to \"%s\"", old_path, new_path);
- if (rename(old_path, new_path)) {
+ if (test_mode())
+ log_verbose("Test mode: Skipping rename.");
+ else if (rename(old_path, new_path)) {
log_error("Renaming \"%s\" to \"%s\" failed: %s",
old_path, new_path, strerror(errno));
goto error;
@@ -175,19 +170,3 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
-/* FIXME: Moved into vg_write now */
-/*******************
-char *lv_change_vgname(char *vg_name, char *lv_name)
-{
- char *lv_name_ptr = NULL;
- static char lv_name_buf[NAME_LEN] = { 0, };
-
- ** check if lv_name includes a path
- if ((lv_name_ptr = strrchr(lv_name, '/'))) {
- lv_name_ptr++;
- sprintf(lv_name_buf, "%s%s/%s%c", cmd->dev_dir, vg_name,
- lv_name_ptr, 0);}
- else
- strncpy(lv_name_buf, lv_name, NAME_LEN - 1); return lv_name_buf;}
-
-**********************/
diff --git a/tools/vgscan.c b/tools/vgscan.c
index 504f5347..0af067d7 100644
--- a/tools/vgscan.c
+++ b/tools/vgscan.c
@@ -20,7 +20,28 @@
#include "tools.h"
-static int vgscan_single(struct cmd_context *cmd, const char *vg_name);
+static int vgscan_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, int consistent, void *handle)
+{
+ if (!vg) {
+ log_error("Volume group \"%s\" not found", vg_name);
+ return ECMD_FAILED;
+ }
+
+ if (!consistent) {
+ unlock_vg(cmd, vg_name);
+ log_error("Volume group \"%s\" inconsistent", vg_name);
+ /* Don't allow partial switch to this program */
+ if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
+ return ECMD_FAILED;
+ }
+
+ log_print("Found %svolume group \"%s\" using metadata type %s",
+ (vg->status & EXPORTED_VG) ? "exported " : "", vg_name,
+ vg->fid->fmt->name);
+
+ return 0;
+}
int vgscan(struct cmd_context *cmd, int argc, char **argv)
{
@@ -32,28 +53,11 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
log_verbose("Wiping cache of LVM-capable devices");
persistent_filter_wipe(cmd->filter);
- log_verbose("Wiping internal cache of PVs in VGs");
- vgcache_destroy();
+ log_verbose("Wiping internal cache");
+ cache_destroy();
log_print("Reading all physical volumes. This may take a while...");
- return process_each_vg(cmd, argc, argv, LCK_VG_READ, &vgscan_single);
-}
-
-static int vgscan_single(struct cmd_context *cmd, const char *vg_name)
-{
- struct volume_group *vg;
-
- log_verbose("Checking for volume group \"%s\"", vg_name);
-
- if (!(vg = vg_read(cmd, vg_name))) {
- log_error("Volume group \"%s\" not found", vg_name);
- return ECMD_FAILED;
- }
-
- log_print("Found %svolume group \"%s\" using metadata type %s",
- (vg->status & EXPORTED_VG) ? "exported " : "", vg_name,
- vg->fid->fmt->name);
-
- return 0;
+ return process_each_vg(cmd, argc, argv, LCK_VG_READ, 1, NULL,
+ &vgscan_single);
}
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index baa7d2e5..00a77ff1 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -65,7 +65,7 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
{
struct list *lvh, *lvht, *segh;
struct logical_volume *lv;
- struct stripe_segment *seg;
+ struct lv_segment *seg;
struct physical_volume *pv;
struct volume_group *vg_with;
int s;
@@ -77,7 +77,7 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
/* VG as each other */
vg_with = NULL;
list_iterate(segh, &lv->segments) {
- seg = list_item(segh, struct stripe_segment);
+ seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
if (vg_with) {
@@ -164,6 +164,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
struct volume_group *vg_to, *vg_from;
int opt;
int active;
+ int consistent = 1;
if (argc < 3) {
log_error("Existing VG, new VG and physical volumes required.");
@@ -180,16 +181,13 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!driver_is_loaded())
- return ECMD_FAILED;
-
log_verbose("Checking for volume group \"%s\"", vg_name_from);
if (!lock_vol(cmd, vg_name_from, LCK_VG_WRITE)) {
log_error("Can't get lock for %s", vg_name_from);
return ECMD_FAILED;
}
- if (!(vg_from = vg_read(cmd, vg_name_from))) {
+ if (!(vg_from = vg_read(cmd, vg_name_from, &consistent)) || !consistent) {
log_error("Volume group \"%s\" doesn't exist", vg_name_from);
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
@@ -214,7 +212,8 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if ((vg_to = vg_read(cmd, vg_name_to))) {
+ consistent = 0;
+ if ((vg_to = vg_read(cmd, vg_name_to, &consistent))) {
/* FIXME Remove this restriction */
log_error("Volume group \"%s\" already exists", vg_name_to);
goto error;
@@ -250,6 +249,12 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
if (!(_move_snapshots(vg_from, vg_to)))
goto error;
+ /* FIXME Split mdas properly somehow too! */
+ /* Currently we cheat by sharing the format instance and relying on
+ * vg_write to ignore mdas outside the VG! Done this way, with text
+ * format, vg_from disappears for a short time. */
+ vg_to->fid = vg_from->fid;
+
/* store it on disks */
log_verbose("Writing out updated volume groups");
@@ -271,6 +276,13 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
backup(vg_from);
/* Remove EXPORTED flag from new VG */
+ consistent = 1;
+ if (!(vg_to = vg_read(cmd, vg_name_to, &consistent)) || !consistent) {
+ log_error("Volume group \"%s\" became inconsistent: please "
+ "fix manually", vg_name_to);
+ goto error;
+ }
+
vg_to->status &= ~EXPORTED_VG;
if (!vg_write(vg_to))