1
0
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:
Alasdair Kergon 2002-02-11 15:42:34 +00:00
parent 713599407c
commit 7d0e6e800e
27 changed files with 734 additions and 150 deletions

View File

@ -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
View 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
View 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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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\"",

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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>

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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) ?

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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 */

View File

@ -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;