1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-27 05:44:18 +03:00

Compare commits

...

36 Commits

Author SHA1 Message Date
Alasdair Kergon
34d9b5e3d7 2.00.24 2004-09-16 20:56:18 +00:00
Alasdair Kergon
3bf5189d86 Fix pool_empty so it really does empty the memory pool. 2004-09-16 20:09:55 +00:00
Alasdair Kergon
12e5b0681b Rename old segtypes files to segtype. 2004-09-16 18:40:56 +00:00
Alasdair Kergon
8c0285d608 Some fixes to memory debugging code.
Exclude internal commands formats & segtypes from install.
2004-09-16 16:53:39 +00:00
Alasdair Kergon
36558fa3b8 post-2.00.23 2004-09-15 15:59:19 +00:00
Alasdair Kergon
235f940cde 2.00.23 2004-09-15 15:32:21 +00:00
Alasdair Kergon
803d61fcbc Add formats & segtypes files. 2004-09-15 15:27:26 +00:00
Alasdair Kergon
ffbd7d8de4 Export dm name build & split functions. 2004-09-15 15:02:36 +00:00
Alasdair Kergon
4ed924d7c7 Use O_NOATIME on devices if available. 2004-09-14 22:23:23 +00:00
Alasdair Kergon
798dc9948b Write log message when each segtype/format gets initialised. 2004-09-14 17:37:51 +00:00
Alasdair Kergon
13515f7ee4 New commands 'segtypes' and 'formats'. 2004-09-14 16:42:46 +00:00
Alasdair Kergon
ef80824c26 Suppress pvmove abort message in test mode. 2004-09-14 15:23:42 +00:00
Alasdair Kergon
c8503fd65e Improve pvcreate/remove device not found error message. 2004-09-14 14:54:58 +00:00
Alasdair Kergon
b3c454fb1c Allow pvmove to move data within the same PV. 2004-09-14 13:59:17 +00:00
Alasdair Kergon
1d7723e873 Describe how pvmove works on man page. 2004-09-14 13:58:11 +00:00
Alasdair Kergon
77100b2365 Test for incompatible format/segtype combinations in lv_extend. 2004-09-14 13:56:18 +00:00
Patrick Caulfield
259a788134 Fix man page for lvchange. The example seems to have been lifted from pvchange. 2004-09-13 08:01:54 +00:00
Alasdair Kergon
39511455cb post 2.00.22 2004-09-03 19:18:23 +00:00
Alasdair Kergon
b04c16178e 2.00.22 2004-09-03 19:08:50 +00:00
Alasdair Kergon
49a959c06e Fix /dev/vgname mkdir perms. 2004-09-02 14:38:46 +00:00
Alasdair Kergon
096a8932b4 clvmd man page tweaks 2004-09-02 14:16:54 +00:00
Alasdair Kergon
e39e66df93 Restructure xlate.h 2004-09-02 13:53:25 +00:00
Patrick Caulfield
513633f49a clvmd man page. 2004-08-23 08:42:53 +00:00
Alasdair Kergon
eb3740daaf post-2.4.21 2004-08-19 17:13:49 +00:00
Alasdair Kergon
f7947b148a 2.00.21 2004-08-19 16:10:15 +00:00
Alasdair Kergon
9a2a702f3f Recognise iseries/vd devices. 2004-08-18 19:13:01 +00:00
Alasdair Kergon
c65d95bf29 Cluster-extension-only installation. 2004-08-18 18:57:40 +00:00
Alasdair Kergon
753a5edc4f Cope with DT_UNKNOWN in sysfs. 2004-08-18 18:50:21 +00:00
Alasdair Kergon
0b3f853c2d Update pvmove prototype. 2004-08-18 18:49:29 +00:00
Patrick Caulfield
3527fcf1d5 Updated file from cman. 2004-08-18 16:04:35 +00:00
Alasdair Kergon
4544a89c7a Support for PE ranges in pvmove source PV. 2004-08-17 22:09:02 +00:00
Alasdair Kergon
ffeae9005e Remove duplicate line in pvremove help text. 2004-08-17 22:06:06 +00:00
Alasdair Kergon
47217bcfb7 Change alloc_areas to pe_ranges and allow suppression of availability checks. 2004-08-17 21:55:23 +00:00
Alasdair Kergon
80ff58b57a Add a const. 2004-08-11 13:15:35 +00:00
Alasdair Kergon
d15dd368f1 Add dev_size column to pvs. 2004-08-11 13:15:05 +00:00
Alasdair Kergon
8a2ec32bd8 Add report columns for in-kernel device number. 2004-07-03 22:07:52 +00:00
68 changed files with 2776 additions and 1786 deletions

View File

@@ -1 +1 @@
2.00.21-cvs (2004-07-03)
2.00.24-cvs (2004-09-16)

View File

@@ -1,5 +1,43 @@
Version 2.00.21 -
=============================
Version 2.00.24 - 16th September 2004
=====================================
Fix pool_empty so it really does empty the memory pool.
Rename old segtypes files to segtype.
Some fixes to memory debugging code.
Exclude internal commands formats & segtypes from install.
Version 2.00.23 - 15th September 2004
=====================================
Export dm name build & split functions.
Use O_NOATIME on devices if available.
Write log message when each segtype/format gets initialised.
New commands 'segtypes' and 'formats'.
Suppress pvmove abort message in test mode.
Improve pvcreate/remove device not found error message.
Allow pvmove to move data within the same PV.
Describe how pvmove works on man page.
Test for incompatible format/segtype combinations in lv_extend.
Fix lvchange example on man page.
Version 2.00.22 - 3rd September 2004
====================================
Fix /dev/vgname perms.
Restructure xlate.h.
Add clvmd man page.
Version 2.00.21 - 19th August 2004
==================================
Update cnxman-socket.h from cman.
Recognise iseries/vd devices.
Use 'make install_cluster' to install cluster extensions only.
Cope with DT_UNKNOWN in sysfs.
Fix extents_moved metadata size comment.
Remove duplicate line in pvremove help text.
Support variable mirror region size.
Support PE ranges in pvmove source PV.
Fixes to as-yet-unused LV segment splitting code.
Change alloc_areas to pe_ranges and allow suppression of availability checks.
Add dev_size column to pvs.
Add report columns for in-kernel device number.
Version 2.00.20 - 3 July 2004
=============================

View File

@@ -44,3 +44,6 @@ install_clvmd: $(TARGETS)
$(sbindir)/clvmd
install: $(INSTALL_TARGETS)
install_cluster: $(INSTALL_TARGETS)

View File

@@ -17,26 +17,16 @@
#ifndef __CNXMAN_SOCKET_H
#define __CNXMAN_SOCKET_H
/* Just made these up but the address family must be less than 32 (NPROTO) */
#define AF_CLUSTER 31
/* A currently unused number. TIPC also uses this number and you're unlikely
to be using both.
*/
#define AF_CLUSTER 30
#define PF_CLUSTER AF_CLUSTER
/* Protocol(socket) types */
#define CLPROTO_MASTER 2
#define CLPROTO_CLIENT 3
/* Setsockopt -- maybe should be ioctls?? */
#define CLU_SET_MULTICAST 100
#define CLU_JOIN_CLUSTER 101
#define CLU_LEAVE_CLUSTER 102
#define CLU_SET_RCVONLY 103
#define CLU_SET_UNICAST 104
#define KCL_SET_MULTICAST 105
#define KCL_SET_RCVONLY 106
#define KCL_SET_UNICAST 107
#define KCL_SET_NODENAME 108
#define CLU_SET_NODENAME 109
/* ioctls -- should register these properly */
#define SIOCCLUSTER_NOTIFY _IOW('x', 0x01, int)
#define SIOCCLUSTER_REMOVENOTIFY _IO( 'x', 0x02)
@@ -58,12 +48,20 @@
#define SIOCCLUSTER_SERVICE_SETSIGNAL _IOW('x', 0x30, int)
#define SIOCCLUSTER_SERVICE_STARTDONE _IOW('x', 0x40, unsigned int)
#define SIOCCLUSTER_SERVICE_GETEVENT _IOR('x', 0x50, struct cl_service_event)
#define SIOCCLUSTER_SERVICE_GETMEMBERS _IOR('x', 0x60, struct cl_cluster_node)
#define SIOCCLUSTER_SERVICE_GETMEMBERS _IOR('x', 0x60, struct cl_cluster_nodelist)
#define SIOCCLUSTER_SERVICE_GLOBALID _IOR('x', 0x70, uint32_t)
#define SIOCCLUSTER_SERVICE_SETLEVEL _IOR('x', 0x80, int)
#define SIOCCLUSTER_GETNODE _IOWR('x', 0x90, struct cl_cluster_node)
#define SIOCCLUSTER_BARRIER _IOW('x', 0x0a0, struct cl_barrier_info)
/* These were setsockopts */
#define SIOCCLUSTER_PASS_SOCKET _IOW('x', 0x0b0, struct cl_passed_sock)
#define SIOCCLUSTER_SET_NODENAME _IOW('x', 0x0b1, char *)
#define SIOCCLUSTER_SET_NODEID _IOW('x', 0x0b2, int)
#define SIOCCLUSTER_JOIN_CLUSTER _IOW('x', 0x0b3, struct cl_join_cluster_info)
#define SIOCCLUSTER_LEAVE_CLUSTER _IOW('x', 0x0b4, int)
/* Maximum size of a cluster message */
#define MAX_CLUSTER_MESSAGE 1500
#define MAX_CLUSTER_MEMBER_NAME_LEN 255
@@ -109,7 +107,7 @@
#define MSG_ALLINT 0x100000 /* Send out of all interfaces */
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
NODESTATE_DEAD } nodestate_t;
NODESTATE_DEAD } nodestate_t;
struct sockaddr_cl {
@@ -119,13 +117,14 @@ struct sockaddr_cl {
int scl_nodeid;
};
/* This is how we pass the multicast socket into kernel space. addr is the
* multicast address to use in the address family of the socket (eg for UDP it
* might be 255.255.255.0) */
struct cl_multicast_sock {
/*
* This is how we pass the multicast & receive sockets into kernel space.
*/
struct cl_passed_sock {
int fd; /* FD of master socket to do multicast on */
int number; /* Socket number, to match up recvonly & bcast
* sockets */
int multicast; /* Is it multicast or receive ? */
};
/* Cluster configuration info passed when we join the cluster */

View File

@@ -31,7 +31,7 @@
../lib/log/log.h
../lib/metadata/lv_alloc.h
../lib/metadata/metadata.h
../lib/metadata/segtypes.h
../lib/metadata/segtype.h
../lib/mm/dbg_malloc.h
../lib/mm/memlock.h
../lib/mm/pool.h

View File

@@ -20,6 +20,8 @@ VPATH = @srcdir@
LN_S = @LN_S@
.PHONY: clean distclean all install pofile install_cluster
all: .symlinks_created
.symlinks_created: .symlinks
@@ -37,5 +39,5 @@ clean:
install:
.PHONY: clean distclean all install pofile
install_cluster:

View File

@@ -70,7 +70,7 @@ SOURCES =\
metadata/metadata.c \
metadata/mirror.c \
metadata/pv_map.c \
metadata/segtypes.c \
metadata/segtype.c \
metadata/snapshot_manip.c \
misc/crc.c \
misc/lvm-file.c \

View File

@@ -21,7 +21,7 @@
#include "lvm-string.h"
#include "fs.h"
#include "defaults.h"
#include "segtypes.h"
#include "segtype.h"
#include "display.h"
#include "toolcontext.h"
#include "targets.h"
@@ -165,89 +165,6 @@ static inline void _clear_flag(struct dev_layer *dl, int bit)
dl->flags &= ~(1 << bit);
}
/*
* Device layer names are all of the form <vg>-<lv>-<layer>, any
* other hyphens that appear in these names are quoted with yet
* another hyphen. The top layer of any device has no layer
* name. eg, vg0-lvol0.
*/
static void _count_hyphens(const char *str, size_t *len, int *hyphens)
{
const char *ptr;
for (ptr = str; *ptr; ptr++, (*len)++)
if (*ptr == '-')
(*hyphens)++;
}
/*
* Copies a string, quoting hyphens with hyphens.
*/
static void _quote_hyphens(char **out, const char *src)
{
while (*src) {
if (*src == '-')
*(*out)++ = '-';
*(*out)++ = *src++;
}
}
/*
* <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
*/
static char *_build_name(struct pool *mem, const char *vg,
const char *lv, const char *layer)
{
size_t len = 0;
int hyphens = 0;
char *r, *out;
_count_hyphens(vg, &len, &hyphens);
_count_hyphens(lv, &len, &hyphens);
if (layer && *layer)
_count_hyphens(layer, &len, &hyphens);
len += hyphens + 2;
if (!(r = pool_alloc(mem, len))) {
stack;
return NULL;
}
out = r;
_quote_hyphens(&out, vg);
*out++ = '-';
_quote_hyphens(&out, lv);
if (layer && *layer) {
*out++ = '-';
_quote_hyphens(&out, layer);
}
*out = '\0';
return r;
}
/* Find start of LV component in hyphenated name */
static char *_find_lv_name(char *vg)
{
char *c = vg;
while (*c && *(c + 1)) {
if (*c == '-') {
if (*(c + 1) == '-')
c++;
else
return (c + 1);
}
c++;
}
return NULL;
}
static char *_build_dlid(struct pool *mem, const char *lvid, const char *layer)
{
char *dlid;
@@ -519,10 +436,16 @@ static int _percent(struct dev_manager *dm, const char *name, const char *uuid,
return 0;
}
static int _rename(struct dev_layer *dl, char *newname)
static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname)
{
int r = 1;
struct dm_task *dmt;
char *vgname, *lvname, *layer;
if (!split_dm_name(dm->mem, dl->name, &vgname, &lvname, &layer)) {
log_error("Couldn't split up dm layer name %s", dl->name);
return 0;
}
log_verbose("Renaming %s to %s", dl->name, newname);
@@ -537,11 +460,13 @@ static int _rename(struct dev_layer *dl, char *newname)
goto out;
}
if (!(r = dm_task_run(dmt)))
if (!(r = dm_task_run(dmt))) {
log_error("Couldn't rename device '%s'.", dl->name);
goto out;
}
if (r && _get_flag(dl, VISIBLE))
fs_rename_lv(dl->lv, newname, _find_lv_name(dl->name));
fs_rename_lv(dl->lv, newname, lvname);
dl->name = newname;
@@ -1052,7 +977,7 @@ int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
/*
* Build a name for the top layer.
*/
if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
stack;
return 0;
}
@@ -1077,7 +1002,7 @@ int dev_manager_snapshot_percent(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_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
stack;
return 0;
}
@@ -1109,7 +1034,7 @@ int dev_manager_mirror_percent(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_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) {
stack;
return 0;
}
@@ -1173,7 +1098,7 @@ static struct dev_layer *_create_layer(struct dev_manager *dm,
char *name, *dlid;
struct dev_layer *dl;
if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, layer))) {
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) {
stack;
return NULL;
}
@@ -1618,11 +1543,11 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
if (dl->info.exists) {
if ((suffix = rindex(dl->dlid, '-')))
suffix++;
newname = _build_name(dm->mem, dm->vg_name, dl->lv->name,
suffix);
newname = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
suffix);
if (strcmp(newname, dl->name)) {
if (!_suspend_parents(dm, dl) ||
!_suspend(dl) || !_rename(dl, newname)) {
!_suspend(dl) || !_rename(dm, dl, newname)) {
stack;
return 0;
}
@@ -2227,8 +2152,8 @@ int dev_manager_lv_mknodes(const struct logical_volume *lv)
{
char *name;
if (!(name = _build_name(lv->vg->cmd->mem, lv->vg->name,
lv->name, NULL))) {
if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name,
lv->name, NULL))) {
stack;
return 0;
}

View File

@@ -46,7 +46,7 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
return 1;
log_very_verbose("Creating directory %s", vg_path);
if (mkdir(vg_path, 0555)) {
if (mkdir(vg_path, 0777)) {
log_sys_error("mkdir", vg_path);
return 0;
}

View File

@@ -33,7 +33,7 @@
#include "display.h"
#include "memlock.h"
#include "str_list.h"
#include "segtypes.h"
#include "segtype.h"
#include "lvmcache.h"
#ifdef HAVE_LIBDL

View File

@@ -96,9 +96,9 @@
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,move_pv,copy_percent,lv_uuid"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,lv_uuid"
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid"
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
#define DEFAULT_LVS_SORT "vg_name,lv_name"

View File

@@ -212,7 +212,7 @@ static int _aligned_io(struct device_area *where, void *buffer,
* Public functions
*---------------------------------------------------------------*/
int dev_get_size(struct device *dev, uint64_t *size)
int dev_get_size(const struct device *dev, uint64_t *size)
{
int fd;
const char *name = dev_name(dev);
@@ -300,6 +300,12 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
flags |= O_DIRECT;
#endif
#ifdef O_NOATIME
/* Don't update atime on device inodes */
if (!(dev->flags & DEV_REGULAR))
flags |= O_NOATIME;
#endif
if ((dev->fd = open(name, flags, 0777)) < 0) {
log_sys_error("open", name);
return 0;

View File

@@ -55,7 +55,7 @@ struct device_area {
/*
* All io should use these routines.
*/
int dev_get_size(struct device *dev, uint64_t *size);
int dev_get_size(const struct device *dev, uint64_t *size);
int dev_get_sectsize(struct device *dev, uint32_t *size);
/* Use quiet version if device number could change e.g. when opening LV */

View File

@@ -18,7 +18,7 @@
#include "display.h"
#include "activate.h"
#include "toolcontext.h"
#include "segtypes.h"
#include "segtype.h"
#define SIZE_BUF 128
@@ -662,3 +662,22 @@ void vgdisplay_short(struct volume_group *vg)
SIZE_SHORT));
return;
}
void display_formats(struct cmd_context *cmd)
{
struct format_type *fmt;
list_iterate_items(fmt, &cmd->formats) {
log_print("%s", fmt->name);
}
}
void display_segtypes(struct cmd_context *cmd)
{
struct segment_type *segtype;
list_iterate_items(segtype, &cmd->segtypes) {
log_print("%s", segtype->name);
}
}

View File

@@ -45,6 +45,9 @@ void vgdisplay_full(struct volume_group *vg);
void vgdisplay_colons(struct volume_group *vg);
void vgdisplay_short(struct volume_group *vg);
void display_formats(struct cmd_context *cmd);
void display_segtypes(struct cmd_context *cmd);
/*
* Allocation policy display conversion routines.
*/

View File

@@ -16,7 +16,7 @@
#include "pool.h"
#include "list.h"
#include "toolcontext.h"
#include "segtypes.h"
#include "segtype.h"
#include "display.h"
#include "text_export.h"
#include "text_import.h"
@@ -97,5 +97,7 @@ struct segment_type *init_error_segtype(struct cmd_context *cmd)
segtype->private = NULL;
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
log_very_verbose("Initialised segtype: %s", segtype->name);
return segtype;
}

View File

@@ -169,6 +169,8 @@ static int _read_devs(struct dev_set *ds, const char *dir)
{
struct dirent *d;
DIR *dr;
unsigned char dtype;
struct stat info;
char path[PATH_MAX];
dev_t dev;
int r = 1;
@@ -189,19 +191,29 @@ static int _read_devs(struct dev_set *ds, const char *dir)
continue;
}
if (d->d_type == DT_DIR) {
dtype = d->d_type;
if (dtype == DT_UNKNOWN) {
if (stat(path, &info) >= 0) {
if (S_ISDIR(info.st_mode))
dtype = DT_DIR;
else if (S_ISREG(info.st_mode))
dtype = DT_REG;
}
}
if (dtype == DT_DIR) {
if (!_read_devs(ds, path)) {
r = 0;
break;
}
}
if ((d->d_type == DT_REG && !strcmp(d->d_name, "dev")))
if ((dtype == DT_REG && !strcmp(d->d_name, "dev")))
if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
r = 0;
break;
}
}
if (closedir(dr))

View File

@@ -55,6 +55,7 @@ static const device_info_t device_info[] = {
{"drbd", 16}, /* Distributed Replicated Block Device */
{"power2", 16}, /* EMC Powerpath */
{"i2o_block", 16}, /* i2o Block Disk */
{"iseries/vd", 8}, /* iSeries disks */
{NULL, 0}
};

View File

@@ -29,8 +29,6 @@ LIB_SHARED = liblvm2format1.so
include $(top_srcdir)/make.tmpl
.PHONY: install
install: liblvm2format1.so
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/liblvm2format1.so.$(LIB_VERSION)

View File

@@ -24,6 +24,7 @@
#include "lvmcache.h"
#include "lvm1-label.h"
#include "format1.h"
#include "segtype.h"
#define FMT_LVM1_NAME "lvm1"
@@ -492,6 +493,17 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
return 1;
}
static int _segtype_supported (struct format_instance *fid,
struct segment_type *segtype)
{
if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
stack;
return 0;
}
return 1;
}
static struct metadata_area_ops _metadata_format1_ops = {
vg_read:_vg_read,
vg_write:_vg_write,
@@ -542,6 +554,7 @@ static struct format_handler _format1_ops = {
pv_write:_pv_write,
lv_setup:_lv_setup,
vg_setup:_vg_setup,
segtype_supported:_segtype_supported,
create_instance:_create_instance,
destroy_instance:_destroy_instance,
destroy:_destroy,
@@ -578,5 +591,7 @@ struct format_type *init_format(struct cmd_context *cmd)
return NULL;
}
log_very_verbose("Initialised format: %s", fmt->name);
return fmt;
}

View File

@@ -25,7 +25,7 @@
#include "lvm-string.h"
#include "filter.h"
#include "toolcontext.h"
#include "segtypes.h"
#include "segtype.h"
#include <time.h>

View File

@@ -20,7 +20,7 @@
#include "disk-rep.h"
#include "lv_alloc.h"
#include "display.h"
#include "segtypes.h"
#include "segtype.h"
/*
* After much thought I have decided it is easier,

View File

@@ -26,8 +26,6 @@ LIB_SHARED = liblvm2formatpool.so
include $(top_srcdir)/make.tmpl
.PHONY: install
install: liblvm2formatpool.so
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/liblvm2formatpool.so.$(LIB_VERSION)

View File

@@ -357,5 +357,7 @@ struct format_type *init_format(struct cmd_context *cmd)
return NULL;
}
log_very_verbose("Initialised format: %s", fmt->name);
return fmt;
}

View File

@@ -22,7 +22,7 @@
#include "lv_alloc.h"
#include "str_list.h"
#include "display.h"
#include "segtypes.h"
#include "segtype.h"
/* This file contains only imports at the moment... */
@@ -146,7 +146,7 @@ int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
}
pl->pv = pvl->pv;
pvl->mdas = NULL;
pvl->alloc_areas = NULL;
pvl->pe_ranges = NULL;
list_add(pvs, &pvl->list);
}

View File

@@ -20,7 +20,7 @@
#include "pool.h"
#include "display.h"
#include "lvm-string.h"
#include "segtypes.h"
#include "segtype.h"
#include "text_export.h"
#include <stdarg.h>

View File

@@ -1682,14 +1682,15 @@ struct format_type *create_text_format(struct cmd_context *cmd)
}
}
if (!(cn = find_config_node(cmd->cft->root, "metadata/disk_areas")))
return fmt;
for (cn = cn->child; cn; cn = cn->sib) {
if (!_get_config_disk_area(cmd, cn, &mda_lists->raws))
goto err;
if ((cn = find_config_node(cmd->cft->root, "metadata/disk_areas"))) {
for (cn = cn->child; cn; cn = cn->sib) {
if (!_get_config_disk_area(cmd, cn, &mda_lists->raws))
goto err;
}
}
log_very_verbose("Initialised format: %s", fmt->name);
return fmt;
err:

View File

@@ -22,7 +22,7 @@
#include "toolcontext.h"
#include "lvmcache.h"
#include "lv_alloc.h"
#include "segtypes.h"
#include "segtype.h"
#include "text_import.h"
typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,

View File

@@ -22,9 +22,7 @@ LIB_SHARED = liblvm2clusterlock.so
include $(top_srcdir)/make.tmpl
.PHONY: install
install: liblvm2clusterlock.so
install install_cluster: liblvm2clusterlock.so
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/liblvm2clusterlock.so.$(LIB_VERSION)
$(LN_S) -f liblvm2clusterlock.so.$(LIB_VERSION) \

View File

@@ -21,7 +21,7 @@
#include "toolcontext.h"
#include "lv_alloc.h"
#include "display.h"
#include "segtypes.h"
#include "segtype.h"
/*
* These functions adjust the pe counts in pv's
@@ -623,6 +623,16 @@ int lv_extend(struct format_instance *fid,
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (fid->fmt->ops->segtype_supported &&
!fid->fmt->ops->segtype_supported(fid, segtype)) {
log_error("Metadata format (%s) does not support required "
"LV segment type (%s).", fid->fmt->name,
segtype->name);
log_error("Consider changing the metadata format by running "
"vgconvert.");
return 0;
}
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count, alloc,
segtype, stripes, stripe_size, mirrors, mirrored_pv,
mirrored_pe, status)) {

View File

@@ -18,7 +18,7 @@
#include "toolcontext.h"
#include "lv_alloc.h"
#include "str_list.h"
#include "segtypes.h"
#include "segtype.h"
/*
* Attempt to merge two adjacent segments.
@@ -39,6 +39,9 @@ int lv_merge_segments(struct logical_volume *lv)
struct list *segh, *t;
struct lv_segment *current, *prev = NULL;
if (lv->status & LOCKED || lv->status & PVMOVE)
return 1;
list_iterate_safe(segh, t, &lv->segments) {
current = list_item(segh, struct lv_segment);
@@ -77,6 +80,7 @@ int lv_check_segments(struct logical_volume *lv)
/*
* Split the supplied segment at the supplied logical extent
* NB Use LE numbering that works across stripes PV1: 0,2,4 PV2: 1,3,5 etc.
*/
static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
uint32_t le)
@@ -85,6 +89,7 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
struct lv_segment *split_seg;
uint32_t s;
uint32_t offset = le - seg->le;
uint32_t area_offset;
if (!(seg->segtype->flags & SEG_CAN_SPLIT)) {
log_error("Unable to split the %s segment at LE %" PRIu32
@@ -107,8 +112,9 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
}
/* In case of a striped segment, the offset has to be / stripes */
area_offset = offset;
if (seg->segtype->flags & SEG_AREAS_STRIPED)
offset /= seg->area_count;
area_offset /= seg->area_count;
/* Adjust the PV mapping */
for (s = 0; s < seg->area_count; s++) {
@@ -116,12 +122,19 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
switch (seg->area[s].type) {
case AREA_LV:
split_seg->area[s].u.lv.le =
seg->area[s].u.lv.le + offset;
seg->area[s].u.lv.le + area_offset;
log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name,
seg->le, s, le, seg->area[s].u.lv.lv->name,
split_seg->area[s].u.lv.le);
break;
case AREA_PV:
split_seg->area[s].u.pv.pe =
seg->area[s].u.pv.pe + offset;
seg->area[s].u.pv.pe + area_offset;
log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
seg->le, s, le,
dev_name(seg->area[s].u.pv.pv->dev),
split_seg->area[s].u.pv.pe);
break;
default:
@@ -131,8 +144,13 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
}
}
split_seg->area_len = seg->area_len - offset;
seg->area_len = offset;
split_seg->area_len -= area_offset;
seg->area_len = area_offset;
split_seg->len -= offset;
seg->len = offset;
split_seg->le = seg->le + seg->len;
/* Add split off segment to the list _after_ the original one */
list_add_h(&seg->list, &split_seg->list);

View File

@@ -265,7 +265,7 @@ struct name_list {
char *name;
};
struct alloc_area {
struct pe_range {
struct list list;
uint32_t start; /* PEs */
uint32_t count; /* PEs */
@@ -275,7 +275,7 @@ struct pv_list {
struct list list;
struct physical_volume *pv;
struct list *mdas; /* Metadata areas */
struct list *alloc_areas; /* Areas we may allocate from */
struct list *pe_ranges; /* Ranges of PEs e.g. for allocation */
};
struct lv_list {
@@ -341,6 +341,12 @@ struct format_handler {
*/
int (*vg_setup) (struct format_instance * fi, struct volume_group * vg);
/*
* Check whether particular segment type is supported.
*/
int (*segtype_supported) (struct format_instance *fid,
struct segment_type *segtype);
/*
* Create format instance with a particular metadata area
*/
@@ -501,7 +507,7 @@ int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow);
*/
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
struct physical_volume *pv,
struct list *source_pvl,
struct logical_volume *lv,
struct list *allocatable_pvs,
struct list *lvs_changed);

View File

@@ -16,7 +16,7 @@
#include "lib.h"
#include "metadata.h"
#include "toolcontext.h"
#include "segtypes.h"
#include "segtype.h"
#include "display.h"
#include "activate.h"
@@ -26,7 +26,7 @@
*/
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
struct physical_volume *pv,
struct list *source_pvl,
struct logical_volume *lv,
struct list *allocatable_pvs,
struct list *lvs_changed)
@@ -34,9 +34,15 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
struct list *segh;
struct lv_segment *seg;
struct lv_list *lvl;
struct pv_list *pvl;
int lv_used = 0;
uint32_t s, start_le, extent_count = 0u;
struct segment_type *segtype;
struct pe_range *per;
uint32_t pe_start, pe_end, per_end, stripe_multiplier;
/* Only 1 PV may feature in source_pvl */
pvl = list_item(source_pvl->n, struct pv_list);
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "mirror"))) {
stack;
@@ -50,43 +56,113 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
return 0;
}
/* Split LV segments to match PE ranges */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV ||
seg->area[s].u.pv.pv->dev != pvl->pv->dev)
continue;
/* Do these PEs need moving? */
list_iterate_items(per, pvl->pe_ranges) {
pe_start = seg->area[s].u.pv.pe;
pe_end = pe_start + seg->area_len - 1;
per_end = per->start + per->count - 1;
/* No overlap? */
if ((pe_end < per->start) ||
(pe_start > per_end))
continue;
if (seg->segtype->flags & SEG_AREAS_STRIPED)
stripe_multiplier = seg->area_count;
else
stripe_multiplier = 1;
if ((per->start != pe_start &&
per->start > pe_start) &&
!lv_split_segment(lv, seg->le +
(per->start - pe_start) *
stripe_multiplier)) {
stack;
return 0;
}
if ((per_end != pe_end &&
per_end < pe_end) &&
!lv_split_segment(lv, seg->le +
(per_end - pe_start + 1) *
stripe_multiplier)) {
stack;
return 0;
}
}
}
}
/* Work through all segments on the supplied PV */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV ||
seg->area[s].u.pv.pv->dev != pv->dev)
seg->area[s].u.pv.pv->dev != pvl->pv->dev)
continue;
/* First time, add LV to list of LVs affected */
if (!lv_used) {
if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
log_error("lv_list alloc failed");
pe_start = seg->area[s].u.pv.pe;
/* Do these PEs need moving? */
list_iterate_items(per, pvl->pe_ranges) {
per_end = per->start + per->count - 1;
if ((pe_start < per->start) ||
(pe_start > per_end))
continue;
log_debug("Matched PE range %u-%u against "
"%s %u len %u", per->start, per_end,
dev_name(seg->area[s].u.pv.pv->dev),
seg->area[s].u.pv.pe, seg->area_len);
/* First time, add LV to list of LVs affected */
if (!lv_used) {
if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
log_error("lv_list alloc failed");
return 0;
}
lvl->lv = lv;
list_add(lvs_changed, &lvl->list);
lv_used = 1;
}
log_very_verbose("Moving %s:%u-%u of %s/%s",
dev_name(pvl->pv->dev),
seg->area[s].u.pv.pe,
seg->area[s].u.pv.pe +
seg->area_len - 1,
lv->vg->name, lv->name);
start_le = lv_mirr->le_count;
if (!lv_extend(lv->vg->fid, lv_mirr, segtype, 1,
seg->area_len, 0u, seg->area_len,
seg->area[s].u.pv.pv,
seg->area[s].u.pv.pe,
PVMOVE, allocatable_pvs,
lv->alloc)) {
log_error("Unable to allocate "
"temporary LV for pvmove.");
return 0;
}
lvl->lv = lv;
list_add(lvs_changed, &lvl->list);
lv_used = 1;
seg->area[s].type = AREA_LV;
seg->area[s].u.lv.lv = lv_mirr;
seg->area[s].u.lv.le = start_le;
extent_count += seg->area_len;
lv->status |= LOCKED;
break;
}
start_le = lv_mirr->le_count;
if (!lv_extend(lv->vg->fid, lv_mirr, segtype, 1,
seg->area_len, 0u, seg->area_len,
seg->area[s].u.pv.pv,
seg->area[s].u.pv.pe,
PVMOVE, allocatable_pvs,
lv->alloc)) {
log_error("Allocation for temporary "
"pvmove LV failed");
return 0;
}
seg->area[s].type = AREA_LV;
seg->area[s].u.lv.lv = lv_mirr;
seg->area[s].u.lv.le = start_le;
extent_count += seg->area_len;
lv->status |= LOCKED;
}
}
@@ -167,8 +243,12 @@ int remove_pvmove_mirrors(struct volume_group *vg,
lv1->status &= ~LOCKED;
}
}
if (!lv_merge_segments(lv1))
stack;
}
return 1;
}

View File

@@ -206,13 +206,13 @@ static int _create_areas(struct pool *mem, struct pv_map *pvm, uint32_t start,
static int _create_allocatable_areas(struct pool *mem, struct pv_map *pvm)
{
struct list *alloc_areas, *aah;
struct alloc_area *aa;
struct pe_range *aa;
alloc_areas = pvm->pvl->alloc_areas;
alloc_areas = pvm->pvl->pe_ranges;
if (alloc_areas) {
list_iterate(aah, alloc_areas) {
aa = list_item(aah, struct alloc_area);
aa = list_item(aah, struct pe_range);
if (!_create_areas(mem, pvm, aa->start, aa->count)) {
stack;
return 0;

View File

@@ -15,7 +15,7 @@
#include "lib.h"
#include "toolcontext.h"
#include "segtypes.h"
#include "segtype.h"
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
const char *str)

View File

@@ -85,4 +85,8 @@ struct segment_type *init_snapshot_segtype(struct cmd_context *cmd);
struct segment_type *init_mirrored_segtype(struct cmd_context *cmd);
#endif
#ifdef CRYPT_INTERNAL
struct segment_type *init_crypt_segtype(struct cmd_context *cmd);
#endif
#endif

View File

@@ -22,8 +22,6 @@ LIB_SHARED = liblvm2mirror.so
include $(top_srcdir)/make.tmpl
.PHONY: install
install: liblvm2mirror.so
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/liblvm2mirror.so.$(LIB_VERSION)

View File

@@ -18,7 +18,7 @@
#include "list.h"
#include "toolcontext.h"
#include "metadata.h"
#include "segtypes.h"
#include "segtype.h"
#include "display.h"
#include "text_export.h"
#include "text_import.h"
@@ -95,7 +95,7 @@ static int _text_export(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "mirror_count = %u", seg->area_count);
if (seg->status & PVMOVE)
out_size(f, (uint64_t) seg->extents_copied,
out_size(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
"extents_moved = %u", seg->extents_copied);
return out_areas(f, seg, "mirror");
@@ -130,6 +130,7 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
int mirror_status = MIRR_RUNNING;
int areas = seg->area_count;
int start_area = 0u;
uint32_t region_size, region_max;
if (!*target_state)
*target_state = _init_target(mem, cft);
@@ -143,7 +144,7 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
if (seg->extents_copied == seg->area_len) {
mirror_status = MIRR_COMPLETED;
start_area = 1;
} else if (*pvmove_mirror_count++) {
} else if ((*pvmove_mirror_count)++) {
mirror_status = MIRR_DISABLED;
areas = 1;
}
@@ -153,8 +154,20 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
*target = "linear";
} else {
*target = "mirror";
/* Find largest power of 2 region size unit we can use */
region_max = (1 << (ffs(seg->area_len) - 1)) *
seg->lv->vg->extent_size;
region_size = mirr_state->region_size;
if (region_max < region_size) {
region_size = region_max;
log_verbose("Using reduced mirror region size of %u sectors",
region_size);
}
if ((*pos = lvm_snprintf(params, paramsize, "core 1 %u %u ",
mirr_state->region_size, areas)) < 0) {
region_size, areas)) < 0) {
stack;
return -1;
}
@@ -162,7 +175,6 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
return compose_areas_line(dm, seg, params, paramsize, pos, start_area,
areas);
}
static int _target_percent(void **target_state, struct pool *mem,
@@ -188,8 +200,7 @@ static int _target_percent(void **target_state, struct pool *mem,
*total_denominator += denominator;
if (seg)
seg->extents_copied = mirr_state->region_size *
numerator / seg->lv->vg->extent_size;
seg->extents_copied = seg->area_len * numerator / denominator;
return 1;
}
@@ -247,5 +258,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
segtype->private = NULL;
segtype->flags = SEG_AREAS_MIRRORED;
log_very_verbose("Initialised segtype: %s", segtype->name);
return segtype;
}

View File

@@ -16,6 +16,7 @@
#include "lib.h"
#include "lvm-types.h"
#include "lvm-string.h"
#include "pool.h"
#include <ctype.h>
@@ -98,3 +99,107 @@ int split_words(char *buffer, unsigned max, char **argv)
return arg;
}
/*
* Device layer names are all of the form <vg>-<lv>-<layer>, any
* other hyphens that appear in these names are quoted with yet
* another hyphen. The top layer of any device has no layer
* name. eg, vg0-lvol0.
*/
static void _count_hyphens(const char *str, size_t *len, int *hyphens)
{
const char *ptr;
for (ptr = str; *ptr; ptr++, (*len)++)
if (*ptr == '-')
(*hyphens)++;
}
/*
* Copies a string, quoting hyphens with hyphens.
*/
static void _quote_hyphens(char **out, const char *src)
{
while (*src) {
if (*src == '-')
*(*out)++ = '-';
*(*out)++ = *src++;
}
}
/*
* <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
*/
char *build_dm_name(struct pool *mem, const char *vg,
const char *lv, const char *layer)
{
size_t len = 0;
int hyphens = 0;
char *r, *out;
_count_hyphens(vg, &len, &hyphens);
_count_hyphens(lv, &len, &hyphens);
if (layer && *layer)
_count_hyphens(layer, &len, &hyphens);
len += hyphens + 2;
if (!(r = pool_alloc(mem, len))) {
stack;
return NULL;
}
out = r;
_quote_hyphens(&out, vg);
*out++ = '-';
_quote_hyphens(&out, lv);
if (layer && *layer) {
*out++ = '-';
_quote_hyphens(&out, layer);
}
*out = '\0';
return r;
}
/*
* Remove hyphen quoting from a component of a name.
* NULL-terminates the component and returns start of next component.
*/
static char *_unquote(char *component)
{
char *c = component;
char *o = c;
while (*c) {
if (*(c + 1)) {
if (*c == '-') {
if (*(c + 1) == '-')
c++;
else
break;
}
}
*o = *c;
o++;
c++;
}
*o = '\0';
return (c + 1);
}
int split_dm_name(struct pool *mem, const char *dmname,
char **vgname, char **lvname, char **layer)
{
if (!(*vgname = pool_strdup(mem, dmname)))
return 0;
_unquote(*layer = _unquote(*lvname = _unquote(*vgname)));
return 1;
}

View File

@@ -19,6 +19,8 @@
#include <stdio.h>
#include <stdarg.h>
struct pool;
/*
* On error, up to glibc 2.0.6, snprintf returned -1 if buffer was too small;
* From glibc 2.1 it returns number of chars (excl. trailing null) that would
@@ -32,4 +34,10 @@ int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...);
int split_words(char *buffer, unsigned max, char **argv);
char *build_dm_name(struct pool *mem, const char *vg,
const char *lv, const char *layer);
int split_dm_name(struct pool *mem, const char *dmname,
char **vgname, char **lvname, char **layer);
#endif

View File

@@ -29,11 +29,13 @@ struct memblock {
};
static struct {
unsigned int blocks, mblocks;
unsigned block_serialno;/* Non-decreasing serialno of block */
unsigned blocks_allocated; /* Current number of blocks allocated */
unsigned blocks_max; /* Max no of concurrently-allocated blocks */
unsigned int bytes, mbytes;
} _mem_stats = {
0, 0, 0, 0};
0, 0, 0, 0, 0};
static struct memblock *_head = 0;
static struct memblock *_tail = 0;
@@ -65,7 +67,7 @@ void *malloc_aux(size_t s, const char *file, int line)
/* setup fields */
nb->magic = nb + 1;
nb->length = s;
nb->id = ++_mem_stats.blocks;
nb->id = ++_mem_stats.block_serialno;
nb->next = 0;
nb->prev = _tail;
@@ -89,8 +91,9 @@ void *malloc_aux(size_t s, const char *file, int line)
*ptr++ = (char) nb->id;
}
if (_mem_stats.blocks > _mem_stats.mblocks)
_mem_stats.mblocks = _mem_stats.blocks;
_mem_stats.blocks_allocated++;
if (_mem_stats.blocks_allocated > _mem_stats.blocks_max)
_mem_stats.blocks_max = _mem_stats.blocks_allocated;
_mem_stats.bytes += s;
if (_mem_stats.bytes > _mem_stats.mbytes)
@@ -140,8 +143,8 @@ void free_aux(void *p)
else
_tail = mb->prev;
assert(_mem_stats.blocks);
_mem_stats.blocks--;
assert(_mem_stats.blocks_allocated);
_mem_stats.blocks_allocated--;
_mem_stats.bytes -= mb->length;
/* free the memory */

View File

@@ -83,7 +83,7 @@ static void _append_block(struct pool *p, struct block *b)
static struct block *_new_block(size_t s, unsigned alignment)
{
static char *_oom = "Out of memory";
static const char *_oom = "Out of memory";
/* FIXME: I'm currently ignoring the alignment arg. */
size_t len = sizeof(struct block) + s;
@@ -180,10 +180,13 @@ int pool_grow_object(struct pool *p, const void *buffer, size_t delta)
if (p->object) {
memcpy(new->data, p->object->data, p->object->size);
dbg_free(p->object->data);
dbg_free(p->object);
}
p->object = new;
memcpy(new->data + size - delta, buffer, delta);
return 1;
}

View File

@@ -109,8 +109,8 @@ void pool_empty(struct pool *p)
for (c = p->chunk; c && c->prev; c = c->prev)
;
if (p->chunk)
pool_free(p, (char *) (p->chunk + 1));
if (c)
pool_free(p, (char *) (c + 1));
}
void pool_free(struct pool *p, void *ptr)

View File

@@ -17,6 +17,41 @@
#define _LVM_XLATE_H
#ifdef linux
# include <endian.h>
# include <byteswap.h>
#else
# include <machine/endian.h>
# define bswap_16(x) (((x) & 0x00ffU) << 8 | \
((x) & 0xff00U) >> 8)
# define bswap_32(x) (((x) & 0x000000ffU) << 24 | \
((x) & 0xff000000U) >> 24 | \
((x) & 0x0000ff00U) << 8 | \
((x) & 0x00ff0000U) >> 8)
# define bswap_64(x) (((x) & 0x00000000000000ffU) << 56 | \
((x) & 0xff00000000000000U) >> 56 | \
((x) & 0x000000000000ff00U) << 40 | \
((x) & 0x00ff000000000000U) >> 40 | \
((x) & 0x0000000000ff0000U) << 24 | \
((x) & 0x0000ff0000000000U) >> 24 | \
((x) & 0x00000000ff000000U) << 8 | \
((x) & 0x000000ff00000000U) >> 8)
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
# define xlate16(x) (x)
# define xlate32(x) (x)
# define xlate64(x) (x)
# define xlate16_be(x) bswap_16(x)
# define xlate32_be(x) bswap_32(x)
# define xlate64_be(x) bswap_64(x)
#elif BYTE_ORDER == BIG_ENDIAN
# define xlate16(x) bswap_16(x)
# define xlate32(x) bswap_32(x)
# define xlate64(x) bswap_64(x)
# define xlate16_be(x) (x)
# define xlate32_be(x) (x)
# define xlate64_be(x) (x)
#else
# include <asm/byteorder.h>
# define xlate16(x) __cpu_to_le16((x))
# define xlate32(x) __cpu_to_le32((x))
@@ -24,41 +59,6 @@
# define xlate16_be(x) __cpu_to_be16((x))
# define xlate32_be(x) __cpu_to_be32((x))
# define xlate64_be(x) __cpu_to_be64((x))
#else
# include <machine/endian.h>
# if !defined(BYTE_ORDER) || \
(BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)
# error "Undefined or unrecognised BYTE_ORDER";
# endif
# define __xlate16(x) (((x) & 0x00ffU) << 8 | \
((x) & 0xff00U) >> 8)
# define __xlate32(x) (((x) & 0x000000ffU) << 24 | \
((x) & 0xff000000U) >> 24 | \
((x) & 0x0000ff00U) << 8 | \
((x) & 0x00ff0000U) >> 8)
# define __xlate64(x) (((x) & 0x00000000000000ffU) << 56 | \
((x) & 0xff00000000000000U) >> 56 | \
((x) & 0x000000000000ff00U) << 40 | \
((x) & 0x00ff000000000000U) >> 40 | \
((x) & 0x0000000000ff0000U) << 24 | \
((x) & 0x0000ff0000000000U) >> 24 | \
((x) & 0x00000000ff000000U) << 8 | \
((x) & 0x000000ff00000000U) >> 8)
# if BYTE_ORDER == LITTLE_ENDIAN
# define xlate16(x) (x)
# define xlate32(x) (x)
# define xlate64(x) (x)
# define xlate16_be(x) __xlate16(x)
# define xlate32_be(x) __xlate32(x)
# define xlate64_be(x) __xlate64(x)
# else
# define xlate16(x) __xlate16(x)
# define xlate32(x) __xlate32(x)
# define xlate64(x) __xlate64(x)
# define xlate16_be(x) (x)
# define xlate32_be(x) (x)
# define xlate64_be(x) (x)
# endif
#endif
#endif

View File

@@ -23,6 +23,8 @@ FIELD(LVS, lv, STR, "LV", name, 4, string, "lv_name")
FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr")
FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major")
FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor")
FIELD(LVS, lv, STR, "KMaj", lvid, 4, lvkmaj, "lv_kernel_major")
FIELD(LVS, lv, STR, "KMin", lvid, 4, lvkmin, "lv_kernel_minor")
FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size")
FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count")
FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, "origin")
@@ -34,6 +36,7 @@ FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags")
FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt")
FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid")
FIELD(PVS, pv, NUM, "PSize", id, 5, pvsize, "pv_size")
FIELD(PVS, pv, NUM, "DevSize", dev, 7, devsize, "dev_size")
FIELD(PVS, pv, NUM, "PFree", id, 5, pvfree, "pv_free")
FIELD(PVS, pv, NUM, "Used", id, 4, pvused, "pv_used")
FIELD(PVS, pv, STR, "PV", dev, 10, dev_name, "pv_name")

View File

@@ -21,7 +21,7 @@
#include "lvm-string.h"
#include "display.h"
#include "activate.h"
#include "segtypes.h"
#include "segtype.h"
/*
* For macro use
@@ -259,6 +259,65 @@ static int _pvfmt_disp(struct report_handle *rh, struct field *field,
return _string_disp(rh, field, &pv->fmt->name);
}
static int _int_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const int value = *(const int *) data;
uint64_t *sortval;
char *repstr;
if (!(repstr = pool_zalloc(rh->mem, 13))) {
log_error("pool_alloc failed");
return 0;
}
if (!(sortval = pool_alloc(rh->mem, sizeof(int64_t)))) {
log_error("pool_alloc failed");
return 0;
}
if (lvm_snprintf(repstr, 12, "%d", value) < 0) {
log_error("int too big: %d", value);
return 0;
}
*sortval = (const uint64_t) value;
field->sort_value = sortval;
field->report_string = repstr;
return 1;
}
static int _lvkmaj_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lvinfo info;
uint64_t minusone = UINT64_C(-1);
if (lv_info(lv, &info) && info.exists)
return _int_disp(rh, field, &info.major);
else
return _int_disp(rh, field, &minusone);
return 1;
}
static int _lvkmin_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lvinfo info;
uint64_t minusone = UINT64_C(-1);
if (lv_info(lv, &info) && info.exists)
return _int_disp(rh, field, &info.minor);
else
return _int_disp(rh, field, &minusone);
return 1;
}
static int _lvstatus_disp(struct report_handle *rh, struct field *field,
const void *data)
{
@@ -586,6 +645,18 @@ static int _pvsize_disp(struct report_handle *rh, struct field *field,
return _size64_disp(rh, field, &size);
}
static int _devsize_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct device *dev = *(const struct device **) data;
uint64_t size;
if (!dev_get_size(dev, &size))
size = 0;
return _size64_disp(rh, field, &size);
}
static int _vgfree_disp(struct report_handle *rh, struct field *field,
const void *data)
{

View File

@@ -22,8 +22,6 @@ LIB_SHARED = liblvm2snapshot.so
include $(top_srcdir)/make.tmpl
.PHONY: install
install: liblvm2snapshot.so
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/liblvm2snapshot.so.$(LIB_VERSION)

View File

@@ -18,7 +18,7 @@
#include "list.h"
#include "toolcontext.h"
#include "metadata.h"
#include "segtypes.h"
#include "segtype.h"
#include "text_export.h"
#include "config.h"
#include "activate.h"
@@ -161,5 +161,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
segtype->private = NULL;
segtype->flags = SEG_SNAPSHOT;
log_very_verbose("Initialised segtype: %s", segtype->name);
return segtype;
}

View File

@@ -17,7 +17,7 @@
#include "pool.h"
#include "list.h"
#include "toolcontext.h"
#include "segtypes.h"
#include "segtype.h"
#include "display.h"
#include "text_export.h"
#include "text_import.h"
@@ -217,5 +217,7 @@ struct segment_type *init_striped_segtype(struct cmd_context *cmd)
segtype->flags =
SEG_CAN_SPLIT | SEG_AREAS_STRIPED | SEG_FORMAT1_SUPPORT;
log_very_verbose("Initialised segtype: %s", segtype->name);
return segtype;
}

View File

@@ -16,7 +16,7 @@
#include "pool.h"
#include "list.h"
#include "toolcontext.h"
#include "segtypes.h"
#include "segtype.h"
#include "display.h"
#include "text_export.h"
#include "text_import.h"
@@ -97,5 +97,7 @@ struct segment_type *init_zero_segtype(struct cmd_context *cmd)
segtype->private = NULL;
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
log_very_verbose("Initialised segtype: %s", segtype->name);
return segtype;
}

View File

@@ -99,20 +99,22 @@ DEPS = $(top_srcdir)/make.tmpl $(top_srcdir)/VERSION Makefile $(INC_LNS)
OBJECTS = $(SOURCES:%.c=%.o)
POTFILES = $(SOURCES:%.c=%.pot)
.PHONY: all install install_cluster pofile distclean clean
.PHONY: $(SUBDIRS) $(SUBDIRS.install) $(SUBDIRS.clean) $(SUBDIRS.distclean)
.PHONY: $(SUBDIRS.pofile) $(SUBDIRS.install_cluster)
SUBDIRS.install := $(SUBDIRS:=.install)
SUBDIRS.install_cluster := $(SUBDIRS:=.install_cluster)
SUBDIRS.pofile := $(SUBDIRS:=.pofile)
SUBDIRS.clean := $(SUBDIRS:=.clean)
SUBDIRS.distclean := $(SUBDIRS:=.distclean)
.PHONY: all install pofile distclean clean
.PHONY: $(SUBDIRS) $(SUBDIRS.install) $(SUBDIRS.clean) $(SUBDIRS.distclean)
.PHONY: $(SUBDIRS.pofile)
TARGETS += $(LIB_SHARED) $(LIB_STATIC)
all: $(SUBDIRS) $(TARGETS)
install: all $(SUBDIRS.install)
install_cluster: all $(SUBDIRS.install_cluster)
$(SUBDIRS):
$(MAKE) -C $@
@@ -120,6 +122,9 @@ $(SUBDIRS):
$(SUBDIRS.install): $(SUBDIRS)
$(MAKE) -C $(@:.install=) install
$(SUBDIRS.install_cluster): $(SUBDIRS)
$(MAKE) -C $(@:.install_cluster=) install_cluster
$(SUBDIRS.clean):
-$(MAKE) -C $(@:.clean=) clean

View File

@@ -24,11 +24,16 @@ MAN8=lvchange.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 lvmchange.8 \
vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 vgimport.8 \
vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \
vgs.8 vgscan.8 vgsplit.8
MAN8CLUSTER=clvmd.8
MAN5DIR=${mandir}/man5
MAN8DIR=${mandir}/man8
include $(top_srcdir)/make.tmpl
ifeq ("@CLVMD@", "yes")
install: install_cluster
endif
install:
@echo "Installing $(MAN8) in $(MAN8DIR)"
@for f in $(MAN8); \
@@ -43,3 +48,11 @@ install:
$(RM) $(MAN5DIR)/$$f; \
@INSTALL@ -D $(OWNER) $(GROUP) -m 444 $$f $(MAN5DIR)/$$f; \
done
install_cluster:
@echo "Installing $(MAN8CLUSTER) in $(MAN8DIR)"
@for f in $(MAN8CLUSTER); \
do \
$(RM) $(MAN8DIR)/$$f; \
@INSTALL@ -D $(OWNER) $(GROUP) -m 444 $$f $(MAN8DIR)/$$f; \
done

28
man/clvmd.8 Normal file
View File

@@ -0,0 +1,28 @@
.TH CLVMD 8 "LVM TOOLS" "Red Hat Inc" \" -*- nroff -*-
.SH NAME
clvmd \- cluster LVM daemon
.SH SYNOPSIS
.B clvmd
[\-d] [\-h]
[\-t <timeout>]
[\-V]
.SH DESCRIPTION
clvmd is the daemon that distributes LVM metadata updates around a cluster.
It must be running on all nodes in the cluster and will give an error
if a node in the cluster does not have this daemon running.
.SH OPTIONS
.TP
.I \-d
Runs in the foreground and prints debugging information (if compiled in) to
stderr. By default, clvmd will fork into the background when invoked.
.TP
.I \-t <timeout>
Specifies the timeout for commands to run around the cluster. This should not
be so small that commands with many disk updates to do will fail, so you
may need to increase this on systems with very large disk farms.
The default is 30 seconds.
.TP
.I \-V
Display the version of the cluster LVM daemon.
.SH SEE ALSO
.BR lvm (8)

View File

@@ -44,8 +44,9 @@ Change access permission to read-only or read/write.
Change read ahead sector count per logical between 2 and 120.
Not used by device-mapper.
.SH Examples
"lvchange -x n vg00/lvol1" prevents the allocation of any physical
extents on logical volume lvol1 in volume group vg00.
"lvchange -p r vg00/lvol1" changes the permission on
volume lvol1 in volume group vg00 to be read-only.
.SH SEE ALSO
.BR lvm (8),
.BR lvcreate (8)

View File

@@ -3,10 +3,10 @@
pvmove \- move physical extents
.SH SYNOPSIS
.B pvmove
[\-\-abort]
[\-\-abort] [\-\-background]
[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
[\-n/\-\-name LogicalVolume]
[SourcePhysicalVolume [DestinationPhysicalVolume[:PE[-PE]...]...]]
[SourcePhysicalVolume[:PE[-PE]...] [DestinationPhysicalVolume[:PE[-PE]...]...]]
.SH DESCRIPTION
.B pvmove
allows you to move the allocated physical extents (PEs) on
@@ -23,13 +23,56 @@ is specifed, the normal allocation rules for the volume group are used.
If \fBpvmove\fP gets interrupted for any reason (e.g. the machine crashes)
then run \fBpvmove\fP again without any PhysicalVolume arguments to
continue with any moves that were in progress or use \fBpvmove --abort\fP to
abort them.
restart any moves that were in progress from the last checkpoint.
Alternatively use \fBpvmove --abort\fP at any time to abort them
at the last checkpoint.
You can run more than one pvmove at once provided they are moving data
off different SourcePhysicalVolumes, but additional pvmoves will ignore
any logical volumes already in the process of being changed, so some
data might not get moved.
\fBpvmove\fP works as follows:
1. A temporary 'pvmove' logical volume is created to store
details of all the data movements required.
2. Every logical volume in the volume group is searched
for contiguous data that need moving
according to the command line arguments.
For each piece of data found, a new segment is added to the end of the
pvmove LV.
This segment takes the form of a temporary mirror to copy the data
from the original location to a newly-allocated location.
The original LV is updated to use the new temporary mirror segment
in the pvmove LV instead of accessing the data directly.
3. The volume group metadata is updated on disk.
4. The first segment of the pvmove logical volume is activated and starts
to mirror the first part of the data. Only one segment is mirrored at once
as this is usually more efficient.
5. A daemon repeatedly checks progress at the specified time interval.
When it detects that the first temporary mirror is in-sync,
it breaks that mirror so that only the new location for that data gets used
and writes a checkpoint into the volume group metadata on disk.
Then it activates the mirror for the next segment of the pvmove LV.
6. When there are no more segments left to be mirrored,
the temporary logical volume is removed and the volume group metadata
is updated so that the logical volumes reflect the new data locations.
Note that this new process cannot support the original LVM1
type of on-disk metadata. Metadata can be converted using \fBvgconvert\fP(8).
.SH OPTIONS
.TP
.I \-\-abort
Abort any moves currently in progress.
Abort any moves in progress.
.TP
.I \-\-background
Run the daemon in the background.
.TP
.I \-i, \-\-interval Seconds
Report progress as a percentage at regular intervals.
@@ -50,4 +93,4 @@ runtime information, use:
\ pvmove -v /dev/hda4
.SH SEE ALSO
.BR lvm (8)
.BR lvm (8), vgconvert (8)

3371
po/lvm2.po

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@ endif
SOURCES =\
archiver.c \
dumpconfig.c \
formats.c \
lvchange.c \
lvcreate.c \
lvdisplay.c \
@@ -43,6 +44,7 @@ SOURCES =\
pvremove.c \
pvscan.c \
reporter.c \
segtypes.c \
toollib.c \
vgcfgbackup.c \
vgcfgrestore.c \
@@ -107,7 +109,7 @@ liblvm2cmd.so: liblvm2cmd.a $(LDDEPS)
.commands: commands.h cmdnames.h Makefile
$(CC) -E -P cmdnames.h 2> /dev/null | \
egrep -v '^ *(|#.*|dumpconfig|help|pvdata|version) *$$' > .commands
egrep -v '^ *(|#.*|dumpconfig|formats|help|pvdata|segtypes|version) *$$' > .commands
.PHONY: install_cmdlib_dynamic install_cmdlib_static \
install_tools_dynamic install_tools_static

View File

@@ -32,6 +32,10 @@ xx(dumpconfig,
"Dump active configuration",
"dumpconfig <filename>\n")
xx(formats,
"List available metadata formats",
"formats\n")
xx(help,
"Display help for commands",
"help <command>" "\n")
@@ -428,6 +432,7 @@ xx(pvmove,
"pvmove " "\n"
"\t[--abort]\n"
"\t[-A|--autobackup {y|n}]\n"
"\t[--alloc AllocationType]\n"
"\t[-b|--background]\n"
"\t[-d|--debug]\n "
"\t[-f|--force]\n"
@@ -438,12 +443,11 @@ xx(pvmove,
"\t[--version]\n"
"\t[{-n|--name} LogicalVolume]\n"
/* "\t[{-n|--name} LogicalVolume[:LogicalExtent[-LogicalExtent]...]]\n" */
"\tSourcePhysicalVolume\n"
/* "\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n" */
"\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n"
"\t[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n",
abort_ARG, autobackup_ARG, background_ARG, force_ARG, interval_ARG, name_ARG,
test_ARG)
abort_ARG, alloc_ARG, autobackup_ARG, background_ARG, force_ARG,
interval_ARG, name_ARG, test_ARG)
xx(pvremove,
"Remove LVM label(s) from physical volume(s)",
@@ -451,7 +455,6 @@ xx(pvremove,
"\t[-d|--debug]" "\n"
"\t[-f[f]|--force [--force]] " "\n"
"\t[-h|-?|--help] " "\n"
"\t[-y|--yes]" "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[-y|--yes]" "\n"
@@ -514,6 +517,10 @@ xx(pvscan,
exported_ARG, ignorelockingfailure_ARG, novolumegroup_ARG, partial_ARG,
short_ARG, uuid_ARG)
xx(segtypes,
"List available segment types",
"segtypes\n")
xx(vgcfgbackup,
"Backup volume group configuration(s)",
"vgcfgbackup " "\n"

23
tools/formats.c Normal file
View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tools.h"
int formats(struct cmd_context *cmd, int argc, char **argv)
{
display_formats(cmd);
return ECMD_PROCESSED;
}

View File

@@ -418,7 +418,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
*/
if (lp->pv_count) {
if (!(pvh = create_pv_list(cmd->mem, vg,
lp->pv_count, lp->pvs))) {
lp->pv_count, lp->pvs, 1))) {
stack;
return 0;
}

View File

@@ -351,7 +351,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
if (lp->argc)
log_print("Ignoring PVs on command line when reducing");
} else if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc,
lp->argv) : &vg->pvs)) {
lp->argv, 1) : &vg->pvs)) {
stack;
return ECMD_FAILED;
}

View File

@@ -149,7 +149,8 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
DEFAULT_PVMETADATACOPIES);
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
log_error("%s: Couldn't find device.", pv_name);
log_error("%s: Couldn't find device. Check your filters?",
pv_name);
goto error;
}

View File

@@ -15,6 +15,7 @@
#include "tools.h"
#include "polldaemon.h"
#include "display.h"
/* Allow /dev/vgname/lvname, vgname/lvname or lvname */
static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
@@ -85,14 +86,15 @@ static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname)
/* Create list of PVs for allocation of replacement extents */
static struct list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
char **argv, struct volume_group *vg,
struct physical_volume *pv)
struct physical_volume *pv,
alloc_policy_t alloc)
{
struct list *allocatable_pvs, *pvht, *pvh;
struct pv_list *pvl;
if (argc) {
if (!(allocatable_pvs = create_pv_list(cmd->mem, vg, argc,
argv))) {
argv, 1))) {
stack;
return NULL;
}
@@ -103,13 +105,18 @@ static struct list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
}
}
/* Don't allocate onto the PV we're clearing! */
/* Remove PV if full */
list_iterate_safe(pvh, pvht, allocatable_pvs) {
pvl = list_item(pvh, struct pv_list);
if ((pvl->pv->dev == pv->dev) ||
(pvl->pv->pe_count == pvl->pv->pe_alloc_count))
list_del(&pvl->list);
/* Don't allocate onto the PV we're clearing! */
if ((alloc != ALLOC_ANYWHERE) && (pvl->pv->dev == pv->dev)) {
list_del(&pvl->list);
continue;
}
/* Remove PV if full */
if ((pvl->pv->pe_count == pvl->pv->pe_alloc_count))
list_del(&pvl->list);
}
if (list_empty(allocatable_pvs)) {
@@ -123,15 +130,17 @@ static struct list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
/* Create new LV with mirror segments for the required copies */
static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
struct volume_group *vg,
struct physical_volume *pv,
struct list *source_pvl,
const char *lv_name,
struct list *allocatable_pvs,
alloc_policy_t alloc,
struct list **lvs_changed)
{
struct logical_volume *lv_mirr, *lv;
struct lv_list *lvl;
/* FIXME Cope with non-contiguous => splitting existing segments */
/* FIXME Pass 'alloc' down to lv_extend */
if (!(lv_mirr = lv_create_empty(vg->fid, NULL, "pvmove%d",
LVM_READ | LVM_WRITE,
ALLOC_CONTIGUOUS, vg))) {
@@ -165,7 +174,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
log_print("Skipping locked LV %s", lv->name);
continue;
}
if (!insert_pvmove_mirrors(cmd, lv_mirr, pv, lv,
if (!insert_pvmove_mirrors(cmd, lv_mirr, source_pvl, lv,
allocatable_pvs, *lvs_changed)) {
stack;
return NULL;
@@ -222,8 +231,10 @@ static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
/* Only the first mirror segment gets activated as a mirror */
if (first_time) {
if (!activate_lv(cmd, lv_mirr->lvid.s)) {
log_error("ABORTING: Temporary mirror activation "
"failed. Run pvmove --abort.");
if (!test_mode())
log_error("ABORTING: Temporary mirror "
"activation failed. "
"Run pvmove --abort.");
/* FIXME Resume using *original* metadata here! */
resume_lvs(cmd, lvs_changed);
return 0;
@@ -248,13 +259,20 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
int argc, char **argv)
{
const char *lv_name = NULL;
char *pv_name_arg;
struct volume_group *vg;
struct list *source_pvl;
struct list *allocatable_pvs;
alloc_policy_t alloc;
struct list *lvs_changed;
struct physical_volume *pv;
struct logical_volume *lv_mirr;
int first_time = 1;
pv_name_arg = argv[0];
argc--;
argv++;
/* Find PV (in VG) */
if (!(pv = find_pv_by_name(cmd, pv_name))) {
stack;
@@ -299,10 +317,22 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
first_time = 0;
} else {
/* Determine PE ranges to be moved */
if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
&pv_name_arg, 0))) {
stack;
unlock_vg(cmd, pv->vg_name);
return ECMD_FAILED;
}
alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG,
ALLOC_INHERIT);
if (alloc == ALLOC_INHERIT)
alloc = vg->alloc;
/* Get PVs we can use for allocation */
if (!(allocatable_pvs = _get_allocatable_pvs(cmd, argc, argv,
vg, pv))) {
vg, pv, alloc))) {
stack;
unlock_vg(cmd, pv->vg_name);
return ECMD_FAILED;
@@ -314,8 +344,8 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
return ECMD_FAILED;
}
if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, pv, lv_name,
allocatable_pvs,
if (!(lv_mirr = _set_up_pvmove_lv(cmd, vg, source_pvl, lv_name,
allocatable_pvs, alloc,
&lvs_changed))) {
stack;
unlock_vg(cmd, pv->vg_name);
@@ -459,12 +489,21 @@ int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
int pvmove(struct cmd_context *cmd, int argc, char **argv)
{
char *pv_name = NULL;
char *colon;
int ret;
if (argc) {
pv_name = argv[0];
argc--;
argv++;
/* Drop any PE lists from PV name */
if ((colon = strchr(pv_name, ':'))) {
if (!(pv_name = pool_strndup(cmd->mem, pv_name,
(unsigned) (colon -
pv_name)))) {
log_error("Failed to clone PV name");
return 0;
}
}
if (!arg_count(cmd, abort_ARG) &&
(ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
@@ -472,6 +511,7 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv)
stack;
return ret;
}
}
return pvmove_poll(cmd, pv_name,

View File

@@ -81,7 +81,8 @@ static int pvremove_single(struct cmd_context *cmd, const char *pv_name,
goto error;
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
log_error("%s: Couldn't find device.", pv_name);
log_error("%s: Couldn't find device. Check your filters?",
pv_name);
goto error;
}

23
tools/segtypes.c Normal file
View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tools.h"
int segtypes(struct cmd_context *cmd, int argc, char **argv)
{
display_segtypes(cmd);
return ECMD_PROCESSED;
}

View File

@@ -694,40 +694,40 @@ char *default_vgname(struct cmd_context *cmd)
return pool_strdup(cmd->mem, vg_path);
}
static int _add_alloc_area(struct pool *mem, struct list *alloc_areas,
uint32_t start, uint32_t count)
static int _add_pe_range(struct pool *mem, struct list *pe_ranges,
uint32_t start, uint32_t count)
{
struct alloc_area *aa;
struct pe_range *per;
log_debug("Adding alloc area: start PE %" PRIu32 " length %" PRIu32,
log_debug("Adding PE range: start PE %" PRIu32 " length %" PRIu32,
start, count);
/* Ensure no overlap with existing areas */
list_iterate_items(aa, alloc_areas) {
if (((start < aa->start) && (start + count - 1 >= aa->start)) ||
((start >= aa->start) &&
(aa->start + aa->count - 1) >= start)) {
list_iterate_items(per, pe_ranges) {
if (((start < per->start) && (start + count - 1 >= per->start))
|| ((start >= per->start) &&
(per->start + per->count - 1) >= start)) {
log_error("Overlapping PE ranges detected (%" PRIu32
"-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")",
start, start + count - 1, aa->start,
aa->start + aa->count - 1);
start, start + count - 1, per->start,
per->start + per->count - 1);
return 0;
}
}
if (!(aa = pool_alloc(mem, sizeof(*aa)))) {
if (!(per = pool_alloc(mem, sizeof(*per)))) {
log_error("Allocation of list failed");
return 0;
}
aa->start = start;
aa->count = count;
list_add(alloc_areas, &aa->list);
per->start = start;
per->count = count;
list_add(pe_ranges, &per->list);
return 1;
}
static int _parse_pes(struct pool *mem, char *c, struct list *alloc_areas,
static int _parse_pes(struct pool *mem, char *c, struct list *pe_ranges,
uint32_t size)
{
char *endptr;
@@ -735,7 +735,7 @@ static int _parse_pes(struct pool *mem, char *c, struct list *alloc_areas,
/* Default to whole PV */
if (!c) {
if (!_add_alloc_area(mem, alloc_areas, UINT32_C(0), size)) {
if (!_add_pe_range(mem, pe_ranges, UINT32_C(0), size)) {
stack;
return 0;
}
@@ -785,7 +785,7 @@ static int _parse_pes(struct pool *mem, char *c, struct list *alloc_areas,
return 0;
}
if (!_add_alloc_area(mem, alloc_areas, start, end - start + 1)) {
if (!_add_pe_range(mem, pe_ranges, start, end - start + 1)) {
stack;
return 0;
}
@@ -800,19 +800,20 @@ static int _parse_pes(struct pool *mem, char *c, struct list *alloc_areas,
}
static void _create_pv_entry(struct pool *mem, struct pv_list *pvl,
char *colon, struct list *r)
char *colon, int allocatable_only, struct list *r)
{
const char *pvname;
struct pv_list *new_pvl;
struct list *alloc_areas;
struct list *pe_ranges;
pvname = dev_name(pvl->pv->dev);
if (!(pvl->pv->status & ALLOCATABLE_PV)) {
if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
log_error("Physical volume %s not allocatable", pvname);
return;
}
if (pvl->pv->pe_count == pvl->pv->pe_alloc_count) {
if (allocatable_only &&
(pvl->pv->pe_count == pvl->pv->pe_alloc_count)) {
log_err("No free extents on physical volume \"%s\"", pvname);
return;
}
@@ -824,24 +825,24 @@ static void _create_pv_entry(struct pool *mem, struct pv_list *pvl,
memcpy(new_pvl, pvl, sizeof(*new_pvl));
if (!(alloc_areas = pool_alloc(mem, sizeof(*alloc_areas)))) {
log_error("Allocation of alloc_areas list failed");
if (!(pe_ranges = pool_alloc(mem, sizeof(*pe_ranges)))) {
log_error("Allocation of pe_ranges list failed");
return;
}
list_init(alloc_areas);
list_init(pe_ranges);
/* Specify which physical extents may be used for allocation */
if (!_parse_pes(mem, colon, alloc_areas, pvl->pv->pe_count)) {
/* Determine selected physical extents */
if (!_parse_pes(mem, colon, pe_ranges, pvl->pv->pe_count)) {
stack;
return;
}
new_pvl->alloc_areas = alloc_areas;
new_pvl->pe_ranges = pe_ranges;
list_add(r, &new_pvl->list);
}
struct list *create_pv_list(struct pool *mem,
struct volume_group *vg, int argc, char **argv)
struct list *create_pv_list(struct pool *mem, struct volume_group *vg, int argc,
char **argv, int allocatable_only)
{
struct list *r;
struct pv_list *pvl;
@@ -870,7 +871,8 @@ struct list *create_pv_list(struct pool *mem,
list_iterate_items(pvl, &vg->pvs) {
if (str_list_match_item(&pvl->pv->tags,
tagname)) {
_create_pv_entry(mem, pvl, NULL, r);
_create_pv_entry(mem, pvl, NULL,
allocatable_only, r);
}
}
continue;
@@ -892,7 +894,7 @@ struct list *create_pv_list(struct pool *mem,
"Volume Group \"%s\"", pvname, vg->name);
return NULL;
}
_create_pv_entry(mem, pvl, colon, r);
_create_pv_entry(mem, pvl, colon, allocatable_only, r);
}
if (list_empty(r))

View File

@@ -74,8 +74,8 @@ const char *extract_vgname(struct cmd_context *cmd, const char *lv_name);
* Builds a list of pv's from the names in argv. Used in
* lvcreate/extend.
*/
struct list *create_pv_list(struct pool *mem,
struct volume_group *vg, int argc, char **argv);
struct list *create_pv_list(struct pool *mem, struct volume_group *vg, int argc,
char **argv, int allocatable_only);
struct list *clone_pv_list(struct pool *mem, struct list *pvs);

View File

@@ -43,7 +43,7 @@
#include "lvm-file.h"
#include "lvm-string.h"
#include "pool.h"
#include "segtypes.h"
#include "segtype.h"
#include "str_list.h"
#include "toolcontext.h"
#include "toollib.h"