1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-12-25 20:23:49 +03:00

Compare commits

...

17 Commits

Author SHA1 Message Date
Alasdair Kergon
e748a5d5f4 Tidy up for another release: updated documentation; removed old files;
module build fix.
2002-06-26 21:50:53 +00:00
Patrick Caulfield
99c5a3ae46 Flush on open as well as close. 2002-06-25 14:02:28 +00:00
Alasdair Kergon
51da710f5a o Long-awaited ioctl interface clean-up. *** Not backwardly compatible ***
o Various other kernel side tidy-ups.
o Version number changes so we have the option of adding new ioctl commands
  in future without affecting the use of existing ones should you later
  revert to an older kernel but not revert the userspace library/tools.
o Better separation of kernel/userspace elements in the build process to
  prepare for independent distribution of the kernel driver.
2002-06-19 13:07:05 +00:00
Joe Thornber
569d69b3d2 o Knock the version check out of the makefile, Alasdair will no doubt put it back :)
o  Change to new ioctl names.
2002-06-17 15:50:17 +00:00
Patrick Caulfield
059a6b1d90 Get rid of compile warnings on 64bit platforms. 2002-06-07 08:37:07 +00:00
Alasdair Kergon
990af7548a Increment version. 2002-05-31 19:33:30 +00:00
Alasdair Kergon
a38aefdfc8 Add vgsplit. 2002-05-31 19:30:51 +00:00
Alasdair Kergon
3bcb12e7d1 Tidy/fix segment rounding. 2002-05-31 19:29:43 +00:00
Alasdair Kergon
7904ecb462 Tidy 2002-05-31 19:28:37 +00:00
Alasdair Kergon
9ba4d45109 Remember to update VG free_count when reducing size of an LV. 2002-05-30 16:08:19 +00:00
Alasdair Kergon
56b8afe19d Fix vgcfgrestore segfault (wrong variable used). 2002-05-30 16:03:26 +00:00
Alasdair Kergon
f7aed9a94c update 2002-05-27 13:00:18 +00:00
AJ Lewis
e12a7e881d o fix changed function names 2002-05-23 14:13:21 +00:00
Alasdair Kergon
5afb65325d Fix LVM1 backwards compatibility issue when LV with a low LV number is deleted. 2002-05-23 11:37:51 +00:00
Joe Thornber
135f520f32 o Remove ext3 incompatibility bug
o	Mention 2.4.18 VM problem
2002-05-23 08:20:44 +00:00
Andres Salomon
bc251f4ff6 update for .08 2002-05-23 07:49:25 +00:00
Alasdair Kergon
b8769751f6 Rename; add some FIXMEs. 2002-05-22 14:03:45 +00:00
23 changed files with 487 additions and 173 deletions

3
BUGS
View File

@@ -1 +1,2 @@
LVM2's device-mapper driver and ext3 are incompatible at the moment.
Snapshots under 2.4.18 can deadlock due to a bug in the VM system.
2.4.19-pre8 is fine.

View File

@@ -1 +1 @@
1.95.08-cvs (2002-05-21)
1.95.10-cvs (2002-05-31)

6
debian/changelog vendored
View File

@@ -1,3 +1,9 @@
lvm2 (1.95.08-1) unstable; urgency=low
* New upstream release (Beta3).
-- Andres Salomon <dilinger@mp3revolution.net> Thu, 23 May 2002 03:46:37 -0500
lvm2 (0.95.05-3) unstable; urgency=low
* Get rid of awk dependency in init script. (Closes: #146257)

6
debian/init.d vendored
View File

@@ -33,12 +33,6 @@ case "$1" in
echo -n "Initializing $DESC: "
create_devfiles
vgchange -a y
# # Mount all LVM devices
# for vg in $( vgchange -a y 2>/dev/null | grep active | awk -F\" '{print $2}' ); do
# MTPT=$( grep $vg /etc/fstab | awk '{print $2}' )
# mount $MTPT
# done
echo "$NAME."
;;
stop)

View File

@@ -78,7 +78,7 @@ int lv_info(struct logical_volume *lv, struct dm_info *info)
/*
* Returns 1 if percent set, else 0 on failure.
*/
int lv_snapshot_percentage(struct logical_volume *lv, float *percent)
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
{
int r;
struct dev_manager *dm;
@@ -88,9 +88,9 @@ int lv_snapshot_percentage(struct logical_volume *lv, float *percent)
return 0;
}
if (!(r = dev_manager_get_snapshot_use(dm, lv, percent)))
if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
stack;
dev_manager_destroy(dm);
return r;

View File

@@ -19,7 +19,7 @@ int lv_info(struct logical_volume *lv, struct dm_info *info);
/*
* Returns 1 if percent has been set, else 0.
*/
int lv_snapshot_percentage(struct logical_volume *lv, float *percent);
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
/*
* These should eventually use config file

View File

@@ -329,6 +329,7 @@ static int _info(const char *name, const char *uuid, struct dm_info *info,
return 0;
}
/* FIXME Interface must cope with multiple targets */
static int _status_run(const char *name, const char *uuid,
unsigned long long *s, unsigned long long *l,
char **t, uint32_t t_size, char **p, uint32_t p_size)
@@ -336,7 +337,7 @@ static int _status_run(const char *name, const char *uuid,
int r = 0;
struct dm_task *dmt;
void *next = NULL;
unsigned long long start, length;
uint64_t start, length;
char *type = NULL;
char *params = NULL;
@@ -353,28 +354,27 @@ static int _status_run(const char *name, const char *uuid,
do {
next = dm_get_next_target(dmt, next, &start, &length,
&type, &params);
if(type) {
if (type) {
*s = start;
*l = length;
/* Make sure things are null terminated */
strncpy(*t, type, t_size);
(*t)[t_size-1] = '\0';
(*t)[t_size - 1] = '\0';
strncpy(*p, params, p_size);
(*p)[p_size-1] = '\0';
(*p)[p_size - 1] = '\0';
r = 1;
/* FIXME Cope with multiple targets! */
break;
}
} while (next);
} while (next);
out:
dm_task_destroy(dmt);
return r;
}
static int _status(const char *name, const char *uuid,
unsigned long long *start, unsigned long long *length,
char **type, uint32_t type_size, char **params,
@@ -386,13 +386,12 @@ static int _status(const char *name, const char *uuid,
return 1;
if (name && _status_run(name, NULL, start, length, type, type_size,
params, param_size))
params, param_size))
return 1;
return 0;
}
static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname)
{
int r = 1;
@@ -793,23 +792,22 @@ int dev_manager_info(struct dev_manager *dm, struct logical_volume *lv,
return 1;
}
int dev_manager_get_snapshot_use(struct dev_manager *dm,
struct logical_volume *lv, float *percent)
int dev_manager_snapshot_percent(struct dev_manager *dm,
struct logical_volume *lv, float *percent)
{
char *name, *type, *params;
unsigned long long start, length;
/* FIXME: Hard coded numbers can be bad, but not really sure what to
* use here...we don't really care about the type and the parameter
* should be a percentage */
uint32_t type_size = 2;
uint32_t param_size = 7;
if(!(type = pool_alloc(dm->mem, sizeof(*type) * type_size))) {
/* FIXME: Use #defines - & move allocations into _status_run ? */
uint32_t type_size = 32;
uint32_t param_size = 32;
if (!(type = pool_alloc(dm->mem, sizeof(*type) * type_size))) {
stack;
return 0;
}
if(!(params = pool_alloc(dm->mem, sizeof(*params) * param_size))) {
if (!(params = pool_alloc(dm->mem, sizeof(*params) * param_size))) {
stack;
return 0;
}
@@ -817,7 +815,7 @@ int dev_manager_get_snapshot_use(struct dev_manager *dm,
/*
* Build a name for the top layer.
*/
if(!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
stack;
return 0;
}
@@ -826,16 +824,19 @@ int dev_manager_get_snapshot_use(struct dev_manager *dm,
* Try and get some info on this device.
*/
log_debug("Getting device status for %s", name);
if(!(_status(name, lv->lvid.s, &start, &length, &type, type_size,
&params, param_size))) {
stack;
return 0;
if (!(_status(name, lv->lvid.s, &start, &length, &type, type_size,
&params, param_size))) {
stack;
return 0;
}
/* FIXME Ensure this is a *snapshot* target with percentage! */
/* FIXME pool_free ? */
/* If the snapshot isn't available, percent will be -1 */
*percent = -1;
if(!params)
if (!params)
return 0;
return sscanf(params, "%f", percent);

View File

@@ -27,13 +27,12 @@ void dev_manager_destroy(struct dev_manager *dm);
*/
int dev_manager_info(struct dev_manager *dm, struct logical_volume *lv,
struct dm_info *info);
int dev_manager_get_snapshot_use(struct dev_manager *dm,
struct logical_volume *lv, float *percent);
int dev_manager_snapshot_percent(struct dev_manager *dm,
struct logical_volume *lv, float *percent);
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
/*
* Put the desired changes into effect.
*/

View File

@@ -62,6 +62,12 @@ int dev_get_sectsize(struct device *dev, uint32_t * size)
return 1;
}
static void _flush(int fd)
{
ioctl(fd, BLKFLSBUF, 0);
}
int dev_open(struct device *dev, int flags)
{
struct stat buf;
@@ -92,17 +98,12 @@ int dev_open(struct device *dev, int flags)
dev_close(dev);
return 0;
}
_flush(dev->fd);
dev->flags = 0;
return 1;
}
static void _flush(int fd)
{
ioctl(fd, BLKFLSBUF, 0);
}
int dev_close(struct device *dev)
{
if (dev->fd < 0) {

View File

@@ -256,8 +256,8 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
log_print("LV snapshot status source of");
list_iterate(slh, snaplist) {
snap = list_item(slh, struct snapshot_list)->snapshot;
snap_active = lv_snapshot_percentage(snap->cow,
&snap_percent);
snap_active = lv_snapshot_percent(snap->cow,
&snap_percent);
log_print(" %s%s/%s [%s]",
lv->vg->cmd->dev_dir, lv->vg->name,
snap->cow->name,
@@ -270,7 +270,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
}
/* Check to see if this LV is a COW target for a snapshot */
else if ((snap = find_cow(lv))) {
snap_active = lv_snapshot_percentage(lv, &snap_percent);
snap_active = lv_snapshot_percent(lv, &snap_percent);
log_print("LV snapshot status %s destination for %s%s/%s",
(snap_active > 0) ? "active" : "INACTIVE",
lv->vg->cmd->dev_dir, lv->vg->name,

View File

@@ -500,7 +500,7 @@ static int _write_lvd(struct device *dev, ulong pos, struct lv_disk *disk)
static int _write_lvs(struct disk_list *data)
{
struct list *lvh;
ulong pos;
ulong pos, offset;
pos = data->pvd.lv_on_disk.base;
@@ -513,10 +513,15 @@ static int _write_lvs(struct disk_list *data)
list_iterate(lvh, &data->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
if (!_write_lvd(data->dev, pos, &ll->lvd))
fail;
offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
if (offset + sizeof(struct lv_disk) >
data->pvd.lv_on_disk.size) {
log_error("lv_number %d too large", ll->lvd.lv_number);
return 0;
}
pos += sizeof(struct lv_disk);
if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
fail;
}
return 1;

View File

@@ -477,6 +477,7 @@ int lv_reduce(struct format_instance *fi,
lv->le_count -= extents;
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
lv->vg->free_count += extents;
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;

View File

@@ -68,7 +68,8 @@ struct list *find_snapshots(struct logical_volume *lv)
{
struct list *slh;
struct list *snaplist;
struct snapshot_list *sl, *newsl;
struct snapshot *s;
struct snapshot_list *newsl;
struct pool *mem = lv->vg->cmd->mem;
if (!(snaplist = pool_alloc(mem, sizeof(*snaplist)))) {
@@ -79,15 +80,15 @@ struct list *find_snapshots(struct logical_volume *lv)
list_init(snaplist);
list_iterate(slh, &lv->vg->snapshots) {
sl = list_item(slh, struct snapshot_list);
if (!(sl->snapshot->origin == lv))
s = list_item(slh, struct snapshot_list)->snapshot;
if (!(s->origin == lv))
continue;
if (!(newsl = pool_alloc(mem, sizeof(*newsl)))) {
log_error("snapshot_list structure allocation failed");
pool_free(mem, snaplist);
return NULL;
}
newsl->snapshot = sl->snapshot;
newsl->snapshot = s;
list_add(snaplist, &newsl->list);
}

View File

@@ -133,8 +133,9 @@ static int _create_dir_recursive(const char *dir)
{
char *orig, *s;
int rc;
/* create parent directories */
log_verbose("Creating directory \"%s\"", dir);
/* Create parent directories */
orig = s = dbg_strdup(dir);
while ((s = strchr(s, '/')) != NULL) {
*s = '\0';
@@ -150,8 +151,7 @@ static int _create_dir_recursive(const char *dir)
}
dbg_free(orig);
/* done w/ parents, create final directory */
log_verbose("Creating directory \"%s\"", dir);
/* Create final directory */
rc = mkdir(dir, 0777);
if (rc < 0 && errno != EEXIST) {
log_sys_error("mkdir", dir);

View File

@@ -31,23 +31,12 @@ install_fs: fs/libdevmapper.so
install_ioctl: ioctl/libdevmapper.so
$(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/libdevmapper.so.$(LIB_VERSION).$(IOCTL_VERSION)
$(LN_S) -f libdevmapper.so.$(LIB_VERSION).$(IOCTL_VERSION) \
$(libdir)/libdevmapper.so.$(LIB_VERSION)
ioctl/libdevmapper.o: ioctl_version
ioctl_version: ioctl/libdevmapper.c
@echo Checking library version compatible with kernel version in dm-ioctl.h
test "$(IOCTL_VERSION)" = \
"$(shell $(CC) -E -dM $(INCLUDES) $(CFLAGS) \
ioctl/libdevmapper.c | \
awk -F '[ \t\"]+' '/DM_IOCTL_VERSION/ {print $$3}' )"
$(libdir)/libdevmapper.so.$(LIB_VERSION)
distclean_lib:
$(RM) libdm-common.h
distclean: distclean_lib
.PHONY: ioctl_version distclean_lib distclean
.PHONY: distclean_lib distclean

View File

@@ -16,7 +16,7 @@
#include <errno.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/limits.h>
#include <sys/ioctl.h>
#include <linux/dm-ioctl.h>
@@ -25,20 +25,32 @@
#define ALIGNMENT sizeof(int)
static char *dm_cmd_list[] = {
"create",
"reload",
"remove",
"remove_all",
"suspend",
"resume",
"info",
"deps",
"rename",
"version",
"status",
"table",
"waitevent"
/*
* Ensure build compatibility. The hard-coded version here (major, minor)
* is the highest present in the _cmd_data array below.
*/
#if DM_VERSION_MAJOR != 1 || DM_VERSION_MINOR < 0
#error The version of dm-ioctl.h included is incompatible.
#endif
static struct {
char *name;
int cmd;
int version[3];
} _cmd_data[] = {
{ "create", DM_DEV_CREATE, {1, 0, 0} },
{ "reload", DM_DEV_RELOAD, {1, 0, 0} },
{ "remove", DM_DEV_REMOVE, {1, 0, 0} },
{ "remove_all", DM_REMOVE_ALL, {1, 0, 0} },
{ "suspend", DM_DEV_SUSPEND, {1, 0, 0} },
{ "resume", DM_DEV_SUSPEND, {1, 0, 0} },
{ "info", DM_DEV_STATUS, {1, 0, 0} },
{ "deps", DM_DEV_DEPS, {1, 0, 0} },
{ "rename", DM_DEV_RENAME, {1, 0, 0} },
{ "version", DM_VERSION, {1, 0, 0} },
{ "status", DM_TARGET_STATUS, {1, 0, 0} },
{ "table", DM_TARGET_STATUS, {1, 0, 0} },
{ "waitevent", DM_TARGET_WAIT, {1, 0, 0} },
};
static void *_align(void *ptr, unsigned int a)
@@ -76,11 +88,13 @@ void dm_task_destroy(struct dm_task *dmt)
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
{
unsigned int *v;
if (!dmt->dmi)
return 0;
strncpy(version, dmt->dmi->version, size);
v = dmt->dmi->version;
snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
return 1;
}
@@ -281,7 +295,9 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
memset(dmi, 0, len);
strncpy(dmi->version, DM_IOCTL_VERSION, sizeof(dmi->version));
dmi->version[0] = _cmd_data[dmt->type].version[0];
dmi->version[1] = _cmd_data[dmt->type].version[1];
dmi->version[2] = _cmd_data[dmt->type].version[2];
dmi->data_size = len;
dmi->data_start = sizeof(struct dm_ioctl);
@@ -339,71 +355,23 @@ int dm_task_run(struct dm_task *dmt)
goto bad;
}
switch (dmt->type) {
case DM_DEVICE_CREATE:
command = DM_CREATE;
break;
case DM_DEVICE_RELOAD:
command = DM_RELOAD;
break;
case DM_DEVICE_REMOVE:
command = DM_REMOVE;
break;
case DM_DEVICE_REMOVE_ALL:
command = DM_REMOVE_ALL;
break;
case DM_DEVICE_SUSPEND:
command = DM_SUSPEND;
break;
case DM_DEVICE_RESUME:
command = DM_SUSPEND;
break;
case DM_DEVICE_INFO:
command = DM_INFO;
break;
case DM_DEVICE_DEPS:
command = DM_DEPS;
break;
case DM_DEVICE_RENAME:
command = DM_RENAME;
break;
case DM_DEVICE_VERSION:
command = DM_VERSION;
break;
case DM_DEVICE_STATUS:
command = DM_GET_STATUS;
break;
case DM_DEVICE_TABLE:
dmi->flags |= DM_STATUS_TABLE_FLAG;
command = DM_GET_STATUS;
break;
case DM_DEVICE_WAITEVENT:
command = DM_WAIT_EVENT;
break;
default:
if (dmt->type >= (sizeof(_cmd_data) / sizeof(*_cmd_data))) {
log_error("Internal error: unknown device-mapper task %d",
dmt->type);
goto bad;
}
log_debug("dm %s %s %s %s", dm_cmd_list[dmt->type], dmi->name,
command = _cmd_data[dmt->type].cmd;
if (dmt->type == DM_DEVICE_TABLE)
dmi->flags |= DM_STATUS_TABLE_FLAG;
log_debug("dm %s %s %s %s", _cmd_data[dmt->type].name, dmi->name,
dmi->uuid, dmt->newname ? dmt->newname : "");
if (ioctl(fd, command, dmi) < 0) {
log_error("device-mapper ioctl cmd %d failed: %s", dmt->type,
strerror(errno));
log_error("device-mapper ioctl cmd %d failed: %s",
_IOC_NR(command), strerror(errno));
goto bad;
}

View File

@@ -4,11 +4,14 @@ dmsetup \- low level logical volume management
.SH SYNOPSIS
.ad l
.B dmsetup create
.I device_name table_file
.I device_name table_file [uuid]
.br
.B dmsetup remove
.I device_name
.br
.B dmsetup rename
.I device_name new_name
.br
.B dmsetup suspend
.I device_name
.br
@@ -20,6 +23,23 @@ dmsetup \- low level logical volume management
.br
.B dmsetup info
.I device_name
.br
.B dmsetup deps
.I device_name
.br
.B dmsetup status
.I device_name
.br
.B dmsetup table
.I device_name
.br
.B dmsetup wait
.I device_name
.br
.B dmsetup remove_all
.I device_name
.br
.B dmsetup version
.ad b
.SH DESCRIPTION
dmsetup manages logical devices that use the device-mapper driver.
@@ -27,19 +47,25 @@ Devices are created by loading a table that specifies a target for
each sector in the logical device.
The first argument to dmsetup is a command.
The second argument is the logical device name.
The second argument is the logical device name or uuid.
.SH COMMANDS
.IP \fBcreate
.I device_name table_file
.I device_name table_file [uuid]
.br
Attempts to create a device using the table file given. If
Attempts to create a device using the table file given.
The optional uuid can be used in place of
device_name in subsequent dmsetup commands. If
successful a device will appear as
/dev/device-mapper/<device-name>. See below for information
on the table file format.
.IP \fBremove
.I device_name
.br
Removes the device
Removes a device
.IP \fBrename
.I device_name new_name
.br
Renames a device
.IP \fBsuspend
.I device_name
.br
@@ -67,14 +93,40 @@ Outputs some brief information about the device in the form:
major,minor
.br
target_count
.IP \fBdeps
.I device_name
.br
Outputs a list of (major, minor) pairs for devices referenced by the
specified device.
.IP \fBstatus
.I device_name
.br
Outputs status information for each of the device's targets.
.IP \fBtable
.I device_name
.br
Outputs the current table for the device in a format than can be fed
back in using the create or reload commands.
.IP \fBwait
.I device_name
.br
Sleeps until an event is triggered against a device.
.IP \fBremove_all
.br
Attempts to remove all device definitions i.e. reset the driver.
Use with care!
.IP \fBversion
.I device_name
.br
Outputs version information.
.SH TABLE FORMAT
Each line of the table specifies a single target and is of the form:
.br
logical_start_sector num_sectors target_type target_args
.br
.br
At the moment there are 3 simple target types available - though your
system might have more in the form of modules.
There are currently three simple target types available together
with more complex optional ones that implement snapshots and mirrors.
.IP \fBlinear
.I destination_device start_sector

View File

@@ -52,7 +52,8 @@ SOURCES=\
vgreduce.c \
vgremove.c \
vgrename.c \
vgscan.c
vgscan.c \
vgsplit.c
TARGETS=\
.commands \

View File

@@ -234,10 +234,9 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
struct format_instance *tf;
void *context;
if (!(context = create_text_context(vg->cmd->fmtt, file,
if (!(context = create_text_context(cmd->fmtt, file,
cmd->cmd_line)) ||
!(tf = vg->cmd->fmtt->ops->create_instance(cmd->fmtt, NULL,
context))) {
!(tf = cmd->fmtt->ops->create_instance(cmd->fmtt, NULL, context))) {
log_error("Couldn't create text format object.");
return NULL;
}

View File

@@ -87,9 +87,9 @@ xx(lvcreate,
"\t[--version]\n"
"\tVolumeGroupName [PhysicalVolumePath...]\n\n",
autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG,
minor_ARG, name_ARG, permission_ARG, persistent_ARG, readahead_ARG,
size_ARG, snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, zero_ARG)
autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG, minor_ARG,
name_ARG, permission_ARG, persistent_ARG, readahead_ARG, size_ARG,
snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, zero_ARG)
xx(lvdisplay,
"Display information about a logical volume",
@@ -533,13 +533,14 @@ xx(vgsplit,
"\t[-d|--debug] " "\n"
"\t[-h|--help] " "\n"
"\t[-l|--list]" "\n"
"\t[-M|--metadatatype lvm1/text] " "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version]" "\n"
"\tExistingVolumeGroupName NewVolumeGroupName" "\n"
"\tPhysicalVolumePath [PhysicalVolumePath...]\n",
autobackup_ARG, list_ARG, test_ARG)
autobackup_ARG, list_ARG, metadatatype_ARG, test_ARG)
xx(version,
"Display software and driver version information",

View File

@@ -27,7 +27,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
struct dm_info info;
uint32_t extents = 0;
uint32_t size = 0;
uint32_t stripes = 0, stripesize = 0;
uint32_t stripes = 0, stripesize = 0, stripesize_extents = 0;
uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
uint32_t extents_used = 0;
uint32_t size_rest;
@@ -256,12 +256,19 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
if (stripes > 1 && !stripesize) {
log_error("Stripesize for striped segment should not be 0!");
} else if ((stripes > 1) &&
(size_rest = seg_size % (stripes * stripesize))) {
log_print("Rounding size (%d extents) down to stripe boundary "
"size for segment (%d extents)", extents,
extents - size_rest);
extents = extents - size_rest;
goto error_cmdline;
}
if ((stripes > 1)) {
if (!(stripesize_extents = stripesize / vg->extent_size))
stripesize_extents = 1;
if ((size_rest = seg_size % (stripes * stripesize_extents))) {
log_print("Rounding size (%d extents) down to stripe "
"boundary size for segment (%d extents)",
extents, extents - size_rest);
extents = extents - size_rest;
}
}
if (extents == lv->le_count) {

View File

@@ -13,5 +13,4 @@ int pvdata(struct cmd_context *cmd, int argc, char **argv) unimplemented
int pvmove(struct cmd_context *cmd, int argc, char **argv) unimplemented
int pvresize(struct cmd_context *cmd, int argc, char **argv) unimplemented
int vgmknodes(struct cmd_context *cmd, int argc, char **argv) unimplemented
int vgsplit(struct cmd_context *cmd, int argc, char **argv) unimplemented

289
tools/vgsplit.c Normal file
View File

@@ -0,0 +1,289 @@
/*
* Copyright (C) 2001 Sistina Software
*
* LVM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* LVM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LVM; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#include "tools.h"
static int _move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
char *pv_name)
{
struct pv_list *pvl;
struct physical_volume *pv;
if (!(pvl = find_pv_in_vg(vg_from, pv_name))) {
log_error("Physical volume %s not in volume group %s",
pv_name, vg_from->name);
return 0;
}
list_del(&pvl->list);
list_add(&vg_to->pvs, &pvl->list);
vg_from->pv_count--;
vg_to->pv_count++;
pv = list_item(pvl, struct pv_list)->pv;
vg_from->extent_count -= pv->pe_count;
vg_to->extent_count += pv->pe_count;
vg_from->free_count -= pv->pe_count - pv->pe_alloc_count;
vg_to->free_count += pv->pe_count - pv->pe_alloc_count;
return 1;
}
static int _pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
{
struct list *pvh;
list_iterate(pvh, &vg->pvs) {
if (pv == list_item(pvh, struct pv_list)->pv)
return 1;
}
return 0;
}
static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
{
struct list *lvh, *lvht, *segh;
struct logical_volume *lv;
struct stripe_segment *seg;
struct physical_volume *pv;
struct volume_group *vg_with;
int s;
list_iterate_safe(lvh, lvht, &vg_from->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
/* Ensure all the PVs used by this LV remain in the same */
/* VG as each other */
vg_with = NULL;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
if (vg_with) {
if (!_pv_is_in_vg(vg_with, pv)) {
log_error("Logical Volume %s "
"split between "
"Volume Groups",
lv->name);
return 0;
}
continue;
}
if (_pv_is_in_vg(vg_from, pv)) {
vg_with = vg_from;
continue;
}
if (_pv_is_in_vg(vg_to, pv)) {
vg_with = vg_to;
continue;
}
log_error("Physical Volume %s not found",
dev_name(pv->dev));
return 0;
}
}
if (vg_with == vg_from)
continue;
/* Move this LV */
list_del(lvh);
list_add(&vg_to->lvs, lvh);
vg_from->lv_count--;
vg_to->lv_count++;
}
return 1;
}
static int _lv_is_in_vg(struct volume_group *vg, struct logical_volume *lv)
{
struct list *lvh;
list_iterate(lvh, &vg->lvs) {
if (lv == list_item(lvh, struct lv_list)->lv)
return 1;
}
return 0;
}
static int _move_snapshots(struct volume_group *vg_from,
struct volume_group *vg_to)
{
struct list *slh, *slth;
struct snapshot *snap;
int cow_from, origin_from;
list_iterate_safe(slh, slth, &vg_from->snapshots) {
snap = list_item(slh, struct snapshot_list)->snapshot;
cow_from = _lv_is_in_vg(vg_from, snap->cow);
origin_from = _lv_is_in_vg(vg_from, snap->origin);
if (cow_from && origin_from)
return 1;
if ((!cow_from && origin_from) || (cow_from && !origin_from)) {
log_error("Snapshot %s split", snap->cow->name);
return 0;
}
vg_from->snapshot_count--;
vg_to->snapshot_count++;
list_del(slh);
list_add(&vg_to->snapshots, slh);
}
return 1;
}
int vgsplit(struct cmd_context *cmd, int argc, char **argv)
{
char *vg_name_from, *vg_name_to;
struct volume_group *vg_to, *vg_from;
int opt;
int active;
if (argc < 3) {
log_error("Existing VG, new VG and physical volumes required.");
return EINVALID_CMD_LINE;
}
vg_name_from = argv[0];
vg_name_to = argv[1];
argc -= 2;
argv += 2;
if (!strcmp(vg_name_to, vg_name_from)) {
log_error("Duplicate volume group name \"%s\"", vg_name_from);
return ECMD_FAILED;
}
log_verbose("Checking for volume group \"%s\"", vg_name_from);
if (!lock_vol(cmd, vg_name_from, LCK_VG_WRITE)) {
log_error("Can't get lock for %s", vg_name_from);
return ECMD_FAILED;
}
if (!(vg_from = vg_read(cmd, vg_name_from))) {
log_error("Volume group \"%s\" doesn't exist", vg_name_from);
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
}
if (vg_from->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg_from->name);
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
}
if (!(vg_from->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_from->name);
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
}
log_verbose("Checking for volume group \"%s\"", vg_name_to);
if (!lock_vol(cmd, vg_name_to, LCK_VG_WRITE | LCK_NONBLOCK)) {
log_error("Can't get lock for %s", vg_name_to);
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
}
if ((vg_to = vg_read(cmd, vg_name_to))) {
/* FIXME Remove this restriction */
log_error("Volume group \"%s\" already exists", vg_name_to);
goto error;
}
if ((active = lvs_in_vg_activated(vg_from))) {
/* FIXME Remove this restriction */
log_error("Logical volumes in \"%s\" must be inactive",
vg_name_from);
goto error;
}
/* Create new VG structure */
if (!(vg_to = vg_create(cmd, vg_name_to, vg_from->extent_size,
vg_from->max_pv, vg_from->max_lv, 0, NULL)))
goto error;
/* Archive vg_from before changing it */
if (!archive(vg_from))
goto error;
/* Move PVs across to new structure */
for (opt = 0; opt < argc; opt++) {
if (!_move_pv(vg_from, vg_to, argv[opt]))
goto error;
}
/* Move required LVs across, checking consistency */
if (!(_move_lvs(vg_from, vg_to)))
goto error;
/* Move required snapshots across */
if (!(_move_snapshots(vg_from, vg_to)))
goto error;
/* store it on disks */
log_verbose("Writing out updated volume groups");
/* Write out new VG as EXPORTED */
vg_to->status |= EXPORTED_VG;
if (!archive(vg_to))
goto error;
if (!vg_write(vg_to))
goto error;
backup(vg_to);
/* Write out updated old VG */
if (!vg_write(vg_from))
goto error;
backup(vg_from);
/* Remove EXPORTED flag from new VG */
vg_to->status &= ~EXPORTED_VG;
if (!vg_write(vg_to))
goto error;
backup(vg_to);
unlock_vg(cmd, vg_name_from);
unlock_vg(cmd, vg_name_to);
log_print("Volume group \"%s\" successfully split from \"%s\"",
vg_to->name, vg_from->name);
return 0;
error:
unlock_vg(cmd, vg_name_from);
unlock_vg(cmd, vg_name_to);
return ECMD_FAILED;
}