summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Makefile.in2
-rw-r--r--lib/locking/file_locking.c193
-rw-r--r--lib/locking/locking.c154
-rw-r--r--lib/locking/locking.h4
-rw-r--r--lib/misc/lvm-file.c54
-rw-r--r--lib/misc/lvm-file.h11
-rw-r--r--tools/lvcreate.c50
-rw-r--r--tools/lvm.c11
-rw-r--r--tools/lvrename.c32
-rw-r--r--tools/lvresize.c53
-rw-r--r--tools/pvchange.c16
-rw-r--r--tools/toollib.c63
-rw-r--r--tools/toollib.h6
-rw-r--r--tools/tools.h2
-rw-r--r--tools/vgcfgbackup.c2
-rw-r--r--tools/vgchange.c5
-rw-r--r--tools/vgck.c2
-rw-r--r--tools/vgcreate.c29
-rw-r--r--tools/vgdisplay.c2
-rw-r--r--tools/vgexport.c17
-rw-r--r--tools/vgextend.c33
-rw-r--r--tools/vgimport.c15
-rw-r--r--tools/vgmerge.c42
-rw-r--r--tools/vgreduce.c16
-rw-r--r--tools/vgremove.c14
-rw-r--r--tools/vgrename.c49
-rw-r--r--tools/vgscan.c3
27 files changed, 732 insertions, 148 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 5b9480b6..58d4803b 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -38,6 +38,8 @@ SOURCES=\
format_text/import.c \
label/label.c \
label/uuid-map.c \
+ locking/locking.c \
+ locking/file_locking.c \
log/log.c \
metadata/lv_manip.c \
metadata/merge.c \
diff --git a/lib/locking/file_locking.c b/lib/locking/file_locking.c
new file mode 100644
index 00000000..1cc157a2
--- /dev/null
+++ b/lib/locking/file_locking.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the LGPL.
+ *
+ */
+
+#include "log.h"
+#include "locking.h"
+#include "locking_types.h"
+#include "activate.h"
+#include "config.h"
+#include "defaults.h"
+#include "lvm-file.h"
+#include "lvm-string.h"
+#include "dbg_malloc.h"
+
+#include <limits.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <signal.h>
+
+struct lock_list {
+ struct list list;
+ int lf;
+ char *res;
+};
+
+static struct list _lock_list;
+static char _lock_dir[NAME_LEN];
+
+static int _release_lock(const char *file)
+{
+ struct lock_list *ll;
+ struct list *llh, *llt;
+
+ list_iterate_safe(llh, llt, &_lock_list) {
+ ll = list_item(llh, struct lock_list);
+
+ if (!file || !strcmp(ll->res, file)) {
+ list_del(llh);
+ log_very_verbose("Unlocking %s", ll->res);
+
+ /*
+ * If this is the last pid using the file, remove it
+ */
+ if (!flock(ll->lf, LOCK_NB | LOCK_EX))
+ if (unlink(ll->res))
+ log_sys_error("unlink", ll->res);
+
+ if (close(ll->lf) < 0)
+ log_sys_error("close", ll->res);
+
+ dbg_free(ll->res);
+ dbg_free(llh);
+
+ if (file)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void fin_file_locking(void)
+{
+ _release_lock(NULL);
+}
+
+void _trap_ctrl_c(int signal)
+{
+ log_error("CTRL-c detected: giving up waiting for lock");
+ return;
+}
+
+static void _install_ctrl_c_handler()
+{
+ siginterrupt(SIGINT, 1);
+ signal(SIGINT, _trap_ctrl_c);
+}
+
+static void _remove_ctrl_c_handler()
+{
+ signal(SIGINT, SIG_IGN);
+ siginterrupt(SIGINT, 0);
+}
+
+static int _lock_file(const char *file, int flags)
+{
+ int operation;
+ int r = 1;
+
+ struct lock_list *ll;
+
+ switch (flags & LCK_TYPE_MASK) {
+ case LCK_READ:
+ operation = LOCK_SH;
+ break;
+ case LCK_WRITE:
+ operation = LOCK_EX;
+ break;
+ case LCK_NONE:
+ return _release_lock(file);
+ default:
+ log_error("Unrecognised lock type: %d", flags & LCK_TYPE_MASK);
+ return 0;
+ }
+
+ if (!(ll = dbg_malloc(sizeof(struct lock_list))))
+ return 0;
+
+ if (!(ll->res = dbg_strdup(file))) {
+ dbg_free(ll);
+ return 0;
+ }
+
+ log_very_verbose("Locking %s", ll->res);
+ if ((ll->lf = open(file, O_CREAT | O_APPEND | O_RDWR, 0777)) < 0) {
+ log_sys_error("open", file);
+ dbg_free(ll->res);
+ dbg_free(ll);
+ return 0;
+ }
+
+ if ((flags & LCK_NONBLOCK))
+ operation |= LOCK_NB;
+ else
+ _install_ctrl_c_handler();
+
+ if (flock(ll->lf, operation)) {
+ log_sys_error("flock", ll->res);
+ dbg_free(ll->res);
+ dbg_free(ll);
+ r = 0;
+ } else
+ list_add(&_lock_list, &ll->list);
+
+
+ if (!(flags & LCK_NONBLOCK))
+ _remove_ctrl_c_handler();
+
+ return r;
+}
+
+int lock_resource(const char *resource, int flags)
+{
+ char lockfile[PATH_MAX];
+
+ switch (flags & LCK_SCOPE_MASK) {
+ case LCK_VG:
+ if (!resource || !*resource)
+ lvm_snprintf(lockfile, sizeof(lockfile),
+ "%s/P_orphans", _lock_dir);
+ else
+ lvm_snprintf(lockfile, sizeof(lockfile),
+ "%s/V_%s", _lock_dir, resource);
+ break;
+ case LCK_LV:
+ /* No-op for now */
+ return 1;
+ default:
+ log_error("Unrecognised lock scope: %d",
+ flags & LCK_SCOPE_MASK);
+ return 0;
+ }
+
+ if (!_lock_file(lockfile, flags))
+ return 0;
+
+ return 1;
+}
+
+
+int init_file_locking(struct locking_type *locking, struct config_file *cf)
+{
+ locking->lock_resource = lock_resource;
+ locking->fin_locking = fin_file_locking;
+
+ /* Get lockfile directory from config file */
+ strncpy(_lock_dir, find_config_str(cf->root, "global/locking_dir",
+ '/', DEFAULT_LOCK_DIR),
+ sizeof(_lock_dir));
+
+ if (!create_dir(_lock_dir))
+ return 0;
+
+ list_init(&_lock_list);
+
+ return 1;
+}
diff --git a/lib/locking/locking.c b/lib/locking/locking.c
new file mode 100644
index 00000000..c4e94624
--- /dev/null
+++ b/lib/locking/locking.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the LGPL.
+ *
+ */
+
+#include "log.h"
+#include "locking.h"
+#include "locking_types.h"
+#include "lvm-string.h"
+#include "activate.h"
+
+#include <signal.h>
+
+static struct locking_type _locking;
+
+static int _lock_count = 0; /* Number of locks held */
+static int _signals_ignored = 0;
+
+static void _ignore_signals(void)
+{
+ int s;
+
+ if (_signals_ignored)
+ return;
+
+ for (s = 0; s < NSIG; s++)
+ signal(s, SIG_IGN);
+
+ _signals_ignored = 1;
+
+ return;
+}
+
+static void _enable_signals(void)
+{
+ int s;
+
+ /* Don't enable signals while any locks are held */
+ if (!_signals_ignored || _lock_count)
+ return;
+
+ for (s = 0; s < NSIG; s++)
+ signal(s, SIG_DFL);
+
+ _signals_ignored = 0;
+
+ return;
+}
+
+static inline void _update_lock_count(int flags)
+{
+ if ((flags & LCK_TYPE_MASK) == LCK_NONE)
+ _lock_count--;
+ else
+ _lock_count++;
+}
+
+/*
+ * No locking - currently does nothing.
+ */
+int no_lock_resource(const char *resource, int flags)
+{
+ return 1;
+}
+
+void no_fin_locking(void)
+{
+ return;
+}
+
+static void _init_no_locking(struct locking_type *locking,
+ struct config_file *cf)
+{
+ locking->lock_resource = no_lock_resource;
+ locking->fin_locking = no_fin_locking;
+}
+
+/*
+ * Select a locking type
+ */
+int init_locking(int type, struct config_file *cf)
+{
+ switch (type) {
+ case 0:
+ _init_no_locking(&_locking, cf);
+ log_print("WARNING: Locking disabled. Be carefui! "
+ "This could corrupt your metadata.");
+ break;
+ case 1:
+ if (!init_file_locking(&_locking, cf))
+ return 0;
+ log_very_verbose("File-based locking enabled.");
+ break;
+/******
+ case 2:
+ if (!init_other_locking(&_locking, cf))
+ return 0;
+ log_very_verbose("Other locking enabled.");
+ break;
+******/
+ default:
+ log_error("Unknown locking type requested.");
+ return 0;
+ }
+
+ return 1;
+}
+
+void fin_locking(void)
+{
+ _locking.fin_locking();
+}
+
+/*
+ * VG locking is by name
+ * LV locking is by struct logical_volume
+ * FIXME This should take a unique name or id for an LV
+ */
+int lock_vol(const void *vol, int flags)
+{
+ char resource[258];
+
+ switch (flags & LCK_SCOPE_MASK) {
+ case LCK_VG:
+ /*
+ * Lock a volume group before changing on-disk metadata.
+ */
+ strncpy(resource, (char *) vol, sizeof(resource));
+ break;
+ case LCK_LV:
+ /*
+ * Suspends LV if it's active.
+ */
+ default:
+ log_error("Unrecognised lock scope: %d",
+ flags & LCK_SCOPE_MASK);
+ return 0;
+ }
+
+ _ignore_signals();
+
+ if (!(_locking.lock_resource(resource, flags))) {
+ _enable_signals();
+ return 0;
+ }
+
+ _update_lock_count(flags);
+ _enable_signals();
+
+ return 1;
+}
+
diff --git a/lib/locking/locking.h b/lib/locking/locking.h
index 37d0c149..ed981585 100644
--- a/lib/locking/locking.h
+++ b/lib/locking/locking.h
@@ -24,9 +24,9 @@ void fin_locking(void);
* struct logical_volume *vol
*
* FIXME: Change to
- * int lock_vol(struct id *id, int flags);
+ * int lock_vol(const struct id *id, int flags);
*/
-int lock_vol(void *vol, int flags);
+int lock_vol(const void *vol, int flags);
/*
* Lock type
diff --git a/lib/misc/lvm-file.c b/lib/misc/lvm-file.c
index 10d6d05e..f0ae9aad 100644
--- a/lib/misc/lvm-file.c
+++ b/lib/misc/lvm-file.c
@@ -99,3 +99,57 @@ int lvm_rename(const char *old, const char *new)
return 1;
}
+
+int path_exists(const char *path)
+{
+ struct stat info;
+
+ if (!*path)
+ return 0;
+
+ if (stat(path, &info) < 0)
+ return 0;
+
+ return 1;
+}
+
+int dir_exists(const char *path)
+{
+ struct stat info;
+
+ if (!*path)
+ return 0;
+
+ if (stat(path, &info) < 0)
+ return 0;
+
+ if (!S_ISDIR(info.st_mode))
+ return 0;
+
+ return 1;
+}
+
+
+/* FIXME: Make this create directories recursively */
+int create_dir(const char *dir)
+{
+ struct stat info;
+
+ if (!*dir)
+ return 1;
+
+ if (stat(dir, &info) < 0) {
+ log_verbose("Creating directory \"%s\"", dir);
+ if (!mkdir(dir, 0777))
+ return 1;
+ log_sys_error("mkdir", dir);
+ return 0;
+ }
+
+ if (S_ISDIR(info.st_mode))
+ return 1;
+
+ log_error("Directory \"%s\" not found", dir);
+ return 0;
+}
+
diff --git a/lib/misc/lvm-file.h b/lib/misc/lvm-file.h
index 1f65a1a6..3c3e9072 100644
--- a/lib/misc/lvm-file.h
+++ b/lib/misc/lvm-file.h
@@ -16,3 +16,14 @@ int create_temp_name(const char *dir, char *buffer, size_t len, int *fd);
*/
int lvm_rename(const char *old, const char *new);
+/*
+ * Return 1 if path exists else return 0
+ */
+int path_exists(const char *path);
+int dir_exists(const char *path);
+
+/*
+ * Create directory (but not recursively) if necessary
+ * Return 1 if directory exists on return, else 0
+ */
+int create_dir(const char *dir);
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 979130fb..14608d48 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -118,25 +118,31 @@ int lvcreate(int argc, char **argv)
/* does VG exist? */
log_verbose("Finding volume group \"%s\"", vg_name);
+
+ if (!lock_vol(vg_name, LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for %s", vg_name);
+ return ECMD_FAILED;
+ }
+
if (!(vg = fid->ops->vg_read(fid, vg_name))) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (lv_name && find_lv_in_vg(vg, lv_name)) {
log_error("Logical volume \"%s\" already exists in "
"volume group \"%s\"", lv_name, vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (!argc)
@@ -147,27 +153,27 @@ int lvcreate(int argc, char **argv)
if (!(pvh = create_pv_list(fid->cmd->mem, vg,
argc - opt, argv + opt))) {
stack;
- return ECMD_FAILED;
+ goto error;
}
}
if (argc && argc < stripes ) {
log_error("Too few physical volumes on "
"command line for %d-way striping", stripes);
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
}
if (stripes < 1 || stripes > MAX_STRIPES) {
log_error("Number of stripes (%d) must be between %d and %d",
stripes, 1, MAX_STRIPES);
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
}
if (stripes > 1 && (stripesize < STRIPE_SIZE_MIN ||
stripesize > STRIPE_SIZE_MAX ||
stripesize & (stripesize - 1))) {
log_error("Invalid stripe size %d", stripesize);
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
}
if (stripesize > vg->extent_size) {
@@ -201,12 +207,12 @@ int lvcreate(int argc, char **argv)
}
if (!archive(vg))
- return ECMD_FAILED;
+ goto error;
if (!(lv = lv_create(fid, lv_name, status,
stripes, stripesize, extents,
vg, pvh)))
- return ECMD_FAILED;
+ goto error;
if (arg_count(readahead_ARG)) {
log_verbose("Setting read ahead sectors");
@@ -226,21 +232,21 @@ int lvcreate(int argc, char **argv)
if (!arg_count(minor_ARG)) {
log_error("Please specify minor number with "
"--minor when using -My");
- return ECMD_FAILED;
+ goto error;
}
lv->status |= FIXED_MINOR;
}
/* store vg on disk(s) */
if (!fid->ops->vg_write(fid, vg))
- return ECMD_FAILED;
+ goto error;
backup(vg);
log_print("Logical volume \"%s\" created", lv->name);
if (!lv_activate(lv))
- return ECMD_FAILED;
+ goto error;
if (zero) {
struct device *dev;
@@ -248,29 +254,39 @@ int lvcreate(int argc, char **argv)
if (!(name = pool_alloc(fid->cmd->mem, PATH_MAX))) {
log_error("Name allocation failed - device not zeroed");
- return ECMD_FAILED;
+ goto error;
}
if (lvm_snprintf(name, PATH_MAX, "%s%s/%s", fid->cmd->dev_dir,
lv->vg->name, lv->name) < 0) {
log_error("Name too long - device not zeroed (%s)",
lv->name);
- return ECMD_FAILED;
+ goto error;
}
log_verbose("Zeroing start of logical volume \"%s\"", name);
if (!(dev = dev_cache_get(name, NULL))) {
log_error("\"%s\" not found: device not zeroed", name);
- return ECMD_FAILED;
+ goto error;
}
if (!(dev_open(dev, O_WRONLY)))
- return ECMD_FAILED;
+ goto error;
dev_zero(dev, 0, 4096);
dev_close(dev);
} else
log_print("WARNING: \"%s\" not zeroed", lv->name);
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+
return 0;
+
+ error:
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ return ECMD_FAILED;
+
+ error_cmdline:
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ return EINVALID_CMD_LINE;
}
diff --git a/tools/lvm.c b/tools/lvm.c
index c2f6f70f..a77db806 100644
--- a/tools/lvm.c
+++ b/tools/lvm.c
@@ -720,6 +720,7 @@ static char *_copy_command_line(struct pool *mem, int argc, char **argv)
static int run_command(int argc, char **argv)
{
int ret = 0;
+ int locking_type;
if (!(cmd->cmd_line = _copy_command_line(cmd->mem, argc, argv)))
return ECMD_FAILED;
@@ -739,8 +740,18 @@ static int run_command(int argc, char **argv)
_use_settings(&_current_settings);
+ 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 = the_command->fn(argc, argv);
+ fin_locking();
+
/*
* set the debug and verbose levels back
* to the global default. We have to do
diff --git a/tools/lvrename.c b/tools/lvrename.c
index 37a22f49..ed56ee1e 100644
--- a/tools/lvrename.c
+++ b/tools/lvrename.c
@@ -85,57 +85,63 @@ int lvrename(int argc, char **argv)
}
log_verbose("Checking for existing volume group \"%s\"", vg_name);
+
+ if (!lock_vol(vg_name, LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for %s", vg_name);
+ return ECMD_FAILED;
+ }
+
if (!(vg = fid->ops->vg_read(fid, vg_name))) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg->name);
- return ECMD_FAILED;
+ goto error;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (find_lv_in_vg(vg, lv_name_new)) {
log_error("Logical volume \"%s\" already exists in "
"volume group \"%s\"", lv_name_new, vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (!(lvl = find_lv_in_vg(vg, lv_name_old))) {
log_error("Existing logical volume \"%s\" not found in "
"volume group \"%s\"", lv_name_old, vg_name);
- return ECMD_FAILED;
+ goto error;
}
lv = lvl->lv;
if (!archive(lv->vg))
- return ECMD_FAILED;
+ goto error;
if ((active = lv_active(lv)) < 0) {
log_error("Unable to determine status of \"%s\"", lv->name);
- return ECMD_FAILED;
+ goto error;
}
if (active && !lv_suspend(lv)) {
log_error("Failed to suspend \"%s\"", lv->name);
- return ECMD_FAILED;
+ goto error;
}
if (!(lv->name = pool_strdup(fid->cmd->mem, lv_name_new))) {
log_error("Failed to allocate space for new name");
- return ECMD_FAILED;
+ goto error;
}
/* store it on disks */
log_verbose("Writing out updated volume group");
if (!(fid->ops->vg_write(fid, vg))) {
- return ECMD_FAILED;
+ goto error;
}
if (active) {
@@ -145,8 +151,14 @@ int lvrename(int argc, char **argv)
backup(lv->vg);
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+
log_print("Renamed \"%s\" to \"%s\" in volume group \"%s\"",
lv_name_old, lv_name_new, vg_name);
return 0;
+
+ error:
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ return ECMD_FAILED;
}
diff --git a/tools/lvresize.c b/tools/lvresize.c
index 17aa1659..16439251 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -105,26 +105,31 @@ int lvresize(int argc, char **argv)
/* does VG exist? */
log_verbose("Finding volume group %s", vg_name);
+ if (!lock_vol(vg_name, LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for %s", vg_name);
+ return ECMD_FAILED;
+ }
+
if (!(vg = fid->ops->vg_read(fid, vg_name))) {
log_error("Volume group %s doesn't exist", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group %s is exported", vg->name);
- return ECMD_FAILED;
+ goto error;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group %s is read-only", vg_name);
- return ECMD_FAILED;
+ goto error;
}
/* does LV exist? */
if (!(lvl = find_lv_in_vg(vg, lv_name))) {
log_error("Logical volume %s not found in volume group %s",
lv_name, vg_name);
- return ECMD_FAILED;
+ goto error;
}
lv = lvl->lv;
@@ -157,7 +162,7 @@ int lvresize(int argc, char **argv)
if (extents >= lv->le_count) {
log_error("Unable to reduce %s below 1 extent",
lv_name);
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
}
extents = lv->le_count - extents;
@@ -165,13 +170,13 @@ int lvresize(int argc, char **argv)
if (!extents) {
log_error("New size of 0 not permitted");
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
}
if (extents == lv->le_count) {
log_error("New size (%d extents) matches existing size "
"(%d extents)", extents, lv->le_count);
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
}
/* If extending, find stripes, stripesize & size of last segment */
@@ -190,7 +195,7 @@ int lvresize(int argc, char **argv)
(seg_stripes && seg_stripes != str && !stripes)) {
log_error("Please specify number of "
"stripes (-i) and stripesize (-I)");
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
}
seg_stripesize = sz;
@@ -245,7 +250,7 @@ int lvresize(int argc, char **argv)
if (extents == lv->le_count) {
log_error("New size (%d extents) matches existing size "
"(%d extents)", extents, lv->le_count);
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
}
if (extents < lv->le_count) {
@@ -253,7 +258,7 @@ int lvresize(int argc, char **argv)
log_error("New size given (%d extents) not larger "
"than existing size (%d extents)",
extents, lv->le_count);
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
} else
resize = LV_REDUCE;
}
@@ -263,7 +268,7 @@ int lvresize(int argc, char **argv)
log_error("New size given (%d extents) not less than "
"existing size (%d extents)", extents,
lv->le_count);
- return EINVALID_CMD_LINE;
+ goto error_cmdline;
} else
resize = LV_EXTEND;
}
@@ -290,27 +295,27 @@ int lvresize(int argc, char **argv)
" [y/n]: ", lv_name) == 'n') {
log_print("Logical volume %s NOT reduced",
lv_name);
- return ECMD_FAILED;
+ goto error;
}
}
if (!archive(vg))
- return ECMD_FAILED;
+ goto error;
if (!lv_reduce(fid, lv, lv->le_count - extents))
- return ECMD_FAILED;
+ goto error;
}
if ((resize == LV_EXTEND && argc) &&
!(pvh = create_pv_list(fid->cmd->mem, vg,
argc - opt, argv + opt))) {
stack;
- return ECMD_FAILED;
+ goto error;
}
if (resize == LV_EXTEND) {
if (!archive(vg))
- return ECMD_FAILED;
+ goto error;
if (!argc) {
/* Use full list from VG */
@@ -322,7 +327,7 @@ int lvresize(int argc, char **argv)
if (!lv_extend(fid, lv, stripes, stripesize,
extents - lv->le_count, pvh))
- return ECMD_FAILED;
+ goto error;
}
@@ -332,16 +337,26 @@ int lvresize(int argc, char **argv)
/* store vg on disk(s) */
if (!fid->ops->vg_write(fid, vg))
- return ECMD_FAILED;
+ goto error;
backup(vg);
if (active && !lv_reactivate(lv))
- return ECMD_FAILED;
+ goto error;
/********* FIXME Resume *********/
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+
log_print("Logical volume %s successfully resized", lv_name);
return 0;
+
+ error:
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ return ECMD_FAILED;
+
+ error_cmdline:
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ return EINVALID_CMD_LINE;
}
diff --git a/tools/pvchange.c b/tools/pvchange.c
index d6d3ac09..371cddbb 100644
--- a/tools/pvchange.c
+++ b/tools/pvchange.c
@@ -94,23 +94,33 @@ int pvchange_single(struct physical_volume *pv)
if (*pv->vg_name) {
log_verbose("Finding volume group of physical volume \"%s\"",
pv_name);
+
+ if (!lock_vol(pv->vg_name, LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for %s", pv->vg_name);
+ return ECMD_FAILED;
+ }
+
if (!(vg = fid->ops->vg_read(fid, pv->vg_name))) {
+ lock_vol(pv->vg_name, LCK_VG | LCK_NONE);
log_error("Unable to find volume group of \"%s\"",
pv_name);
return 0;
}
if (vg->status & EXPORTED_VG) {
+ lock_vol(pv->vg_name, LCK_VG | LCK_NONE);
log_error("Volume group \"%s\" is exported", vg->name);
return ECMD_FAILED;
}
if (!(vg->status & LVM_WRITE)) {
+ lock_vol(pv->vg_name, LCK_VG | LCK_NONE);
log_error("Volume group \"%s\" is read-only", vg->name);
return ECMD_FAILED;
}
if (!(pvl = find_pv_in_vg(vg, pv_name))) {
+ lock_vol(pv->vg_name, LCK_VG | LCK_NONE);
log_error("Unable to find \"%s\" in volume group \"%s\"",
pv_name, vg->name);
return 0;
@@ -123,12 +133,16 @@ int pvchange_single(struct physical_volume *pv)
/* change allocatability for a PV */
if (allocatable && (pv->status & ALLOCATABLE_PV)) {
log_error("Physical volume \"%s\" is already allocatable", pv_name);
+ if (*pv->vg_name)
+ lock_vol(pv->vg_name, LCK_VG | LCK_NONE);
return 0;
}
if (!allocatable && !(pv->status & ALLOCATABLE_PV)) {
log_error("Physical volume \"%s\" is already unallocatable",
pv_name);
+ if (*pv->vg_name)
+ lock_vol(pv->vg_name, LCK_VG | LCK_NONE);
return 0;
}
@@ -144,11 +158,13 @@ int pvchange_single(struct physical_volume *pv)
log_verbose("Updating physical volume \"%s\"", pv_name);
if (*pv->vg_name) {
if (!(fid->ops->vg_write(fid,vg))) {
+ lock_vol(pv->vg_name, LCK_VG | LCK_NONE);
log_error("Failed to store physical volume \"%s\" in "
"volume group \"%s\"", pv_name, vg->name);
return 0;
}
backup(vg);
+ lock_vol(pv->vg_name, LCK_VG | LCK_NONE);
} else {
if (!(fid->ops->pv_write(fid, pv))) {
log_error("Failed to store physical volume \"%s\"",
diff --git a/tools/toollib.c b/tools/toollib.c
index 95dbff74..4a466a00 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -8,43 +8,6 @@
#include <sys/stat.h>
-int dir_exists(const char *dir)
-{
- struct stat info;
-
- if (!*dir)
- return 1;
-
- if (stat(dir, &info) != -1) {
- log_error("\"%s\" exists", dir);
- return 0;
- }
-
- return 1;
-}
-
-int create_dir(const char *dir)
-{
- struct stat info;
-
- if (!*dir)
- return 1;
-
- if (stat(dir, &info) < 0) {
- log_verbose("Creating directory \"%s\"", dir);
- if (!mkdir(dir, 0777))
- return 1;
- log_sys_error("mkdir", dir);
- return 0;
- }
-
- if (S_ISDIR(info.st_mode))
- return 1;
-
- log_error("Directory \"%s\" not found", dir);
- return 0;
-}
-
int process_each_lv_in_vg(struct volume_group *vg,
int (*process_single) (struct logical_volume *lv))
{
@@ -151,7 +114,7 @@ int process_each_lv(int argc, char **argv,
return ret_max;
}
-int process_each_vg(int argc, char **argv,
+int process_each_vg(int argc, char **argv, int lock_type,
int (*process_single) (const char *vg_name))
{
int opt = 0;
@@ -161,11 +124,20 @@ int process_each_vg(int argc, char **argv,
struct list *vgh;
struct list *vgs;
+ char *vg_name;
+
if (argc) {
log_verbose("Using volume group(s) on command line");
- for (; opt < argc; opt++)
- if ((ret = process_single(argv[opt])) > ret_max)
+ for (; opt < argc; opt++) {
+ vg_name = argv[opt];
+ if (!lock_vol((void *)vg_name, LCK_VG | lock_type)) {
+ log_error("Can't lock %s: skipping", vg_name);
+ continue;
+ }
+ if ((ret = process_single(vg_name)) > ret_max)
ret_max = ret;
+ lock_vol((void *)vg_name, LCK_VG | LCK_NONE);
+ }
} else {
log_verbose("Finding all volume groups");
if (!(vgs = fid->ops->get_vgs(fid))) {
@@ -173,11 +145,16 @@ int process_each_vg(int argc, char **argv,
return ECMD_FAILED;
}
list_iterate(vgh, vgs) {
- ret =
- process_single(list_item
- (vgh, struct name_list)->name);
+ vg_name = list_item (vgh, struct name_list)->name;
+ if (!lock_vol((void *)vg_name, LCK_VG | lock_type)) {
+ log_error("Can't lock %s: skipping", vg_name);
+ continue;
+ }
+ ret = process_single(vg_name);
+
if (ret > ret_max)
ret_max = ret;
+ lock_vol((void *)vg_name, LCK_VG | LCK_NONE);
}
}
diff --git a/tools/toollib.h b/tools/toollib.h
index 98ca5e30..d43a0b9d 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -26,9 +26,7 @@ int autobackup_init(const char *backup_dir, int keep_days, int keep_number,
int autobackup);
int autobackup(struct volume_group *vg);
-int create_dir(const char *dir);
-
-int process_each_vg(int argc, char **argv,
+int process_each_vg(int argc, char **argv, int lock_type,
int (*process_single) (const char *vg_name));
int process_each_pv(int argc, char **argv, struct volume_group *vg,
@@ -45,8 +43,6 @@ int process_each_lv_in_vg(struct volume_group *vg,
int (*process_single) (struct logical_volume * lv));
int is_valid_chars(char *n);
-int dir_exists(const char *dir);
-
char *default_vgname(struct format_instance *fi);
char *extract_vgname(struct format_instance *fi, char *lv_name);
diff --git a/tools/tools.h b/tools/tools.h
index bebee43f..512b7fea 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -25,6 +25,7 @@
#include "list.h"
#include "log.h"
#include "lvm-string.h"
+#include "lvm-file.h"
#include "metadata.h"
#include "config.h"
#include "dev-cache.h"
@@ -41,6 +42,7 @@
#include "toollib.h"
#include "activate.h"
#include "archive.h"
+#include "locking.h"
#include <stdio.h>
#include <stdarg.h>
diff --git a/tools/vgcfgbackup.c b/tools/vgcfgbackup.c
index 17e37883..dbfcb63e 100644
--- a/tools/vgcfgbackup.c
+++ b/tools/vgcfgbackup.c
@@ -54,6 +54,6 @@ static int vg_backup_single(const char *vg_name)
int vgcfgbackup(int argc, char **argv)
{
- return process_each_vg(argc, argv, &vg_backup_single);
+ return process_each_vg(argc, argv, LCK_READ, &vg_backup_single);
}
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 711f5bcd..aac06152 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -44,7 +44,10 @@ int vgchange(int argc, char **argv)
return EINVALID_CMD_LINE;
}
- return process_each_vg(argc, argv, &vgchange_single);
+ return process_each_vg(argc, argv,
+ (arg_count(available_ARG)) ?
+ LCK_READ : LCK_WRITE,
+ &vgchange_single);
}
static int vgchange_single(const char *vg_name)
diff --git a/tools/vgck.c b/tools/vgck.c
index 26d0aeab..9d9343a5 100644
--- a/tools/vgck.c
+++ b/tools/vgck.c
@@ -24,7 +24,7 @@ static int vgck_single(const char *vg_name);
int vgck(int argc, char **argv)
{
- return process_each_vg(argc, argv, &vgck_single);
+ return process_each_vg(argc, argv, LCK_READ, &vgck_single);
}
static int vgck_single(const char *vg_name)
diff --git a/tools/vgcreate.c b/tools/vgcreate.c
index 622cfb2d..1fdc12be 100644
--- a/tools/vgcreate.c
+++ b/tools/vgcreate.c
@@ -67,7 +67,10 @@ int vgcreate(int argc, char **argv)
vg_name += strlen(fid->cmd->dev_dir);
snprintf(vg_path, PATH_MAX, "%s%s", fid->cmd->dev_dir, vg_name);
- if (!dir_exists(vg_path)) return ECMD_FAILED;
+ if (path_exists(vg_path)) {
+ log_error("%s: already exists in filesystem", vg_path);
+ return ECMD_FAILED;
+ }
if (!is_valid_chars(vg_name)) {
log_error("New volume group name \"%s\" has invalid characters",
@@ -88,12 +91,32 @@ int vgcreate(int argc, char **argv)
log_error("Warning: Setting maxphysicalvolumes to %d",
vg->max_pv);
- if (!archive(vg))
+ if (!lock_vol("", LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for orphan PVs");
+ return ECMD_FAILED;
+ }
+
+ if (!lock_vol(vg_name, LCK_VG | LCK_WRITE | LCK_NONBLOCK)) {
+ log_error("Can't get lock for %s", vg_name);
+ lock_vol("", LCK_VG | LCK_NONE);
+ return ECMD_FAILED;
+ }
+
+ if (!archive(vg)) {
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ lock_vol("", LCK_VG | LCK_NONE);
return ECMD_FAILED;
+ }
/* Store VG on disk(s) */
- if (!fid->ops->vg_write(fid, vg))
+ if (!fid->ops->vg_write(fid, vg)) {
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ lock_vol("", LCK_VG | LCK_NONE);
return ECMD_FAILED;
+ }
+
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ lock_vol("", LCK_VG | LCK_NONE);
backup(vg);
diff --git a/tools/vgdisplay.c b/tools/vgdisplay.c
index 57e4e54c..c096d40c 100644
--- a/tools/vgdisplay.c
+++ b/tools/vgdisplay.c
@@ -45,7 +45,7 @@ int vgdisplay(int argc, char **argv)
}
**********/
- process_each_vg(argc, argv, &vgdisplay_single);
+ process_each_vg(argc, argv, LCK_READ, &vgdisplay_single);
/******** FIXME Need to count number processed
Add this to process_each_vg if arg_count(activevolumegroups_ARG) ?
diff --git a/tools/vgexport.c b/tools/vgexport.c
index e74db3c8..05fdb781 100644
--- a/tools/vgexport.c
+++ b/tools/vgexport.c
@@ -34,7 +34,7 @@ int vgexport(int argc, char **argv)
return ECMD_FAILED;
}
- return process_each_vg(argc, argv, &vgexport_single);
+ return process_each_vg(argc, argv, LCK_READ, &vgexport_single);
}
static int vgexport_single(const char *vg_name)
@@ -43,36 +43,39 @@ static int vgexport_single(const char *vg_name)
if (!(vg = fid->ops->vg_read(fid, vg_name))) {
log_error("Unable to find volume group \"%s\"", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is already exported", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (lvs_in_vg_activated(vg)) {
log_error("Volume group \"%s\" has active logical volumes",
vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (!archive(vg))
- return ECMD_FAILED;
+ goto error;
vg->status |= EXPORTED_VG;
if (!fid->ops->vg_write(fid,vg))
- return ECMD_FAILED;
+ goto error;
backup(vg);
log_print("Volume group \"%s\" successfully exported", vg->name);
return 0;
+
+ error:
+ return ECMD_FAILED;
}
diff --git a/tools/vgextend.c b/tools/vgextend.c
index 6c51c27b..b51533bd 100644
--- a/tools/vgextend.c
+++ b/tools/vgextend.c
@@ -40,25 +40,36 @@ int vgextend(int argc, char **argv)
argc--;
argv++;
+ if (!lock_vol("", LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for orphan PVs");
+ return ECMD_FAILED;
+ }
+
log_verbose("Checking for volume group \"%s\"", vg_name);
+ if (!lock_vol(vg_name, LCK_VG | LCK_WRITE | LCK_NONBLOCK)) {
+ lock_vol("", LCK_VG | LCK_NONE);
+ log_error("Can't get lock for %s", vg_name);
+ goto error;
+ }
+
if (!(vg = fid->ops->vg_read(fid, vg_name))) {
log_error("Volume group \"%s\" not found.", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg->name);
- return ECMD_FAILED;
+ goto error;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (!(vg->status & RESIZEABLE_VG)) {
log_error("Volume group \"%s\" is not resizeable.", vg_name);
- return ECMD_FAILED;
+ goto error;
}
/********** FIXME
@@ -69,11 +80,11 @@ int vgextend(int argc, char **argv)
**********/
if (!archive(vg))
- return ECMD_FAILED;
+ goto error;
/* extend vg */
if (!vg_extend(fid, vg, argc, argv))
- return ECMD_FAILED;
+ goto error;
/* ret > 0 */
log_verbose("Volume group \"%s\" will be extended by %d new "
@@ -81,11 +92,19 @@ int vgextend(int argc, char **argv)
/* store vg on disk(s) */
if (!fid->ops->vg_write(fid, vg))
- return ECMD_FAILED;
+ goto error;
backup(vg);
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ lock_vol("", LCK_VG | LCK_NONE);
+
log_print("Volume group \"%s\" successfully extended", vg_name);
return 0;
+
+ error:
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+ lock_vol("", LCK_VG | LCK_NONE);
+ return ECMD_FAILED;
}
diff --git a/tools/vgimport.c b/tools/vgimport.c
index 9163eda7..e30ab252 100644
--- a/tools/vgimport.c
+++ b/tools/vgimport.c
@@ -34,7 +34,7 @@ int vgimport(int argc, char **argv)
return ECMD_FAILED;
}
- return process_each_vg(argc, argv, &vgimport_single);
+ return process_each_vg(argc, argv, LCK_WRITE, &vgimport_single);
}
static int vgimport_single(const char *vg_name)
@@ -44,30 +44,33 @@ static int vgimport_single(const char *vg_name)
if (!(vg = fid->ops->vg_read(fid, vg_name))) {
log_error("Unable to find exported volume group \"%s\"",
vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (!(vg->status & EXPORTED_VG)) {
log_error("Volume group \"%s\" is not exported", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (vg->status & PARTIAL_VG) {
log_error("Volume group \"%s\" is partially missing", vg_name);
- return ECMD_FAILED;
+ goto error;
}
if (!archive(vg))
- return ECMD_FAILED;
+ goto error;
vg->status &= ~EXPORTED_VG;
if (!fid->ops->vg_write(fid,vg))
- return ECMD_FAILED;
+ goto error;
backup(vg);
log_print("Volume group \"%s\" successfully imported", vg->name);
return 0;
+
+ error:
+ return ECMD_FAILED;
}
diff --git a/tools/vgmerge.c b/tools/vgmerge.c
index eefa4f87..9c134f0e 100644
--- a/tools/vgmerge.c
+++ b/tools/vgmerge.c
@@ -58,41 +58,55 @@ int vgmerge_single(const char *vg_name_to, const char *vg_name_from)
}
log_verbose("Checking for volume group \"%s\"", vg_name_to);
+ if (!lock_vol(vg_name_to, LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for %s", vg_name_to);
+ return ECMD_FAILED;
+ }
+
if (!(vg_to = fid->ops->vg_read(fid, vg_name_to))) {
log_error("Volume group \"%s\" doesn't exist", vg_name_to);
+ lock_vol(vg_name_to, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
if (vg_to->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg_to->name);
+ lock_vol(vg_name_to, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
if (!(vg_to->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_to->name);
+ lock_vol(vg_name_to, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
log_verbose("Checking for volume group \"%s\"", vg_name_from);
+ if (!lock_vol(vg_name_from, LCK_VG | LCK_WRITE | LCK_NONBLOCK)) {
+ log_error("Can't get lock for %s", vg_name_from);
+ lock_vol(vg_name_to, LCK_VG | LCK_NONE);
+ return ECMD_FAILED;
+ }
+
if (!(vg_from = fid->ops->vg_read(fid, vg_name_from))) {
log_error("Volume group \"%s\" doesn't exist", vg_name_from);
- return ECMD_FAILED;
+ goto error;
}
if (vg_from->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg_from->name);
- return ECMD_FAILED;
+ goto error;
}
if (!(vg_from->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_from->name);
- return ECMD_FAILED;
+ goto error;
}
if ((active = lvs_in_vg_activated(vg_from))) {
log_error("Logical volumes in \"%s\" must be inactive",
vg_name_from);
- return ECMD_FAILED;
+ goto error;
}
/* Check compatibility */
@@ -100,21 +114,21 @@ int vgmerge_single(const char *vg_name_to, const char *vg_name_from)
log_error("Extent sizes differ: %d (%s) and %d (%s)",
vg_to->extent_size, vg_to->name,
vg_from->extent_size, vg_from->name);
- return ECMD_FAILED;
+ goto error;
}
if (vg_to->max_pv < vg_to->pv_count + vg_from->pv_count) {
log_error("Maximum number of physical volumes (%d) exceeded "
" for \"%s\" and \"%s\"", vg_to->max_pv, vg_to->name,
vg_from->name);
- return ECMD_FAILED;
+ goto error;
}
if (vg_to->max_lv < vg_to->lv_count + vg_from->lv_count) {
log_error("Maximum number of logical volumes (%d) exceeded "
" for \"%s\" and \"%s\"", vg_to->max_lv, vg_to->name,
vg_from->name);
- return ECMD_FAILED;
+ goto error;
}
/* Check no conflicts with LV names */
@@ -131,7 +145,7 @@ int vgmerge_single(const char *vg_name_to, const char *vg_name_from)
"in \"%s\" and \"%s\"",
name1, vg_to->name,
vg_from->name);
- return ECMD_FAILED;
+ goto error;
}
}
}
@@ -139,7 +153,7 @@ int vgmerge_single(const char *vg_name_to, const char *vg_name_from)
/* FIXME List arg: vg_show_with_pv_and_lv(vg_to); */
if (!archive(vg_from) || !archive(vg_to))
- return ECMD_FAILED;
+ goto error;
/* Merge volume groups */
while (!list_empty(&vg_from->pvs)) {
@@ -168,14 +182,22 @@ int vgmerge_single(const char *vg_name_to, const char *vg_name_from)
/* store it on disks */
log_verbose("Writing out updated volume group");
if (!(fid->ops->vg_write(fid, vg_to))) {
- return ECMD_FAILED;
+ goto error;
}
/* FIXME Remove /dev/vgfrom */
backup(vg_to);
+ lock_vol(vg_name_from, LCK_VG | LCK_NONE);
+ lock_vol(vg_name_to, LCK_VG | LCK_NONE);
+
log_print("Volume group \"%s\" successfully merged into \"%s\"",
vg_from->name, vg_to->name);
return 0;
+
+ error:
+ lock_vol(vg_name_from, LCK_VG | LCK_NONE);
+ lock_vol(vg_name_to, LCK_VG | LCK_NONE);
+ return ECMD_FAILED;
}
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index 71153fef..98b31348 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -26,6 +26,7 @@ int vgreduce(int argc, char **argv)
{
struct volume_group *vg;
char *vg_name;
+ int ret;
if (!argc) {
log_error("Please give volume group name and "
@@ -49,29 +50,42 @@ int vgreduce(int argc, char **argv)
argc--;
log_verbose("Finding volume group \"%s\"", vg_name);
+ if (!lock_vol(vg_name, LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for %s", vg_name);
+ return ECMD_FAILED;
+ }
+
if (!(vg = fid->ops->vg_read(fid, vg_name))) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg->name);
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_name);
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
if (!(vg->status & RESIZEABLE_VG)) {
log_error("Volume group \"%s\" is not reducable", vg_name);
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
/* FIXME: Pass private structure through to all these functions */
/* and update in batch here? */
- return process_each_pv(argc, argv, vg, vgreduce_single);
+ ret = process_each_pv(argc, argv, vg, vgreduce_single);
+
+ lock_vol(vg_name, LCK_VG | LCK_NONE);
+
+ return ret;
/******* FIXME
log_error ("no empty physical volumes found in volume group \"%s\"", vg_name);
diff --git a/tools/vgremove.c b/tools/vgremove.c
index cd5d0400..2d29a4d9 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -24,7 +24,19 @@ static int vgremove_single(const char *vg_name);
int vgremove(int argc, char **argv)
{
- return process_each_vg(argc, argv, &vgremove_single);
+ int ret;
+
+ if (!lock_vol("", LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for orphan PVs");
+ return ECMD_FAILED;
+ }
+
+ ret = process_each_vg(argc, argv, LCK_WRITE | LCK_NONBLOCK,
+ &vgremove_single);
+
+ lock_vol("", LCK_VG | LCK_NONE);
+
+ return ret;
}
static int vgremove_single(const char *vg_name)
diff --git a/tools/vgrename.c b/tools/vgrename.c
index d3a74cd7..81b84670 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -68,17 +68,26 @@ int vgrename(int argc, char **argv)
}
log_verbose("Checking for existing volume group \"%s\"", vg_name_old);
+
+ if (!lock_vol(vg_name_old, LCK_VG | LCK_WRITE)) {
+ log_error("Can't get lock for %s", vg_name_old);
+ return ECMD_FAILED;
+ }
+
if (!(vg_old = fid->ops->vg_read(fid, vg_name_old))) {
log_error("Volume group \"%s\" doesn't exist", vg_name_old);
+ lock_vol(vg_name_old, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
if (vg_old->status & EXPORTED_VG) {
+ lock_vol(vg_name_old, LCK_VG | LCK_NONE);
log_error("Volume group \"%s\" is exported", vg_old->name);
return ECMD_FAILED;
}
if (!(vg_old->status & LVM_WRITE)) {
+ lock_vol(vg_name_old, LCK_VG | LCK_NONE);
log_error("Volume group \"%s\" is read-only", vg_old->name);
return ECMD_FAILED;
}
@@ -89,20 +98,28 @@ int vgrename(int argc, char **argv)
/***** FIXME Handle this with multiple LV renames!
if (!force_ARG) {
log_error("Use -f to force the rename");
+ lock_vol(vg_name_old, LCK_VG | LCK_NONE);
return ECMD_FAILED;
}
*****/
}
log_verbose("Checking for new volume group \"%s\"", vg_name_new);
+
+ if (!lock_vol(vg_name_new, LCK_VG | LCK_WRITE | LCK_NONBLOCK)) {
+ lock_vol(vg_name_old, LCK_VG | LCK_NONE);
+ log_error("Can't get lock for %s", vg_name_new);
+ return ECMD_FAILED;
+ }
+
if ((vg_new = fid->ops->vg_read(fid, vg_name_new))) {
log_error("New volume group \"%s\" already exists",
vg_name_new);
- return ECMD_FAILED;
+ goto error;
}
if (!archive(vg_old))
- return ECMD_FAILED;
+ goto error;
/* Change the volume group name */
strcpy(vg_old->name, vg_name_new);
@@ -116,35 +133,43 @@ int vgrename(int argc, char **argv)
/********** FIXME: Check within vg_write now
log_error("A new logical volume path exceeds "
"maximum of %d!", NAME_LEN - 2);
- return ECMD_FAILED;
+ goto error;
*************/
sprintf(old_path, "%s%s", dev_dir, vg_name_old);
sprintf(new_path, "%s%s", dev_dir, vg_name_new);
- log_verbose("Renaming \"%s\" to \"%s\"", old_path, new_path);
- if (rename(old_path, new_path)) {
- log_error("Renaming \"%s\" to \"%s\" failed: %s",
- old_path, new_path, strerror(errno));
- return ECMD_FAILED;
+ if (dir_exists(old_path)) {
+ log_verbose("Renaming \"%s\" to \"%s\"", old_path, new_path);
+ if (rename(old_path, new_path)) {
+ log_error("Renaming \"%s\" to \"%s\" failed: %s",
+ old_path, new_path, strerror(errno));
+ goto error;
+ }
}
/* store it on disks */
log_verbose("Writing out updated volume group");
if (!(fid->ops->vg_write(fid, vg_old))) {
- return ECMD_FAILED;
+ goto error;
}
-/******* FIXME Any LV things to update? */
+/******* FIXME Rename any active LVs! *****/
backup(vg_old);
+ lock_vol(vg_name_new, LCK_VG | LCK_NONE);
+ lock_vol(vg_name_old, LCK_VG | LCK_NONE);
+
log_print("Volume group \"%s\" successfully renamed to \"%s\"",
vg_name_old, vg_name_new);
- /* FIXME: Deallocations */
-
return 0;
+
+ error:
+ lock_vol(vg_name_new, LCK_VG | LCK_NONE);
+ lock_vol(vg_name_old, LCK_VG | LCK_NONE);
+ return ECMD_FAILED;
}
/* FIXME: Moved into vg_write now */
diff --git a/tools/vgscan.c b/tools/vgscan.c
index d5f541d8..bdb43978 100644
--- a/tools/vgscan.c
+++ b/tools/vgscan.c
@@ -37,7 +37,7 @@ int vgscan(int argc, char **argv)
log_print("Reading all physical volumes. This may take a while...");
- return process_each_vg(argc, argv, &vgscan_single);
+ return process_each_vg(argc, argv, LCK_READ, &vgscan_single);
}
static int vgscan_single(const char *vg_name)
@@ -45,6 +45,7 @@ static int vgscan_single(const char *vg_name)
struct volume_group *vg;
log_verbose("Checking for volume group \"%s\"", vg_name);
+
if (!(vg = fid->ops->vg_read(fid, vg_name))) {
log_error("Volume group \"%s\" not found", vg_name);
return ECMD_FAILED;