mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-27 05:44:18 +03:00
Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
34d9b5e3d7 | ||
|
3bf5189d86 | ||
|
12e5b0681b | ||
|
8c0285d608 | ||
|
36558fa3b8 | ||
|
235f940cde | ||
|
803d61fcbc | ||
|
ffbd7d8de4 | ||
|
4ed924d7c7 | ||
|
798dc9948b | ||
|
13515f7ee4 | ||
|
ef80824c26 | ||
|
c8503fd65e | ||
|
b3c454fb1c | ||
|
1d7723e873 | ||
|
77100b2365 | ||
|
259a788134 | ||
|
39511455cb | ||
|
b04c16178e | ||
|
49a959c06e | ||
|
096a8932b4 | ||
|
e39e66df93 | ||
|
513633f49a | ||
|
eb3740daaf | ||
|
f7947b148a | ||
|
9a2a702f3f | ||
|
c65d95bf29 | ||
|
753a5edc4f | ||
|
0b3f853c2d | ||
|
3527fcf1d5 | ||
|
4544a89c7a | ||
|
ffeae9005e | ||
|
47217bcfb7 | ||
|
80ff58b57a | ||
|
d15dd368f1 | ||
|
8a2ec32bd8 |
42
WHATS_NEW
42
WHATS_NEW
@@ -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
|
||||
=============================
|
||||
|
@@ -44,3 +44,6 @@ install_clvmd: $(TARGETS)
|
||||
$(sbindir)/clvmd
|
||||
|
||||
install: $(INSTALL_TARGETS)
|
||||
|
||||
install_cluster: $(INSTALL_TARGETS)
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
||||
|
@@ -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 \
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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))
|
||||
|
@@ -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}
|
||||
};
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@
|
||||
#include "lvm-string.h"
|
||||
#include "filter.h"
|
||||
#include "toolcontext.h"
|
||||
#include "segtypes.h"
|
||||
#include "segtype.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -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:
|
||||
|
@@ -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,
|
||||
|
@@ -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) \
|
||||
|
@@ -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)) {
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
@@ -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
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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")
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
13
make.tmpl.in
13
make.tmpl.in
@@ -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
|
||||
|
||||
|
@@ -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
28
man/clvmd.8
Normal 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)
|
@@ -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)
|
||||
|
55
man/pvmove.8
55
man/pvmove.8
@@ -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
3371
po/lvm2.po
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
@@ -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
23
tools/formats.c
Normal 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;
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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
23
tools/segtypes.c
Normal 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;
|
||||
}
|
@@ -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))
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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"
|
||||
|
Reference in New Issue
Block a user