mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-30 01:47:56 +03:00
o Support locking with local lock files
o Disable control-c during updates (except if blocked waiting for a lock)
This commit is contained in:
parent
713599407c
commit
7d0e6e800e
@ -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 \
|
||||
|
193
lib/locking/file_locking.c
Normal file
193
lib/locking/file_locking.c
Normal file
@ -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;
|
||||
}
|
154
lib/locking/locking.c
Normal file
154
lib/locking/locking.c
Normal file
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
11
tools/lvm.c
11
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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\"",
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) ?
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 ((vg_new = fid->ops->vg_read(fid, vg_name_new))) {
|
||||
log_error("New volume group \"%s\" already exists",
|
||||
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);
|
||||
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 */
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user