From 7d0e6e800e41fd13a5dc51ef05de8298b30b7432 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Mon, 11 Feb 2002 15:42:34 +0000 Subject: [PATCH] o Support locking with local lock files o Disable control-c during updates (except if blocked waiting for a lock) --- lib/Makefile.in | 2 + lib/locking/file_locking.c | 193 +++++++++++++++++++++++++++++++++++++ lib/locking/locking.c | 154 +++++++++++++++++++++++++++++ lib/locking/locking.h | 4 +- lib/misc/lvm-file.c | 54 +++++++++++ lib/misc/lvm-file.h | 11 +++ tools/lvcreate.c | 50 ++++++---- tools/lvm.c | 11 +++ tools/lvrename.c | 32 ++++-- tools/lvresize.c | 53 ++++++---- tools/pvchange.c | 16 +++ tools/toollib.c | 63 ++++-------- tools/toollib.h | 6 +- tools/tools.h | 2 + tools/vgcfgbackup.c | 2 +- tools/vgchange.c | 5 +- tools/vgck.c | 2 +- tools/vgcreate.c | 29 +++++- tools/vgdisplay.c | 2 +- tools/vgexport.c | 17 ++-- tools/vgextend.c | 33 +++++-- tools/vgimport.c | 15 +-- tools/vgmerge.c | 42 ++++++-- tools/vgreduce.c | 16 ++- tools/vgremove.c | 14 ++- tools/vgrename.c | 49 +++++++--- tools/vgscan.c | 3 +- 27 files changed, 732 insertions(+), 148 deletions(-) create mode 100644 lib/locking/file_locking.c create mode 100644 lib/locking/locking.c diff --git a/lib/Makefile.in b/lib/Makefile.in index 5b9480b61..58d4803b8 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 000000000..1cc157a28 --- /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 +#include +#include +#include +#include +#include +#include + +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 000000000..c4e946241 --- /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 + +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 37d0c1498..ed981585f 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 10d6d05e0..f0ae9aad8 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 1f65a1a6e..3c3e9072c 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 979130fb0..14608d480 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 c2f6f70f7..a77db806f 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 37a22f49e..ed56ee1e3 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 17aa16598..164392517 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 d6d3ac09f..371cddbb1 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 95dbff747..4a466a00a 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -8,43 +8,6 @@ #include -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 98ca5e30b..d43a0b9d6 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 bebee43f7..512b7feab 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 #include diff --git a/tools/vgcfgbackup.c b/tools/vgcfgbackup.c index 17e378837..dbfcb63ee 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 711f5bcdd..aac06152b 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 26d0aeab8..9d9343a5f 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 622cfb2dc..1fdc12bec 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 57e4e54c4..c096d40c6 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 e74db3c8b..05fdb7817 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 6c51c27b9..b51533bd1 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 9163eda7e..e30ab2527 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 eefa4f876..9c134f0ec 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 71153fefc..98b313488 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 cd5d04004..2d29a4d92 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 d3a74cd7f..81b84670e 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 d5f541d8b..bdb439780 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; -- 2.43.5