mirror of
git://sourceware.org/git/lvm2.git
synced 2026-01-06 08:32:48 +03:00
Compare commits
61 Commits
old-dm_v1_
...
dm_v1_01_0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
893ec9a302 | ||
|
|
05f65c38e6 | ||
|
|
2e9d062ec0 | ||
|
|
6b0b394e61 | ||
|
|
25621396c9 | ||
|
|
82aa0271f3 | ||
|
|
653cab13f8 | ||
|
|
b526f86b49 | ||
|
|
53c0f00888 | ||
|
|
f0c4d9de40 | ||
|
|
03ef8cec83 | ||
|
|
85f2a2e8c2 | ||
|
|
584b3e6642 | ||
|
|
39b7ef841d | ||
|
|
aa16a9098d | ||
|
|
7b8c2707bc | ||
|
|
60e26a31a7 | ||
|
|
3473c25c14 | ||
|
|
e52f022026 | ||
|
|
b1a7df8e43 | ||
|
|
0fd2479b7c | ||
|
|
273857f914 | ||
|
|
a08b85dbc8 | ||
|
|
a0aedf299a | ||
|
|
3c61426844 | ||
|
|
786f228076 | ||
|
|
004da28792 | ||
|
|
6e2be6efb6 | ||
|
|
a994dfcfbc | ||
|
|
7a8ea2ac93 | ||
|
|
0da3965d19 | ||
|
|
885fd7bb46 | ||
|
|
08771f9c89 | ||
|
|
8be48195a5 | ||
|
|
98ce2d650e | ||
|
|
3af327116a | ||
|
|
b75434db93 | ||
|
|
04e912aacd | ||
|
|
d7be352f87 | ||
|
|
96be3ec22c | ||
|
|
32e7e0d790 | ||
|
|
becc320e62 | ||
|
|
7666ed57d1 | ||
|
|
5e61d0955e | ||
|
|
e8a4662ae7 | ||
|
|
a48da3bd3b | ||
|
|
5f1a5d7b99 | ||
|
|
3e28a9db8f | ||
|
|
ebf6071d77 | ||
|
|
47a35fb9fb | ||
|
|
48e88aba44 | ||
|
|
b85f99c140 | ||
|
|
0a5e0e1f71 | ||
|
|
85dc22ebb7 | ||
|
|
5c21526009 | ||
|
|
14dff1cefc | ||
|
|
39fbb844f9 | ||
|
|
ca4e0c973a | ||
|
|
ecb42bee80 | ||
|
|
674ed2a9f3 | ||
|
|
252daf9717 |
57
WHATS_NEW
57
WHATS_NEW
@@ -1,5 +1,57 @@
|
||||
Version 2.01.11 -
|
||||
==============================
|
||||
Version 2.01.15 -
|
||||
=================================
|
||||
Fix chunksize field in reports.
|
||||
Don't hide snapshots from default 'lvs' output.
|
||||
Add is_dm_major() for use in duplicate device detection in lvmcache_add().
|
||||
Really switch device number in lvmcache when it says it is doing so.
|
||||
Option for bitset memory allocation using malloc as well as pool.
|
||||
Don't assume exactly two mirrors when parsing mirror status.
|
||||
Suppress fsync() error message on filesystems that don't support it.
|
||||
Fix yes_no_prompt() error handling.
|
||||
Add lvm.conf comment warning against multiple filter lines.
|
||||
Tidy lvmconf.sh.
|
||||
Add format1 dev_write debug messages.
|
||||
Add clustered VG attribute to report.
|
||||
Move lvconvert parameters into struct lvconvert_params.
|
||||
Add clustered VG flag to LV lock requests.
|
||||
Change LV locking macros to take lv instead of lvid.
|
||||
Prepend 'cluster' activation parameter to mirror log when appropriate.
|
||||
Pass exclusive flag to lv_activate and on to target activation code.
|
||||
Prevent snapshot creation in a clustered VG for now.
|
||||
Factor out adjusted_mirror_region_size() and generate_log_name_format().
|
||||
Move compose_log_line() into mirror directory.
|
||||
Factor out _get_library_path().
|
||||
Don't kill idling clvmd threads.
|
||||
clvmd no longer takes out locks for non-clustered LVs.
|
||||
Recognise ATA over Ethernet (aoe) devices.
|
||||
|
||||
Version 2.01.14 - 4th August 2005
|
||||
=================================
|
||||
Fix lvconvert PV parameter in help string.
|
||||
Prevent snapshots getting activated in a clustered VG.
|
||||
Separate out _build_dev_string.
|
||||
Move zero_lv to toollib.
|
||||
Fix pool format handler to work with pv segment code.
|
||||
|
||||
Version 2.01.13 - 13th July 2005
|
||||
================================
|
||||
Fix pvmove segment splitting.
|
||||
Abstract vg_validate.
|
||||
Only make one attempt at contiguous allocation.
|
||||
Fix lvm1 format metadata read.
|
||||
Fix lvm1 format non-mirror lvcreate.
|
||||
|
||||
Version 2.01.12 - 14th June 2005
|
||||
================================
|
||||
Various allocation-related pvmove fixes.
|
||||
Log an error if clvmd can't resolve a host name got from CCS.
|
||||
Fix potential spin loop in clvmd.
|
||||
|
||||
Version 2.01.11 - 13th June 2005
|
||||
================================
|
||||
Added lvmconf.sh.
|
||||
Use matchpathcon mode parameter.
|
||||
Don't defer closing dead FDs in clvmd.
|
||||
Remove hard-coded 64k text metadata writing restriction.
|
||||
Make VG name restrictions consistent.
|
||||
Introduce lvconvert. So far only removes mirror images.
|
||||
@@ -36,7 +88,6 @@ Version 2.01.11 -
|
||||
lv_reduce tidying.
|
||||
Remove some unnecessary parameters.
|
||||
Introduce seg_is macros.
|
||||
Don't defer closing dead FDs in clvmd.
|
||||
|
||||
Version 2.01.10 - 3rd May 2005
|
||||
==============================
|
||||
|
||||
12
WHATS_NEW_DM
12
WHATS_NEW_DM
@@ -1,3 +1,15 @@
|
||||
Version 1.01.05 - 26 Sep 2005
|
||||
=============================
|
||||
Resync list.h with LVM2.
|
||||
Remember increased buffer size and use for subsequent calls.
|
||||
On 'buffer full' condition, double buffer size and repeat ioctl.
|
||||
Fix termination of getopt_long() option array.
|
||||
Report 'buffer full' condition with v4 ioctl as well as with v1.
|
||||
|
||||
Version 1.01.04 - 2 Aug 2005
|
||||
============================
|
||||
Fix dmsetup ls -j and status --target with empty table.
|
||||
|
||||
Version 1.01.03 - 13 Jun 2005
|
||||
=============================
|
||||
Use matchpathcon mode parameter.
|
||||
|
||||
@@ -109,7 +109,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
/* This is the biggie */
|
||||
lock_cmd = args[0];
|
||||
lock_cmd = args[0] & 0x3F;
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
status = do_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
@@ -161,7 +161,7 @@ static int lock_vg(struct local_client *client)
|
||||
client->bits.localsock.private = (void *)lock_hash;
|
||||
}
|
||||
|
||||
lock_cmd = args[0];
|
||||
lock_cmd = args[0] & 0x3F;
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||
|
||||
@@ -944,7 +944,13 @@ static int get_all_cluster_nodes()
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGLOG("node %s has clvm disabled\n", nodename);
|
||||
if (!clvmflag) {
|
||||
DEBUGLOG("node %s has clvm disabled\n", nodename);
|
||||
}
|
||||
else {
|
||||
DEBUGLOG("Cannot resolve host name %s\n", nodename);
|
||||
log_err("Cannot resolve host name %s\n", nodename);
|
||||
}
|
||||
}
|
||||
free(nodename);
|
||||
}
|
||||
|
||||
@@ -512,6 +512,10 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
FD_ZERO(&in);
|
||||
for (thisfd = &local_client_head; thisfd != NULL;
|
||||
thisfd = thisfd->next) {
|
||||
|
||||
if (thisfd->removeme)
|
||||
continue;
|
||||
|
||||
/* if the cluster is not quorate then don't listen for new requests */
|
||||
if ((thisfd->type != LOCAL_RENDEZVOUS &&
|
||||
thisfd->type != LOCAL_SOCK) || quorate)
|
||||
@@ -743,6 +747,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
|
||||
/* If the client went away in mid command then tidy up */
|
||||
if (thisfd->bits.localsock.in_progress) {
|
||||
pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
|
||||
pthread_mutex_lock(&thisfd->bits.localsock.mutex);
|
||||
thisfd->bits.localsock.state = POST_COMMAND;
|
||||
pthread_cond_signal(&thisfd->bits.localsock.cond);
|
||||
@@ -759,7 +764,6 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
thisfd->bits.localsock.state = PRE_COMMAND;
|
||||
pthread_cond_signal(&thisfd->bits.localsock.cond);
|
||||
pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
|
||||
pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
|
||||
|
||||
jstat =
|
||||
pthread_join(thisfd->bits.localsock.threadid,
|
||||
|
||||
@@ -168,11 +168,12 @@ int hold_unlock(char *resource)
|
||||
*/
|
||||
|
||||
/* Activate LV exclusive or non-exclusive */
|
||||
static int do_activate_lv(char *resource, int mode)
|
||||
static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
|
||||
{
|
||||
int oldmode;
|
||||
int status;
|
||||
int activate_lv;
|
||||
int exclusive = 0;
|
||||
struct lvinfo lvi;
|
||||
|
||||
/* Is it already open ? */
|
||||
@@ -189,13 +190,17 @@ static int do_activate_lv(char *resource, int mode)
|
||||
return 0; /* Success, we did nothing! */
|
||||
|
||||
/* Do we need to activate exclusively? */
|
||||
if (activate_lv == 2)
|
||||
if ((activate_lv == 2) || (mode == LKM_EXMODE)) {
|
||||
exclusive = 1;
|
||||
mode = LKM_EXMODE;
|
||||
}
|
||||
|
||||
/* OK, try to get the lock */
|
||||
status = hold_lock(resource, mode, LKF_NOQUEUE);
|
||||
if (status)
|
||||
return errno;
|
||||
/* Try to get the lock if it's a clustered volume group */
|
||||
if (lock_flags & LCK_CLUSTER_VG) {
|
||||
status = hold_lock(resource, mode, LKF_NOQUEUE);
|
||||
if (status)
|
||||
return errno;
|
||||
}
|
||||
|
||||
/* If it's suspended then resume it */
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
|
||||
@@ -206,7 +211,7 @@ static int do_activate_lv(char *resource, int mode)
|
||||
return EIO;
|
||||
|
||||
/* Now activate it */
|
||||
if (!lv_activate(cmd, resource))
|
||||
if (!lv_activate(cmd, resource, exclusive))
|
||||
return EIO;
|
||||
|
||||
return 0;
|
||||
@@ -255,14 +260,14 @@ static int do_suspend_lv(char *resource)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_deactivate_lv(char *resource)
|
||||
static int do_deactivate_lv(char *resource, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode;
|
||||
int status;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1) {
|
||||
if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_deactivate_lock, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
@@ -270,9 +275,11 @@ static int do_deactivate_lv(char *resource)
|
||||
if (!lv_deactivate(cmd, resource))
|
||||
return EIO;
|
||||
|
||||
status = hold_unlock(resource);
|
||||
if (status)
|
||||
return errno;
|
||||
if (lock_flags & LCK_CLUSTER_VG) {
|
||||
status = hold_unlock(resource);
|
||||
if (status)
|
||||
return errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -283,7 +290,7 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
|
||||
resource, command, lock_flags);
|
||||
|
||||
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||
@@ -296,7 +303,7 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
|
||||
switch (command) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, LKM_EXMODE);
|
||||
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
|
||||
break;
|
||||
|
||||
case LCK_LV_SUSPEND:
|
||||
@@ -309,11 +316,11 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
break;
|
||||
|
||||
case LCK_LV_ACTIVATE:
|
||||
status = do_activate_lv(resource, LKM_CRMODE);
|
||||
status = do_activate_lv(resource, lock_flags, LKM_CRMODE);
|
||||
break;
|
||||
|
||||
case LCK_LV_DEACTIVATE:
|
||||
status = do_deactivate_lv(resource);
|
||||
status = do_deactivate_lv(resource, lock_flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -433,23 +440,24 @@ static void drop_vg_locks()
|
||||
*/
|
||||
static void *get_initial_state()
|
||||
{
|
||||
char lv[64], vg[64], flags[25];
|
||||
char lv[64], vg[64], flags[25], vg_flags[25];
|
||||
char uuid[65];
|
||||
char line[255];
|
||||
FILE *lvs =
|
||||
popen
|
||||
("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr",
|
||||
("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
|
||||
"r");
|
||||
|
||||
if (!lvs)
|
||||
return NULL;
|
||||
|
||||
while (fgets(line, sizeof(line), lvs)) {
|
||||
if (sscanf(line, "%s %s %s\n", vg, lv, flags) == 3) {
|
||||
if (sscanf(line, "%s %s %s %s\n", vg, lv, flags, vg_flags) == 4) {
|
||||
|
||||
/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
|
||||
if (strlen(vg) == 38 && /* is is a valid UUID ? */
|
||||
(flags[4] == 'a' || flags[4] == 's')) { /* is it active or suspended? */
|
||||
(flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */
|
||||
vg_flags[5] == 'c') { /* is it clustered ? */
|
||||
/* Convert hyphen-separated UUIDs into one */
|
||||
memcpy(&uuid[0], &vg[0], 6);
|
||||
memcpy(&uuid[6], &vg[7], 4);
|
||||
|
||||
@@ -28,7 +28,7 @@ else
|
||||
LIB_SHARED = libdmeventdnoop.so
|
||||
endif
|
||||
|
||||
LDFLAGS += -ldl -ldevmapper -lpthread -lmultilog
|
||||
LDFLAGS += -ldl -ldevmapper -lmultilog
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
@@ -36,11 +36,11 @@ libdmeventdnoop.so: noop.o
|
||||
|
||||
dmevent: dmevent.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
|
||||
$(CC) -o $@ dmevent.o $(LDFLAGS) \
|
||||
-L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -ldmevent $(LIBS)
|
||||
-L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog $(LIBS)
|
||||
|
||||
dmeventd: dmeventd.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
|
||||
$(CC) -o $@ dmeventd.o $(LDFLAGS) \
|
||||
-L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -ldmevent $(LIBS)
|
||||
-L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -lpthread -ldmevent $(LIBS)
|
||||
|
||||
install: $(INSTALL_TYPE)
|
||||
|
||||
|
||||
@@ -26,12 +26,24 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
static enum event_type events = ALL_ERRORS; /* All until we can distinguish. */
|
||||
static char default_dso_name[] = "noop"; /* default DSO is noop */
|
||||
static int default_reg = 1; /* default action is register */
|
||||
static uint32_t timeout;
|
||||
|
||||
struct event_ops {
|
||||
int (*dm_register_for_event)(char *dso_name, char *device,
|
||||
enum event_type event_types);
|
||||
int (*dm_unregister_for_event)(char *dso_name, char *device,
|
||||
enum event_type event_types);
|
||||
int (*dm_get_registered_device)(char **dso_name, char **device,
|
||||
enum event_type *event_types, int next);
|
||||
int (*dm_set_event_timeout)(char *device, uint32_t time);
|
||||
int (*dm_get_event_timeout)(char *device, uint32_t *time);
|
||||
};
|
||||
|
||||
/* Display help. */
|
||||
static void print_usage(char *name)
|
||||
{
|
||||
@@ -102,8 +114,35 @@ static int parse_argv(int argc, char **argv, char **dso_name_arg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int lookup_symbol(void *dl, void **symbol, const char *name)
|
||||
{
|
||||
if ((*symbol = dlsym(dl, name)))
|
||||
return 1;
|
||||
|
||||
fprintf(stderr, "error looking up %s symbol: %s\n", name, dlerror());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lookup_symbols(void *dl, struct event_ops *e)
|
||||
{
|
||||
return lookup_symbol(dl, (void *) &e->dm_register_for_event,
|
||||
"dm_register_for_event") &&
|
||||
lookup_symbol(dl, (void *) &e->dm_unregister_for_event,
|
||||
"dm_unregister_for_event") &&
|
||||
lookup_symbol(dl, (void *) &e->dm_get_registered_device,
|
||||
"dm_get_registered_device") &&
|
||||
lookup_symbol(dl, (void *) &e->dm_set_event_timeout,
|
||||
"dm_set_event_timeout") &&
|
||||
lookup_symbol(dl, (void *) &e->dm_get_event_timeout,
|
||||
"dm_get_event_timeout");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *dl;
|
||||
struct event_ops e;
|
||||
int list = 0, next = 0, ret, reg = default_reg;
|
||||
char *device, *device_arg = NULL, *dso_name, *dso_name_arg = NULL;
|
||||
|
||||
@@ -128,15 +167,22 @@ int main(int argc, char **argv)
|
||||
multilog_add_type(standard, NULL);
|
||||
multilog_init_verbose(standard, _LOG_DEBUG);
|
||||
|
||||
if (!(dl = dlopen("libdmevent.so", RTLD_NOW))){
|
||||
fprintf(stderr, "Cannot dlopen libdmevent.so: %s\n", dlerror());
|
||||
goto out;
|
||||
}
|
||||
if (!(lookup_symbols(dl, &e)))
|
||||
goto out;
|
||||
if (list) {
|
||||
while (1) {
|
||||
if ((ret= dm_get_registered_device(&dso_name, &device,
|
||||
&events, next)))
|
||||
if ((ret= e.dm_get_registered_device(&dso_name,
|
||||
&device,
|
||||
&events, next)))
|
||||
break;
|
||||
printf("%s %s 0x%x", dso_name, device, events);
|
||||
if (events & TIMEOUT){
|
||||
if ((ret = dm_get_event_timeout(device,
|
||||
&timeout))) {
|
||||
if ((ret = e.dm_get_event_timeout(device,
|
||||
&timeout))) {
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
@@ -153,14 +199,14 @@ int main(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((ret = reg ? dm_register_for_event(dso_name, device, events) :
|
||||
dm_unregister_for_event(dso_name, device, events))) {
|
||||
if ((ret = reg ? e.dm_register_for_event(dso_name, device, events) :
|
||||
e.dm_unregister_for_event(dso_name, device, events))) {
|
||||
fprintf(stderr, "Failed to %sregister %s: %s\n",
|
||||
reg ? "": "un", device, strerror(-ret));
|
||||
ret = EXIT_FAILURE;
|
||||
} else {
|
||||
if (reg && (events & TIMEOUT) &&
|
||||
((ret = dm_set_event_timeout(device, timeout)))){
|
||||
((ret = e.dm_set_event_timeout(device, timeout)))){
|
||||
fprintf(stderr, "Failed to set timeout for %s: %s\n",
|
||||
device, strerror(-ret));
|
||||
ret = EXIT_FAILURE;
|
||||
|
||||
@@ -33,8 +33,12 @@ devices {
|
||||
# pattern, the device is accepted; otherwise if any name matches any 'r'
|
||||
# pattern it is rejected; otherwise it is accepted.
|
||||
|
||||
# Remember to run vgscan after you change this parameter to ensure
|
||||
# that the cache file gets regenerated (see below).
|
||||
# Don't have more than one filter line active at once: only one gets used.
|
||||
|
||||
# Run vgscan after you change this parameter to ensure that
|
||||
# the cache file gets regenerated (see below).
|
||||
# If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
|
||||
|
||||
|
||||
# By default we accept every block device:
|
||||
filter = [ "a/.*/" ]
|
||||
|
||||
@@ -130,11 +130,11 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -701,7 +701,8 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
||||
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
int exclusive, int filter)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
@@ -732,6 +733,9 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
||||
if (info.exists && !info.suspended)
|
||||
return 1;
|
||||
|
||||
if (exclusive)
|
||||
lv->status |= ACTIVATE_EXCL;
|
||||
|
||||
memlock_inc();
|
||||
r = _lv_activate_lv(lv);
|
||||
memlock_dec();
|
||||
@@ -741,15 +745,15 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
||||
}
|
||||
|
||||
/* Activate LV */
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||
{
|
||||
return _lv_activate(cmd, lvid_s, 0);
|
||||
return _lv_activate(cmd, lvid_s, exclusive, 0);
|
||||
}
|
||||
|
||||
/* Activate LV only if it passes filter */
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||
{
|
||||
return _lv_activate(cmd, lvid_s, 1);
|
||||
return _lv_activate(cmd, lvid_s, exclusive, 1);
|
||||
}
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
|
||||
@@ -46,8 +46,9 @@ int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive);
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int exclusive);
|
||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
||||
|
||||
@@ -727,51 +727,25 @@ static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int compose_log_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos, int areas,
|
||||
uint32_t region_size)
|
||||
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
|
||||
size_t bufsize, const char *desc)
|
||||
{
|
||||
int tw;
|
||||
char devbuf[10];
|
||||
char *name;
|
||||
struct dev_layer *dl;
|
||||
|
||||
if (!seg->log_lv)
|
||||
tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
|
||||
region_size, areas);
|
||||
else {
|
||||
if (!(name = build_dm_name(dm->mem, seg->log_lv->vg->name,
|
||||
seg->log_lv->name, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dl = hash_lookup(dm->layers, seg->log_lv->lvid.s))) {
|
||||
log_error("device layer %s missing from hash",
|
||||
seg->log_lv->lvid.s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_format_dev(devbuf, sizeof(devbuf), dl->info.major,
|
||||
dl->info.minor)) {
|
||||
log_error("Failed to format device number as dm "
|
||||
"target (%u,%u)",
|
||||
dl->info.major, dl->info.minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME add sync parm? */
|
||||
tw = lvm_snprintf(params, paramsize, "disk 2 %s %u %u ",
|
||||
devbuf, region_size, areas);
|
||||
if (!(dl = hash_lookup(dm->layers, dlid))) {
|
||||
log_error("%s device layer %s missing from hash",
|
||||
desc, dlid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tw < 0) {
|
||||
stack;
|
||||
return -1;
|
||||
if (!dm_format_dev(devbuf, bufsize, dl->info.major,
|
||||
dl->info.minor)) {
|
||||
log_error("Failed to format %s device number for %s as dm "
|
||||
"target (%u,%u)",
|
||||
desc, dlid, dl->info.major, dl->info.minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pos += tw;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -783,7 +757,6 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
int tw = 0;
|
||||
const char *trailing_space;
|
||||
uint64_t esize = seg->lv->vg->extent_size;
|
||||
struct dev_layer *dl;
|
||||
char devbuf[10];
|
||||
|
||||
for (s = start_area; s < areas; s++, *pos += tw) {
|
||||
@@ -803,25 +776,20 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
(seg_pv(seg, s)->pe_start +
|
||||
(esize * seg_pe(seg, s))),
|
||||
trailing_space);
|
||||
else {
|
||||
if (!(dl = hash_lookup(dm->layers,
|
||||
seg_lv(seg, s)->lvid.s))) {
|
||||
log_error("device layer %s missing from hash",
|
||||
seg_lv(seg, s)->lvid.s);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_format_dev
|
||||
(devbuf, sizeof(devbuf), dl->info.major,
|
||||
dl->info.minor)) {
|
||||
log_error
|
||||
("Failed to format device number as dm target (%u,%u)",
|
||||
dl->info.major, dl->info.minor);
|
||||
else if (seg_type(seg, s) == AREA_LV) {
|
||||
if (!build_dev_string(dm, seg_lv(seg, s)->lvid.s, devbuf,
|
||||
sizeof(devbuf), "LV")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
tw = lvm_snprintf(params + *pos, paramsize - *pos,
|
||||
"%s %" PRIu64 "%s", devbuf,
|
||||
esize * seg_le(seg, s),
|
||||
trailing_space);
|
||||
} else {
|
||||
log_error("Internal error: Unassigned area found in LV %s.",
|
||||
seg->lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tw < 0) {
|
||||
@@ -888,22 +856,14 @@ static int _populate_origin(struct dev_manager *dm,
|
||||
{
|
||||
char *real;
|
||||
char params[PATH_MAX + 32];
|
||||
struct dev_layer *dlr;
|
||||
|
||||
if (!(real = _build_dlid(dm->mem, dl->lv->lvid.s, "real"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dlr = hash_lookup(dm->layers, real))) {
|
||||
log_error("Couldn't find real device layer %s in hash", real);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_format_dev(params, sizeof(params), dlr->info.major,
|
||||
dlr->info.minor)) {
|
||||
log_error("Couldn't create origin device parameters for '%s'.",
|
||||
real);
|
||||
if (!build_dev_string(dm, real, params, sizeof(params), "origin")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -924,7 +884,6 @@ static int _populate_snapshot(struct dev_manager *dm,
|
||||
char *origin, *cow;
|
||||
char params[PATH_MAX * 2 + 32];
|
||||
struct lv_segment *snap_seg;
|
||||
struct dev_layer *dlo, *dlc;
|
||||
char devbufo[10], devbufc[10];
|
||||
uint64_t size;
|
||||
|
||||
@@ -944,28 +903,13 @@ static int _populate_snapshot(struct dev_manager *dm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dlo = hash_lookup(dm->layers, origin))) {
|
||||
log_error("Couldn't find origin device layer %s in hash",
|
||||
origin);
|
||||
if (!build_dev_string(dm, origin, devbufo, sizeof(devbufo), "origin")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dlc = hash_lookup(dm->layers, cow))) {
|
||||
log_error("Couldn't find cow device layer %s in hash", cow);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_format_dev(devbufo, sizeof(devbufo), dlo->info.major,
|
||||
dlo->info.minor)) {
|
||||
log_error("Couldn't create origin device parameters for '%s'.",
|
||||
snap_seg->origin->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_format_dev(devbufc, sizeof(devbufc), dlc->info.major,
|
||||
dlc->info.minor)) {
|
||||
log_error("Couldn't create cow device parameters for '%s'.",
|
||||
snap_seg->cow->name);
|
||||
if (!build_dev_string(dm, cow, devbufc, sizeof(devbufc), "cow")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1243,6 +1187,7 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
|
||||
|
||||
/* Add dependencies for any LVs that segments refer to */
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
// When do we need? _set_flag(dl, REMOVE) on the log?
|
||||
if (seg->log_lv &&
|
||||
!str_list_add(dm->mem, &dl->pre_create,
|
||||
_build_dlid(dm->mem, seg->log_lv->lvid.s,
|
||||
@@ -1250,7 +1195,6 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
// FIXME Check we don't want NOPROPAGATE here
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg_type(seg, s) != AREA_LV)
|
||||
@@ -1262,7 +1206,10 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ? if (seg_lv(seg, s)->status & PVMOVE)
|
||||
_set_flag(dl, NOPROPAGATE);
|
||||
// When do we need? _set_flag(dl, REMOVE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1413,11 +1360,19 @@ static int _expand_lv(struct dev_manager *dm, struct logical_volume *lv)
|
||||
/*
|
||||
* FIXME: this doesn't cope with recursive snapshots yet.
|
||||
*/
|
||||
if ((snap_seg = find_cow(lv)))
|
||||
if ((snap_seg = find_cow(lv))) {
|
||||
if (lv->vg->status & CLUSTERED) {
|
||||
log_error("Clustered snapshots are not yet supported");
|
||||
return 0;
|
||||
}
|
||||
return _expand_snapshot(dm, lv, snap_seg);
|
||||
|
||||
else if (lv_is_origin(lv))
|
||||
} else if (lv_is_origin(lv)) {
|
||||
if (lv->vg->status & CLUSTERED) {
|
||||
log_error("Clustered snapshots are not yet supported");
|
||||
return 0;
|
||||
}
|
||||
return _expand_origin(dm, lv);
|
||||
}
|
||||
|
||||
return _expand_vanilla(dm, lv, 0);
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!set_selinux_context(lv_path)) {
|
||||
if (!set_selinux_context(lv_path, S_IFLNK)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos,
|
||||
int start_area, int areas);
|
||||
|
||||
int compose_log_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos, int areas,
|
||||
uint32_t region_size);
|
||||
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
|
||||
size_t bufsize, const char *desc);
|
||||
|
||||
#endif
|
||||
|
||||
15
lib/cache/lvmcache.c
vendored
15
lib/cache/lvmcache.c
vendored
@@ -495,17 +495,32 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
pvid, dev_name(dev),
|
||||
dev_name(existing->dev));
|
||||
return NULL;
|
||||
} else if (is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
!is_dm_major(MAJOR(dev->dev))) {
|
||||
log_very_verbose("Ignoring duplicate PV %s on "
|
||||
"%s - using dm %s",
|
||||
pvid, dev_name(dev),
|
||||
dev_name(existing->dev));
|
||||
return NULL;
|
||||
} else if (MAJOR(existing->dev->dev) != md_major() &&
|
||||
MAJOR(dev->dev) == md_major())
|
||||
log_very_verbose("Duplicate PV %s on %s - "
|
||||
"using md %s", pvid,
|
||||
dev_name(existing->dev),
|
||||
dev_name(dev));
|
||||
else if (!is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
is_dm_major(MAJOR(dev->dev)))
|
||||
log_very_verbose("Duplicate PV %s on %s - "
|
||||
"using dm %s", pvid,
|
||||
dev_name(existing->dev),
|
||||
dev_name(dev));
|
||||
else
|
||||
log_error("Found duplicate PV %s: using %s not "
|
||||
"%s", pvid, dev_name(dev),
|
||||
dev_name(existing->dev));
|
||||
}
|
||||
/* Switch over to new preferred device */
|
||||
existing->dev = dev;
|
||||
info = existing;
|
||||
/* Has labeller changed? */
|
||||
if (info->label->labeller != labeller) {
|
||||
|
||||
@@ -23,12 +23,21 @@ bitset_t bitset_create(struct pool *mem, unsigned num_bits)
|
||||
{
|
||||
unsigned n = (num_bits / BITS_PER_INT) + 2;
|
||||
size_t size = sizeof(int) * n;
|
||||
unsigned *bs = pool_zalloc(mem, size);
|
||||
bitset_t bs;
|
||||
|
||||
if (mem)
|
||||
bs = pool_zalloc(mem, size);
|
||||
else
|
||||
bs = dbg_malloc(size);
|
||||
|
||||
if (!bs)
|
||||
return NULL;
|
||||
|
||||
*bs = num_bits;
|
||||
|
||||
if (!mem)
|
||||
bit_clear_all(bs);
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
|
||||
@@ -247,6 +247,8 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
|
||||
/* Generate pretend device numbers for loopfiles */
|
||||
if (!d) {
|
||||
if (hash_lookup(_cache.names, path))
|
||||
return 1;
|
||||
d = ++loopfile_count;
|
||||
loopfile = 1;
|
||||
}
|
||||
@@ -627,6 +629,10 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
||||
if (!d) {
|
||||
_insert(name, 0);
|
||||
d = (struct device *) hash_lookup(_cache.names, name);
|
||||
if (!d) {
|
||||
_full_scan(0);
|
||||
d = (struct device *) hash_lookup(_cache.names, name);
|
||||
}
|
||||
}
|
||||
|
||||
return (d && (!f || (d->flags & DEV_REGULAR) ||
|
||||
|
||||
@@ -471,7 +471,9 @@ void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
|
||||
log_print("%sLogical extents\t%d to %d", pre,
|
||||
seg_le(seg, s),
|
||||
seg_le(seg, s) + seg->area_len - 1);
|
||||
|
||||
break;
|
||||
case AREA_UNASSIGNED:
|
||||
log_print("%sUnassigned area", pre);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "lvm-string.h"
|
||||
#include "config.h"
|
||||
#include "metadata.h"
|
||||
#include "bitset.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
@@ -38,12 +39,18 @@ typedef struct {
|
||||
} device_info_t;
|
||||
|
||||
static int _md_major = -1;
|
||||
static bitset_t _dm_bitset;
|
||||
|
||||
int md_major(void)
|
||||
{
|
||||
return _md_major;
|
||||
}
|
||||
|
||||
int is_dm_major(int major)
|
||||
{
|
||||
return bit(_dm_bitset, major) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Devices are only checked for partition tables if their minor number
|
||||
* is a multiple of the number corresponding to their type below
|
||||
@@ -71,6 +78,7 @@ static const device_info_t device_info[] = {
|
||||
{"iseries/vd", 8}, /* iSeries disks */
|
||||
{"gnbd", 1}, /* Network block device */
|
||||
{"ramdisk", 1}, /* RAM disk */
|
||||
{"aoe", 16}, /* ATA over Ethernet */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
@@ -180,6 +188,11 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
|
||||
_md_major = line_maj;
|
||||
|
||||
/* Look for dm devices */
|
||||
if (!strncmp("device-mapper", line + i, 13) &&
|
||||
isspace(*(line + i + 13)))
|
||||
bit_set(_dm_bitset, line_maj);
|
||||
|
||||
/* Go through the valid device names and if there is a
|
||||
match store max number of partitions */
|
||||
for (j = 0; device_info[j].name != NULL; j++) {
|
||||
@@ -250,6 +263,12 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
f->destroy = lvm_type_filter_destroy;
|
||||
f->private = NULL;
|
||||
|
||||
if (!(_dm_bitset = bitset_create(NULL, NUMBER_OF_MAJORS))) {
|
||||
stack;
|
||||
dbg_free(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_scan_proc_dev(proc, cn)) {
|
||||
stack;
|
||||
return NULL;
|
||||
@@ -260,6 +279,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
|
||||
void lvm_type_filter_destroy(struct dev_filter *f)
|
||||
{
|
||||
bitset_destroy(_dm_bitset);
|
||||
dbg_free(f);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
void lvm_type_filter_destroy(struct dev_filter *f);
|
||||
|
||||
int md_major(void);
|
||||
|
||||
int is_dm_major(int major);
|
||||
int max_partitions(int major);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -506,6 +506,9 @@ static int _write_vgd(struct disk_list *data)
|
||||
struct vg_disk *vgd = &data->vgd;
|
||||
uint64_t pos = data->pvd.vg_on_disk.base;
|
||||
|
||||
log_debug("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
|
||||
data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
|
||||
|
||||
_xlate_vgd(vgd);
|
||||
if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
|
||||
fail;
|
||||
@@ -528,6 +531,10 @@ static int _write_uuids(struct disk_list *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("Writing %s uuidlist to %s at %" PRIu64 " len %"
|
||||
PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
|
||||
pos, NAME_LEN);
|
||||
|
||||
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
|
||||
fail;
|
||||
|
||||
@@ -539,6 +546,10 @@ static int _write_uuids(struct disk_list *data)
|
||||
|
||||
static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
||||
{
|
||||
log_debug("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
|
||||
PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
|
||||
pos, sizeof(*disk));
|
||||
|
||||
_xlate_lvd(disk);
|
||||
if (!dev_write(dev, pos, sizeof(*disk), disk))
|
||||
fail;
|
||||
@@ -581,6 +592,10 @@ static int _write_extents(struct disk_list *data)
|
||||
struct pe_disk *extents = data->extents;
|
||||
uint64_t pos = data->pvd.pe_on_disk.base;
|
||||
|
||||
log_debug("Writing %s extents metadata to %s at %" PRIu64 " len %"
|
||||
PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
|
||||
pos, len);
|
||||
|
||||
_xlate_extents(extents, data->pvd.pe_total);
|
||||
if (!dev_write(data->dev, pos, len, extents))
|
||||
fail;
|
||||
@@ -613,6 +628,10 @@ static int _write_pvd(struct disk_list *data)
|
||||
memset(buf, 0, size);
|
||||
memcpy(buf, &data->pvd, sizeof(struct pv_disk));
|
||||
|
||||
log_debug("Writing %s PV metadata to %s at %" PRIu64 " len %"
|
||||
PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
|
||||
pos, size);
|
||||
|
||||
_xlate_pvd((struct pv_disk *) buf);
|
||||
if (!dev_write(data->dev, pos, size, buf)) {
|
||||
dbg_free(buf);
|
||||
|
||||
@@ -241,7 +241,7 @@ int import_vg(struct pool *mem,
|
||||
|
||||
vg->extent_size = vgd->pe_size;
|
||||
vg->extent_count = vgd->pe_total;
|
||||
vg->free_count = vgd->pe_total - vgd->pe_allocated;
|
||||
vg->free_count = vgd->pe_total;
|
||||
vg->max_lv = vgd->lv_max;
|
||||
vg->max_pv = vgd->pv_max;
|
||||
vg->alloc = ALLOC_NORMAL;
|
||||
@@ -395,7 +395,7 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
|
||||
return 0;
|
||||
}
|
||||
if (seg_type(seg, s) != AREA_PV) {
|
||||
log_error("LV stripe found in LV %s: "
|
||||
log_error("Non-PV stripe found in LV %s: "
|
||||
"unsupported by format1", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
||||
uint32_t *devcount)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
struct pool_list *pl;
|
||||
struct pool_list *pl = NULL;
|
||||
struct pool *tmpmem;
|
||||
|
||||
uint32_t sp_count = 0;
|
||||
|
||||
@@ -45,7 +45,7 @@ int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
|
||||
get_pool_vg_uuid(&vg->id, &pl->pd);
|
||||
vg->extent_size = POOL_PE_SIZE;
|
||||
vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
|
||||
vg->free_count = 0;
|
||||
vg->free_count = vg->extent_count;
|
||||
vg->max_lv = 1;
|
||||
vg->max_pv = POOL_MAX_DEVICES;
|
||||
vg->alloc = ALLOC_NORMAL;
|
||||
|
||||
@@ -480,6 +480,9 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
seg_lv(seg, s)->name,
|
||||
seg_le(seg, s),
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
break;
|
||||
case AREA_UNASSIGNED:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ static struct flag _lv_flags[] = {
|
||||
{MIRRORED, NULL},
|
||||
{VIRTUAL, NULL},
|
||||
{SNAPSHOT, NULL},
|
||||
{ACTIVATE_EXCL, NULL},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -666,7 +666,7 @@ static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fsync(fd)) {
|
||||
if (fsync(fd) && (errno != EROFS) && (errno != EINVAL)) {
|
||||
log_sys_error("fsync", tc->path_edit);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
|
||||
@@ -364,10 +364,6 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Adjust extent counts in the pv and vg.
|
||||
*/
|
||||
seg->lv->vg->free_count -= seg->area_len;
|
||||
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
|
||||
set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i,
|
||||
flags);
|
||||
|
||||
@@ -327,8 +327,8 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
args = alloca(len);
|
||||
strcpy(args + 2, name);
|
||||
|
||||
args[0] = flags & 0xBF; /* Maskoff LOCAL flag */
|
||||
args[1] = 0; /* Not used now */
|
||||
args[0] = flags & 0x7F; /* Maskoff lock flags */
|
||||
args[1] = flags & 0xC0; /* Bitmap flags */
|
||||
|
||||
/*
|
||||
* VG locks are just that: locks, and have no side effects
|
||||
@@ -339,7 +339,8 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
*/
|
||||
if (cmd == CLVMD_CMD_LOCK_VG ||
|
||||
(flags & LCK_TYPE_MASK) == LCK_EXCL ||
|
||||
(flags & LCK_LOCAL))
|
||||
(flags & LCK_LOCAL) ||
|
||||
!(flags & LCK_CLUSTER_VG))
|
||||
node = ".";
|
||||
|
||||
status = _cluster_request(cmd, node, args, len,
|
||||
|
||||
@@ -243,7 +243,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
break;
|
||||
case LCK_READ:
|
||||
log_debug("Locking LV %s (R)", resource);
|
||||
if (!lv_activate_with_filter(cmd, resource))
|
||||
if (!lv_activate_with_filter(cmd, resource, 0))
|
||||
return 0;
|
||||
break;
|
||||
case LCK_WRITE:
|
||||
@@ -253,7 +253,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
break;
|
||||
case LCK_EXCL:
|
||||
log_debug("Locking LV %s (EX)", resource);
|
||||
if (!lv_activate_with_filter(cmd, resource))
|
||||
if (!lv_activate_with_filter(cmd, resource, 1))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -268,7 +268,7 @@ int resume_lvs(struct cmd_context *cmd, struct list *lvs)
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate_items(lvl, lvs)
|
||||
resume_lv(cmd, lvl->lv->lvid.s);
|
||||
resume_lv(cmd, lvl->lv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -280,11 +280,11 @@ int suspend_lvs(struct cmd_context *cmd, struct list *lvs)
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate_items(lvl, lvs) {
|
||||
if (!suspend_lv(cmd, lvl->lv->lvid.s)) {
|
||||
if (!suspend_lv(cmd, lvl->lv)) {
|
||||
log_error("Failed to suspend %s", lvl->lv->name);
|
||||
list_uniterate(lvh, lvs, &lvl->list) {
|
||||
lvl = list_item(lvh, struct lv_list);
|
||||
resume_lv(cmd, lvl->lv->lvid.s);
|
||||
resume_lv(cmd, lvl->lv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -301,11 +301,11 @@ int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs)
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate_items(lvl, lvs) {
|
||||
if (!activate_lv_excl(cmd, lvl->lv->lvid.s)) {
|
||||
if (!activate_lv_excl(cmd, lvl->lv)) {
|
||||
log_error("Failed to activate %s", lvl->lv->name);
|
||||
list_uniterate(lvh, lvs, &lvl->list) {
|
||||
lvl = list_item(lvh, struct lv_list);
|
||||
activate_lv(cmd, lvl->lv->lvid.s);
|
||||
activate_lv(cmd, lvl->lv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -65,6 +65,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_NONBLOCK 0x00000010 /* Don't block waiting for lock? */
|
||||
#define LCK_HOLD 0x00000020 /* Hold lock when lock_vol returns? */
|
||||
#define LCK_LOCAL 0x00000040 /* Don't propagate to other nodes */
|
||||
#define LCK_CLUSTER_VG 0x00000080 /* VG is clustered */
|
||||
|
||||
/*
|
||||
* Common combinations
|
||||
@@ -79,22 +80,27 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_LV_ACTIVATE (LCK_LV | LCK_READ | LCK_NONBLOCK)
|
||||
#define LCK_LV_DEACTIVATE (LCK_LV | LCK_NULL | LCK_NONBLOCK)
|
||||
|
||||
#define LCK_LV_CLUSTERED(lv) \
|
||||
(((lv)->vg->status & CLUSTERED) ? LCK_CLUSTER_VG : 0)
|
||||
|
||||
#define lock_lv_vol(cmd, lv, flags) \
|
||||
lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv))
|
||||
|
||||
#define unlock_vg(cmd, vol) lock_vol(cmd, vol, LCK_VG_UNLOCK)
|
||||
|
||||
#define resume_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_RESUME)
|
||||
#define suspend_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_SUSPEND | LCK_HOLD)
|
||||
#define deactivate_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_DEACTIVATE)
|
||||
#define activate_lv(cmd, vol) lock_vol(cmd, vol, LCK_LV_ACTIVATE | LCK_HOLD)
|
||||
#define activate_lv_excl(cmd, vol) \
|
||||
lock_vol(cmd, vol, LCK_LV_EXCLUSIVE | LCK_HOLD)
|
||||
#define activate_lv_local(cmd, vol) \
|
||||
lock_vol(cmd, vol, LCK_LV_ACTIVATE | LCK_HOLD | LCK_LOCAL)
|
||||
#define deactivate_lv_local(cmd, vol) \
|
||||
lock_vol(cmd, vol, LCK_LV_DEACTIVATE | LCK_LOCAL)
|
||||
#define resume_lv(cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_RESUME)
|
||||
#define suspend_lv(cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_SUSPEND | LCK_HOLD)
|
||||
#define deactivate_lv(cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE)
|
||||
#define activate_lv(cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD)
|
||||
#define activate_lv_excl(cmd, lv) \
|
||||
lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD)
|
||||
#define activate_lv_local(cmd, lv) \
|
||||
lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD | LCK_LOCAL)
|
||||
#define deactivate_lv_local(cmd, lv) \
|
||||
lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE | LCK_LOCAL)
|
||||
|
||||
/* Process list of LVs */
|
||||
int suspend_lvs(struct cmd_context *cmd, struct list *lvs);
|
||||
int resume_lvs(struct cmd_context *cmd, struct list *lvs);
|
||||
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs);
|
||||
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
case LCK_UNLOCK:
|
||||
return lv_resume_if_active(cmd, resource);
|
||||
case LCK_READ:
|
||||
return lv_activate_with_filter(cmd, resource);
|
||||
return lv_activate_with_filter(cmd, resource, 0);
|
||||
case LCK_WRITE:
|
||||
return lv_suspend_if_active(cmd, resource);
|
||||
case LCK_EXCL:
|
||||
return lv_activate_with_filter(cmd, resource);
|
||||
return lv_activate_with_filter(cmd, resource, 1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,10 @@ int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
|
||||
void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
|
||||
struct logical_volume *lv, uint32_t le,
|
||||
uint32_t flags);
|
||||
int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
|
||||
struct lv_segment *seg_from, uint32_t area_from);
|
||||
void release_lv_segment_area(struct lv_segment *seg, uint32_t s,
|
||||
uint32_t area_reduction);
|
||||
|
||||
struct alloc_handle;
|
||||
struct alloc_handle *allocate_extents(struct volume_group *vg,
|
||||
|
||||
@@ -125,6 +125,74 @@ struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
|
||||
return seg;
|
||||
}
|
||||
|
||||
void release_lv_segment_area(struct lv_segment *seg, uint32_t s,
|
||||
uint32_t area_reduction)
|
||||
{
|
||||
if (seg_type(seg, s) == AREA_UNASSIGNED)
|
||||
return;
|
||||
|
||||
if (seg_type(seg, s) == AREA_PV) {
|
||||
release_pv_segment(seg_pvseg(seg, s), area_reduction);
|
||||
return;
|
||||
}
|
||||
|
||||
if (seg_lv(seg, s)->status & MIRROR_IMAGE) {
|
||||
lv_reduce(seg_lv(seg, s), area_reduction);
|
||||
return;
|
||||
}
|
||||
|
||||
if (area_reduction == seg->area_len) {
|
||||
seg_lv(seg, s) = NULL;
|
||||
seg_le(seg, s) = 0;
|
||||
seg_type(seg, s) = AREA_UNASSIGNED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Move a segment area from one segment to another
|
||||
*/
|
||||
int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
|
||||
struct lv_segment *seg_from, uint32_t area_from)
|
||||
{
|
||||
struct physical_volume *pv;
|
||||
struct logical_volume *lv;
|
||||
uint32_t pe, le;
|
||||
|
||||
switch (seg_type(seg_from, area_from)) {
|
||||
case AREA_PV:
|
||||
pv = seg_pv(seg_from, area_from);
|
||||
pe = seg_pe(seg_from, area_from);
|
||||
|
||||
release_lv_segment_area(seg_from, area_from,
|
||||
seg_from->area_len);
|
||||
release_lv_segment_area(seg_to, area_to, seg_to->area_len);
|
||||
|
||||
if (!set_lv_segment_area_pv(seg_to, area_to, pv, pe)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AREA_LV:
|
||||
lv = seg_lv(seg_from, area_from);
|
||||
le = seg_le(seg_from, area_from);
|
||||
|
||||
release_lv_segment_area(seg_from, area_from,
|
||||
seg_from->area_len);
|
||||
release_lv_segment_area(seg_to, area_to, seg_to->area_len);
|
||||
|
||||
set_lv_segment_area_lv(seg_to, area_to, lv, le, 0);
|
||||
|
||||
break;
|
||||
|
||||
case AREA_UNASSIGNED:
|
||||
release_lv_segment_area(seg_to, area_to, seg_to->area_len);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Link part of a PV to an LV segment.
|
||||
*/
|
||||
@@ -132,7 +200,6 @@ int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
|
||||
struct physical_volume *pv, uint32_t pe)
|
||||
{
|
||||
seg->area[area_num].type = AREA_PV;
|
||||
pv->pe_alloc_count += seg->area_len;
|
||||
|
||||
if (!(seg_pvseg(seg, area_num) =
|
||||
assign_peg_to_lvseg(pv, pe, seg->area_len, seg, area_num))) {
|
||||
@@ -175,24 +242,19 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
|
||||
} else
|
||||
area_reduction = reduction;
|
||||
|
||||
for (s = 0; s < seg->area_count; s++)
|
||||
release_lv_segment_area(seg, s, area_reduction);
|
||||
|
||||
seg->len -= reduction;
|
||||
seg->area_len -= area_reduction;
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg_type(seg, s) == AREA_PV) {
|
||||
release_pv_segment(seg_pvseg(seg, s), area_reduction);
|
||||
seg->lv->vg->free_count += area_reduction;
|
||||
} else if (seg_lv(seg, s)->status & MIRROR_IMAGE)
|
||||
lv_reduce(seg_lv(seg, s), area_reduction);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry point for all LV reductions in size.
|
||||
*/
|
||||
int lv_reduce(struct logical_volume *lv, uint32_t extents)
|
||||
static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
||||
{
|
||||
struct lv_list *lvl;
|
||||
struct lv_segment *seg;
|
||||
@@ -225,6 +287,9 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
|
||||
lv->le_count -= extents;
|
||||
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
|
||||
|
||||
if (!delete)
|
||||
return 1;
|
||||
|
||||
/* Remove the LV if it is now empty */
|
||||
if (!lv->le_count) {
|
||||
if (!(lvl = find_lv_in_vg(lv->vg, lv->name))) {
|
||||
@@ -244,6 +309,19 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Empty an LV
|
||||
*/
|
||||
int lv_empty(struct logical_volume *lv)
|
||||
{
|
||||
return _lv_reduce(lv, 0, lv->le_count);
|
||||
}
|
||||
|
||||
int lv_reduce(struct logical_volume *lv, uint32_t extents)
|
||||
{
|
||||
return _lv_reduce(lv, extents, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Completely remove an LV.
|
||||
*/
|
||||
@@ -406,8 +484,6 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint32_t status,
|
||||
lv->le_count += extents;
|
||||
lv->size += (uint64_t) extents *lv->vg->extent_size;
|
||||
|
||||
lv->vg->free_count -= aa[0].len * area_count;
|
||||
|
||||
if (segtype_is_mirrored(segtype))
|
||||
lv->status |= MIRRORED;
|
||||
|
||||
@@ -624,8 +700,8 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
|
||||
/* Only allocate log_area the first time around */
|
||||
if (ix + ix_offset < ah->area_count +
|
||||
(ah->log_count && !ah->log_area.len) ?
|
||||
ah->log_count : 0)
|
||||
((ah->log_count && !ah->log_area.len) ?
|
||||
ah->log_count : 0))
|
||||
/* FIXME With ALLOC_ANYWHERE, need to split areas */
|
||||
break;
|
||||
|
||||
@@ -645,7 +721,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
} while (*allocated != needed && can_split);
|
||||
} while (!contiguous && *allocated != needed && can_split);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -912,8 +988,6 @@ int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
|
||||
log_lv->le_count += ah->log_area.len;
|
||||
log_lv->size += (uint64_t) log_lv->le_count *log_lv->vg->extent_size;
|
||||
|
||||
log_lv->vg->free_count--;
|
||||
|
||||
if (log_lv->vg->fid->fmt->ops->lv_setup &&
|
||||
!log_lv->vg->fid->fmt->ops->lv_setup(log_lv->vg->fid, log_lv)) {
|
||||
stack;
|
||||
|
||||
@@ -86,7 +86,12 @@ int check_lv_segments(struct logical_volume *lv)
|
||||
}
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg_type(seg, s) == AREA_PV) {
|
||||
if (seg_type(seg, s) == AREA_UNASSIGNED) {
|
||||
log_error("LV %s: segment %u has unassigned "
|
||||
"area %u.",
|
||||
lv->name, seg_count, s);
|
||||
r = 0;
|
||||
} else if (seg_type(seg, s) == AREA_PV) {
|
||||
if (!seg_pvseg(seg, s) ||
|
||||
seg_pvseg(seg, s)->lvseg != seg ||
|
||||
seg_pvseg(seg, s)->lv_area != s) {
|
||||
@@ -104,6 +109,7 @@ int check_lv_segments(struct logical_volume *lv)
|
||||
lv->name, seg_count, s);
|
||||
r = 0;
|
||||
}
|
||||
/* FIXME I don't think this ever holds?
|
||||
if (seg_le(seg, s) != le) {
|
||||
log_error("LV %s: segment %u has "
|
||||
"inconsistent LV area %u "
|
||||
@@ -111,6 +117,7 @@ int check_lv_segments(struct logical_volume *lv)
|
||||
lv->name, seg_count, s);
|
||||
r = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,12 +197,13 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
break;
|
||||
|
||||
case AREA_PV:
|
||||
if (!assign_peg_to_lvseg(seg_pv(seg, s),
|
||||
if (!(seg_pvseg(split_seg, s) =
|
||||
assign_peg_to_lvseg(seg_pv(seg, s),
|
||||
seg_pe(seg, s) +
|
||||
seg->area_len,
|
||||
seg_pvseg(seg, s)->len -
|
||||
seg->area_len,
|
||||
split_seg, s)) {
|
||||
split_seg, s))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -205,9 +213,8 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
seg_pe(split_seg, s));
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Unrecognised segment type %u",
|
||||
seg_type(seg, s));
|
||||
case AREA_UNASSIGNED:
|
||||
log_error("Unassigned area %u found in segment", s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -240,5 +247,10 @@ int lv_split_segment(struct logical_volume *lv, uint32_t le)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_validate(lv->vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -465,9 +465,9 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error("Unrecognised segment type "
|
||||
"%u", seg_type(seg, s));
|
||||
case AREA_UNASSIGNED:
|
||||
log_error("Unassigned area %u found in "
|
||||
"segment", s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -697,14 +697,8 @@ int vg_remove(struct volume_group *vg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* After vg_write() returns success,
|
||||
* caller MUST call either vg_commit() or vg_revert()
|
||||
*/
|
||||
int vg_write(struct volume_group *vg)
|
||||
int vg_validate(struct volume_group *vg)
|
||||
{
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
struct lv_list *lvl;
|
||||
|
||||
if (!check_pv_segments(vg)) {
|
||||
@@ -721,6 +715,23 @@ int vg_write(struct volume_group *vg)
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* After vg_write() returns success,
|
||||
* caller MUST call either vg_commit() or vg_revert()
|
||||
*/
|
||||
int vg_write(struct volume_group *vg)
|
||||
{
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
|
||||
if (!vg_validate(vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vg->status & PARTIAL_VG) {
|
||||
log_error("Cannot change metadata for partial volume group %s",
|
||||
vg->name);
|
||||
@@ -1045,7 +1056,27 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
int *consistent)
|
||||
{
|
||||
return _vg_read(cmd, vgname, consistent, 0);
|
||||
struct volume_group *vg;
|
||||
struct lv_list *lvl;
|
||||
|
||||
if (!(vg = _vg_read(cmd, vgname, consistent, 0)))
|
||||
return NULL;
|
||||
|
||||
if (!check_pv_segments(vg)) {
|
||||
log_error("Internal error: PV segments corrupted in %s.",
|
||||
vg->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (!check_lv_segments(lvl->lv)) {
|
||||
log_error("Internal error: LV segments corrupted in %s.",
|
||||
lvl->lv->name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return vg;
|
||||
}
|
||||
|
||||
struct volume_group *vg_read_precommitted(struct cmd_context *cmd,
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#define VIRTUAL 0x00010000 /* LV - internal use only */
|
||||
#define MIRROR_LOG 0x00020000 /* LV */
|
||||
#define MIRROR_IMAGE 0x00040000 /* LV */
|
||||
#define ACTIVATE_EXCL 0x00080000 /* LV - internal use only */
|
||||
|
||||
#define LVM_READ 0x00000100 /* LV VG */
|
||||
#define LVM_WRITE 0x00000200 /* LV VG */
|
||||
@@ -81,6 +82,7 @@ typedef enum {
|
||||
} alloc_policy_t;
|
||||
|
||||
typedef enum {
|
||||
AREA_UNASSIGNED = 0,
|
||||
AREA_PV,
|
||||
AREA_LV
|
||||
} area_type_t;
|
||||
@@ -390,6 +392,7 @@ struct format_handler {
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
int vg_validate(struct volume_group *vg);
|
||||
int vg_write(struct volume_group *vg);
|
||||
int vg_commit(struct volume_group *vg);
|
||||
int vg_revert(struct volume_group *vg);
|
||||
@@ -443,9 +446,12 @@ struct logical_volume *lv_create_empty(struct format_instance *fi,
|
||||
int import,
|
||||
struct volume_group *vg);
|
||||
|
||||
/* Entry point for all LV extent reductions */
|
||||
/* Reduce the size of an LV by extents */
|
||||
int lv_reduce(struct logical_volume *lv, uint32_t extents);
|
||||
|
||||
/* Empty an LV prior to deleting it */
|
||||
int lv_empty(struct logical_volume *lv);
|
||||
|
||||
/* Entry point for all LV extent allocations */
|
||||
int lv_extend(struct logical_volume *lv,
|
||||
struct segment_type *segtype,
|
||||
@@ -534,11 +540,12 @@ int vg_add_snapshot(struct format_instance *fid, const char *name,
|
||||
|
||||
int vg_remove_snapshot(struct logical_volume *cow);
|
||||
|
||||
|
||||
/*
|
||||
* Mirroring functions
|
||||
*/
|
||||
struct alloc_handle;
|
||||
uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
|
||||
uint32_t region_size);
|
||||
int create_mirror_layers(struct alloc_handle *ah,
|
||||
uint32_t first_area,
|
||||
uint32_t num_mirrors,
|
||||
@@ -547,6 +554,9 @@ int create_mirror_layers(struct alloc_handle *ah,
|
||||
uint32_t status,
|
||||
uint32_t region_size,
|
||||
struct logical_volume *log_lv);
|
||||
int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors);
|
||||
int remove_all_mirror_images(struct logical_volume *lv);
|
||||
|
||||
int insert_pvmove_mirrors(struct cmd_context *cmd,
|
||||
struct logical_volume *lv_mirr,
|
||||
struct list *source_pvl,
|
||||
|
||||
@@ -22,6 +22,26 @@
|
||||
#include "lv_alloc.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
/*
|
||||
* Ensure region size is compatible with volume size.
|
||||
*/
|
||||
uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
|
||||
uint32_t region_size)
|
||||
{
|
||||
uint32_t region_max;
|
||||
|
||||
region_max = (1 << (ffs(extents) - 1)) * extent_size;
|
||||
|
||||
if (region_max < region_size) {
|
||||
region_size = region_max;
|
||||
log_print("Using reduced mirror region size of %" PRIu32
|
||||
" sectors", region_max);
|
||||
return region_max;
|
||||
}
|
||||
|
||||
return region_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reduce mirrored_seg to num_mirrors images.
|
||||
*/
|
||||
@@ -171,6 +191,8 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
|
||||
struct lv_segment *seg;
|
||||
struct lv_list *lvl;
|
||||
struct pv_list *pvl;
|
||||
struct physical_volume *pv;
|
||||
uint32_t pe;
|
||||
int lv_used = 0;
|
||||
uint32_t s, start_le, extent_count = 0u;
|
||||
struct segment_type *segtype;
|
||||
@@ -270,18 +292,19 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
|
||||
lv_used = 1;
|
||||
}
|
||||
|
||||
pv = seg_pv(seg, s);
|
||||
pe = seg_pe(seg, s);
|
||||
log_very_verbose("Moving %s:%u-%u of %s/%s",
|
||||
dev_name(pvl->pv->dev),
|
||||
seg_pe(seg, s),
|
||||
seg_pe(seg, s) +
|
||||
seg->area_len - 1,
|
||||
pe, pe + seg->area_len - 1,
|
||||
lv->vg->name, lv->name);
|
||||
|
||||
start_le = lv_mirr->le_count;
|
||||
/* FIXME Clean this up */
|
||||
release_lv_segment_area(seg, s, seg->area_len);
|
||||
if (!lv_extend(lv_mirr, segtype, 1,
|
||||
seg->area_len, 0u, seg->area_len,
|
||||
seg_pv(seg, s),
|
||||
seg_pe(seg, s),
|
||||
pv, pe,
|
||||
PVMOVE, allocatable_pvs,
|
||||
alloc)) {
|
||||
log_error("Unable to allocate "
|
||||
@@ -355,22 +378,22 @@ int remove_pvmove_mirrors(struct volume_group *vg,
|
||||
else
|
||||
c = 0;
|
||||
|
||||
if (!set_lv_segment_area_pv(seg, s,
|
||||
seg_pv(mir_seg, c),
|
||||
seg_pe(mir_seg, c))) {
|
||||
if (!move_lv_segment_area(seg, s, mir_seg, c)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Replace mirror with old area */
|
||||
release_lv_segment_area(mir_seg, !c, mir_seg->area_len);
|
||||
|
||||
/* Replace mirror with error segment */
|
||||
if (!
|
||||
(mir_seg->segtype =
|
||||
get_segtype_from_string(vg->cmd,
|
||||
"striped"))) {
|
||||
log_error("Missing striped segtype");
|
||||
"error"))) {
|
||||
log_error("Missing error segtype");
|
||||
return 0;
|
||||
}
|
||||
mir_seg->area_count = 1;
|
||||
mir_seg->area_count = 0;
|
||||
|
||||
/* FIXME Assumes only one pvmove at a time! */
|
||||
lv1->status &= ~LOCKED;
|
||||
@@ -381,6 +404,10 @@ int remove_pvmove_mirrors(struct volume_group *vg,
|
||||
|
||||
}
|
||||
|
||||
if (!lv_empty(lv_mirr)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -392,7 +419,7 @@ const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr)
|
||||
list_iterate_items(seg, &lv_mirr->segments) {
|
||||
if (!seg_is_mirrored(seg))
|
||||
continue;
|
||||
if (seg->area[0].type != AREA_PV)
|
||||
if (seg_type(seg, 0) != AREA_PV)
|
||||
continue;
|
||||
return dev_name(seg_dev(seg, 0));
|
||||
}
|
||||
@@ -433,7 +460,7 @@ struct logical_volume *find_pvmove_lv(struct volume_group *vg,
|
||||
|
||||
/* Check segment origins point to pvname */
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (seg->area[0].type != AREA_PV)
|
||||
if (seg_type(seg, 0) != AREA_PV)
|
||||
continue;
|
||||
if (seg_dev(seg, 0) != dev)
|
||||
continue;
|
||||
|
||||
@@ -100,6 +100,11 @@ static int _pv_split_segment(struct physical_volume *pv, struct pv_segment *peg,
|
||||
|
||||
list_add_h(&peg->list, &peg_new->list);
|
||||
|
||||
if (peg->lvseg) {
|
||||
peg->pv->pe_alloc_count -= peg_new->len;
|
||||
peg->lvseg->lv->vg->free_count += peg_new->len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -162,14 +167,24 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv,
|
||||
peg->lvseg = seg;
|
||||
peg->lv_area = area_num;
|
||||
|
||||
peg->pv->pe_alloc_count += area_len;
|
||||
peg->lvseg->lv->vg->free_count -= area_len;
|
||||
|
||||
return peg;
|
||||
}
|
||||
|
||||
int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
|
||||
{
|
||||
peg->pv->pe_alloc_count -= area_reduction;
|
||||
if (!peg->lvseg) {
|
||||
log_error("release_pv_segment with unallocated segment: "
|
||||
"%s PE %" PRIu32, dev_name(peg->pv->dev), peg->pe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (peg->lvseg->area_len == area_reduction) {
|
||||
peg->pv->pe_alloc_count -= area_reduction;
|
||||
peg->lvseg->lv->vg->free_count += area_reduction;
|
||||
|
||||
if (!peg->lvseg->area_len) {
|
||||
peg->lvseg = NULL;
|
||||
peg->lv_area = 0;
|
||||
|
||||
@@ -178,7 +193,8 @@ int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len)) {
|
||||
if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len -
|
||||
area_reduction)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -165,6 +165,47 @@ static struct mirror_state *_init_target(struct pool *mem,
|
||||
return mirr_state;
|
||||
}
|
||||
|
||||
static int _compose_log_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos,
|
||||
int areas, uint32_t region_size)
|
||||
{
|
||||
int tw;
|
||||
char devbuf[10];
|
||||
const char *clustered = "";
|
||||
|
||||
/*
|
||||
* Use clustered mirror log for non-exclusive activation
|
||||
* in clustered VG.
|
||||
*/
|
||||
if ((!(seg->lv->status & ACTIVATE_EXCL) &&
|
||||
(seg->lv->vg->status & CLUSTERED)))
|
||||
clustered = "cluster ";
|
||||
|
||||
if (!seg->log_lv)
|
||||
tw = lvm_snprintf(params, paramsize, "%score 1 %u %u ",
|
||||
clustered, region_size, areas);
|
||||
else {
|
||||
if (!build_dev_string(dm, seg->log_lv->lvid.s, devbuf,
|
||||
sizeof(devbuf), "log")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME add sync parm? */
|
||||
tw = lvm_snprintf(params, paramsize, "%sdisk 2 %s %u %u ",
|
||||
clustered, devbuf, region_size, areas);
|
||||
}
|
||||
|
||||
if (tw < 0) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pos += tw;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg, char *params,
|
||||
@@ -220,8 +261,8 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = compose_log_line(dm, seg, params, paramsize, pos,
|
||||
areas, region_size)) <= 0) {
|
||||
if ((ret = _compose_log_line(dm, seg, params, paramsize, pos,
|
||||
areas, region_size)) <= 0) {
|
||||
stack;
|
||||
return ret;
|
||||
}
|
||||
@@ -238,18 +279,41 @@ static int _target_percent(void **target_state, struct pool *mem,
|
||||
{
|
||||
struct mirror_state *mirr_state;
|
||||
uint64_t numerator, denominator;
|
||||
unsigned mirror_count, m;
|
||||
int used;
|
||||
char *pos = params;
|
||||
|
||||
if (!*target_state)
|
||||
*target_state = _init_target(mem, cft);
|
||||
|
||||
mirr_state = *target_state;
|
||||
|
||||
/* Status line: <#mirrors> (maj:min)+ <synced>/<total_regions> */
|
||||
log_debug("Mirror status: %s", params);
|
||||
if (sscanf(params, "%*d %*x:%*x %*x:%*x %" PRIu64
|
||||
"/%" PRIu64, &numerator, &denominator) != 2) {
|
||||
log_error("Failure parsing mirror status: %s", params);
|
||||
|
||||
if (sscanf(pos, "%u %n", mirror_count, used) != 1) {
|
||||
log_error("Failure parsing mirror status mirror count: %s",
|
||||
params);
|
||||
return 0;
|
||||
}
|
||||
pos += used;
|
||||
|
||||
for (m = 0; m < mirror_count; m++) {
|
||||
if (sscanf(pos, "%*x:%*x %n", &used) != 0) {
|
||||
log_error("Failure parsing mirror status devices: %s",
|
||||
params);
|
||||
return 0;
|
||||
}
|
||||
pos += used;
|
||||
}
|
||||
|
||||
if (sscanf(pos, "%" PRIu64 "/%" PRIu64 "%n", &numerator, &denominator,
|
||||
&used) != 2) {
|
||||
log_error("Failure parsing mirror status fraction: %s", params);
|
||||
return 0;
|
||||
}
|
||||
pos += used;
|
||||
|
||||
*total_numerator += numerator;
|
||||
*total_denominator += denominator;
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ void sync_dir(const char *file)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fsync(fd) == -1)
|
||||
if (fsync(fd) && (errno != EROFS) && (errno != EINVAL))
|
||||
log_sys_error("fsync", dir);
|
||||
|
||||
close(fd);
|
||||
|
||||
@@ -18,27 +18,28 @@
|
||||
|
||||
#include <selinux/selinux.h>
|
||||
|
||||
int set_selinux_context(const char *path)
|
||||
int set_selinux_context(const char *path, mode_t mode)
|
||||
{
|
||||
security_context_t scontext;
|
||||
|
||||
if (is_selinux_enabled() <= 0)
|
||||
return 1;
|
||||
|
||||
if (matchpathcon(path, 0, &scontext) < 0) {
|
||||
log_sys_error("matchpathcon", path);
|
||||
if (matchpathcon(path, mode, &scontext) < 0) {
|
||||
log_error("%s: matchpathcon %07o failed: %s", path, mode,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Setting SELinux context for %s to %s",
|
||||
log_very_verbose("Setting SELinux context for %s to %s.",
|
||||
path, scontext);
|
||||
|
||||
if ((lsetfilecon(path, scontext) < 0) && (errno != ENOTSUP)) {
|
||||
log_sys_error("lsetfilecon", path);
|
||||
free(scontext);
|
||||
freecon(scontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(scontext);
|
||||
freecon(scontext);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#ifndef _LVM_SELINUX_H
|
||||
#define _LVM_SELINUX_H
|
||||
|
||||
int set_selinux_context(const char * path);
|
||||
#include <sys/types.h>
|
||||
|
||||
int set_selinux_context(const char * path, mode_t mode);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,21 +22,28 @@
|
||||
#include <sys/stat.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
void *load_shared_library(struct config_tree *cft, const char *libname,
|
||||
const char *desc)
|
||||
static void _get_library_path(struct config_tree *cft, const char *libname,
|
||||
char *path, int path_len)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct stat info;
|
||||
const char *lib_dir;
|
||||
void *library;
|
||||
|
||||
/* If libname doesn't begin with '/' then use lib_dir/libname,
|
||||
* if present */
|
||||
if (libname[0] == '/' ||
|
||||
!(lib_dir = find_config_str(cft->root, "global/library_dir", 0)) ||
|
||||
(lvm_snprintf(path, sizeof(path), "%s/%s", lib_dir,
|
||||
(lvm_snprintf(path, path_len, "%s/%s", lib_dir,
|
||||
libname) == -1) || stat(path, &info) == -1)
|
||||
strncpy(path, libname, sizeof(path));
|
||||
strncpy(path, libname, path_len);
|
||||
}
|
||||
|
||||
void *load_shared_library(struct config_tree *cft, const char *libname,
|
||||
const char *desc)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
void *library;
|
||||
|
||||
_get_library_path(cft, libname, path, sizeof(path));
|
||||
|
||||
log_very_verbose("Opening shared %s library %s", desc, path);
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags")
|
||||
FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype")
|
||||
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes")
|
||||
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize")
|
||||
FIELD(SEGS, seg, NUM, "Chunk", chunk_size, 5, size32, "chunksize")
|
||||
FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunksize")
|
||||
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize")
|
||||
FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start")
|
||||
FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size")
|
||||
|
||||
@@ -163,8 +163,8 @@ static int _devices_disp(struct report_handle *rh, struct field *field,
|
||||
name = dev_name(seg_dev(seg, s));
|
||||
extent = seg_pe(seg, s);
|
||||
break;
|
||||
default:
|
||||
name = "unknown";
|
||||
case AREA_UNASSIGNED:
|
||||
name = "unassigned";
|
||||
extent = 0;
|
||||
}
|
||||
|
||||
@@ -432,7 +432,7 @@ static int _vgstatus_disp(struct report_handle *rh, struct field *field,
|
||||
const struct volume_group *vg = (const struct volume_group *) data;
|
||||
char *repstr;
|
||||
|
||||
if (!(repstr = pool_zalloc(rh->mem, 6))) {
|
||||
if (!(repstr = pool_zalloc(rh->mem, 7))) {
|
||||
log_error("pool_alloc failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -459,6 +459,11 @@ static int _vgstatus_disp(struct report_handle *rh, struct field *field,
|
||||
|
||||
repstr[4] = _alloc_policy_char(vg->alloc);
|
||||
|
||||
if (vg->status & CLUSTERED)
|
||||
repstr[5] = 'c';
|
||||
else
|
||||
repstr[5] = '-';
|
||||
|
||||
field->report_string = repstr;
|
||||
field->sort_value = (const void *) field->report_string;
|
||||
|
||||
@@ -519,7 +524,8 @@ static int _lvname_disp(struct report_handle *rh, struct field *field,
|
||||
char *repstr;
|
||||
size_t len;
|
||||
|
||||
if (lv->status & VISIBLE_LV) {
|
||||
/* FIXME Remove need for snapshot special case */
|
||||
if (lv->status & VISIBLE_LV || lv_is_cow(lv)) {
|
||||
repstr = lv->name;
|
||||
return _string_disp(rh, field, &repstr);
|
||||
}
|
||||
@@ -654,6 +660,21 @@ static int _segsize_disp(struct report_handle *rh, struct field *field,
|
||||
return _size64_disp(rh, field, &size);
|
||||
}
|
||||
|
||||
static int _chunksize_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
struct lv_segment *snap_seg;
|
||||
uint64_t size;
|
||||
|
||||
if ((snap_seg = find_cow(seg->lv)))
|
||||
size = (uint64_t) snap_seg->chunk_size;
|
||||
else
|
||||
size = 0;
|
||||
|
||||
return _size64_disp(rh, field, &size);
|
||||
}
|
||||
|
||||
static int _pvused_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
|
||||
@@ -115,7 +115,8 @@ static int _segments_compatible(struct lv_segment *first,
|
||||
/* FIXME Relax this to first area type != second area type */
|
||||
/* plus the additional AREA_LV checks needed */
|
||||
if ((first->area[s].type != AREA_PV) ||
|
||||
(second->area[s].type != AREA_PV)) return 0;
|
||||
(second->area[s].type != AREA_PV))
|
||||
return 0;
|
||||
|
||||
width = first->area_len;
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ static int _log_suppress = 0;
|
||||
static int _control_fd = -1;
|
||||
static int _version_checked = 0;
|
||||
static int _version_ok = 1;
|
||||
static unsigned _ioctl_buffer_double_factor = 0;
|
||||
|
||||
/*
|
||||
* Support both old and new major numbers to ease the transition.
|
||||
@@ -610,8 +611,10 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
||||
if (dmt->type == DM_DEVICE_TABLE)
|
||||
dmi->flags |= DM_STATUS_TABLE_FLAG;
|
||||
|
||||
log_debug("dm %s %s %s %s", _cmd_data_v1[dmt->type].name, dmi->name,
|
||||
dmi->uuid, dmt->newname ? dmt->newname : "");
|
||||
log_debug("dm %s %s %s%s%s [%u]", _cmd_data_v1[dmt->type].name,
|
||||
dmi->name, dmi->uuid, dmt->newname ? " " : "",
|
||||
dmt->newname ? dmt->newname : "",
|
||||
dmi->data_size);
|
||||
if (dmt->type == DM_DEVICE_LIST) {
|
||||
if (!_dm_names_v1(dmi))
|
||||
goto bad;
|
||||
@@ -1026,7 +1029,7 @@ static void *_add_target(struct target *t, void *out, void *end)
|
||||
return out;
|
||||
}
|
||||
|
||||
static struct dm_ioctl *_flatten(struct dm_task *dmt)
|
||||
static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
{
|
||||
const size_t min_size = 16 * 1024;
|
||||
const int (*version)[3];
|
||||
@@ -1077,6 +1080,10 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
|
||||
if (len < min_size)
|
||||
len = min_size;
|
||||
|
||||
/* Increase buffer size if repeating because buffer was too small */
|
||||
while (repeat_count--)
|
||||
len *= 2;
|
||||
|
||||
if (!(dmi = malloc(len)))
|
||||
return NULL;
|
||||
|
||||
@@ -1276,10 +1283,59 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
unsigned repeat_count)
|
||||
{
|
||||
struct dm_ioctl *dmi;
|
||||
|
||||
dmi = _flatten(dmt, repeat_count);
|
||||
if (!dmi) {
|
||||
log_error("Couldn't create ioctl argument");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->type == DM_DEVICE_TABLE)
|
||||
dmi->flags |= DM_STATUS_TABLE_FLAG;
|
||||
|
||||
dmi->flags |= DM_EXISTS_FLAG; /* FIXME */
|
||||
|
||||
if (dmt->no_open_count)
|
||||
dmi->flags |= DM_SKIP_BDGET_FLAG;
|
||||
|
||||
log_debug("dm %s %s %s%s%s %c %.0llu %s [%u]",
|
||||
_cmd_data_v4[dmt->type].name,
|
||||
dmi->name, dmi->uuid, dmt->newname ? " " : "",
|
||||
dmt->newname ? dmt->newname : "",
|
||||
dmt->no_open_count ? 'N' : 'O',
|
||||
dmt->sector, dmt->message ? dmt->message : "",
|
||||
dmi->data_size);
|
||||
#ifdef DM_IOCTLS
|
||||
if (ioctl(_control_fd, command, dmi) < 0) {
|
||||
if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
|
||||
(dmt->type == DM_DEVICE_MKNODES)))
|
||||
dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */
|
||||
else {
|
||||
if (_log_suppress)
|
||||
log_verbose("device-mapper ioctl "
|
||||
"cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
else
|
||||
log_error("device-mapper ioctl "
|
||||
"cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
free(dmi);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#else /* Userspace alternative for testing */
|
||||
#endif
|
||||
return dmi;
|
||||
}
|
||||
|
||||
int dm_task_run(struct dm_task *dmt)
|
||||
{
|
||||
struct dm_ioctl *dmi = NULL;
|
||||
unsigned int command;
|
||||
struct dm_ioctl *dmi;
|
||||
unsigned command;
|
||||
|
||||
#ifdef DM_COMPAT
|
||||
if (_dm_version == 1)
|
||||
@@ -1290,7 +1346,7 @@ int dm_task_run(struct dm_task *dmt)
|
||||
(sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
|
||||
log_error("Internal error: unknown device-mapper task %d",
|
||||
dmt->type);
|
||||
goto bad;
|
||||
return 0;
|
||||
}
|
||||
|
||||
command = _cmd_data_v4[dmt->type].cmd;
|
||||
@@ -1306,43 +1362,25 @@ int dm_task_run(struct dm_task *dmt)
|
||||
if (!_open_control())
|
||||
return 0;
|
||||
|
||||
dmi = _flatten(dmt);
|
||||
if (!dmi) {
|
||||
log_error("Couldn't create ioctl argument");
|
||||
repeat_ioctl:
|
||||
if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dmt->type == DM_DEVICE_TABLE)
|
||||
dmi->flags |= DM_STATUS_TABLE_FLAG;
|
||||
|
||||
dmi->flags |= DM_EXISTS_FLAG; /* FIXME */
|
||||
|
||||
if (dmt->no_open_count)
|
||||
dmi->flags |= DM_SKIP_BDGET_FLAG;
|
||||
|
||||
log_debug("dm %s %s %s %s%c %.0llu %s", _cmd_data_v4[dmt->type].name,
|
||||
dmi->name, dmi->uuid, dmt->newname ? dmt->newname : "",
|
||||
dmt->no_open_count ? 'N' : 'O',
|
||||
dmt->sector, dmt->message ? dmt->message : "");
|
||||
#ifdef DM_IOCTLS
|
||||
if (ioctl(_control_fd, command, dmi) < 0) {
|
||||
if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
|
||||
(dmt->type == DM_DEVICE_MKNODES)))
|
||||
dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */
|
||||
else {
|
||||
if (_log_suppress)
|
||||
log_verbose("device-mapper ioctl "
|
||||
"cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
else
|
||||
log_error("device-mapper ioctl "
|
||||
"cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
goto bad;
|
||||
if (dmi->flags & DM_BUFFER_FULL_FLAG) {
|
||||
switch (dmt->type) {
|
||||
case DM_DEVICE_LIST_VERSIONS:
|
||||
case DM_DEVICE_LIST:
|
||||
case DM_DEVICE_DEPS:
|
||||
case DM_DEVICE_STATUS:
|
||||
case DM_DEVICE_TABLE:
|
||||
case DM_DEVICE_WAITEVENT:
|
||||
_ioctl_buffer_double_factor++;
|
||||
free(dmi);
|
||||
goto repeat_ioctl;
|
||||
default:
|
||||
log_error("Warning: libdevmapper buffer too small for data");
|
||||
}
|
||||
}
|
||||
#else /* Userspace alternative for testing */
|
||||
#endif
|
||||
|
||||
switch (dmt->type) {
|
||||
case DM_DEVICE_CREATE:
|
||||
|
||||
@@ -111,6 +111,7 @@ struct dm_task *dm_task_create(int type)
|
||||
dmt->uid = DEVICE_UID;
|
||||
dmt->gid = DEVICE_GID;
|
||||
dmt->mode = DEVICE_MODE;
|
||||
dmt->no_open_count = 0;
|
||||
|
||||
return dmt;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ vg_tags.
|
||||
Any "vg_" prefixes are optional. Columns mentioned in either \fBpvs (8)\fP
|
||||
or \fBlvs (8)\fP can also be chosen, but columns cannot be taken from both
|
||||
at the same time. The vg_attr bits are: (w)riteable, (r)eadonly,
|
||||
resi(z)eable, e(x)ported, (p)artial.
|
||||
resi(z)eable, e(x)ported, (p)artial and (c)lustered.
|
||||
.TP
|
||||
.I \-O, \-\-sort
|
||||
Comma-separated ordered list of columns to sort by. Replaces the default
|
||||
|
||||
2800
po/lvm2.po
2800
po/lvm2.po
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,20 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the lvm2-cluster package.
|
||||
#
|
||||
# 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
|
||||
|
||||
#
|
||||
# Edit an lvm.conf file to adjust various properties
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
function usage
|
||||
{
|
||||
@@ -138,7 +149,7 @@ then
|
||||
if [ "$have_global" = "1" ]
|
||||
then
|
||||
echo "global keys but no 'global {' found, can't edit file"
|
||||
exit 12
|
||||
exit 13
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -161,7 +172,7 @@ EOF
|
||||
if [ $? != 0 ]
|
||||
then
|
||||
echo "failed to create temporary config file, $CONFIGFILE not updated"
|
||||
exit 1
|
||||
exit 14
|
||||
fi
|
||||
else
|
||||
#
|
||||
@@ -208,7 +219,7 @@ else
|
||||
if [ $? != 0 ]
|
||||
then
|
||||
echo "sed failed, $CONFIGFILE not updated"
|
||||
exit 1
|
||||
exit 15
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ xx(lvconvert,
|
||||
"\t[-m|--mirrors Mirrors]\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[--version]" "\n"
|
||||
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
|
||||
"\tLogicalVolume[Path] [PhysicalVolume[Path]...]\n",
|
||||
|
||||
alloc_ARG, mirrors_ARG, test_ARG)
|
||||
|
||||
|
||||
@@ -757,13 +757,16 @@ static int _status(int argc, char **argv, void *data)
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (!name)
|
||||
name = (char *) dm_task_get_name(dmt);
|
||||
|
||||
/* Fetch targets and print 'em */
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
/* Skip if target type doesn't match */
|
||||
if (_switches[TARGET_ARG] && target_type &&
|
||||
strcmp(target_type, _target))
|
||||
if (_switches[TARGET_ARG] &&
|
||||
(!target_type || strcmp(target_type, _target)))
|
||||
continue;
|
||||
if (ls_only) {
|
||||
if (!_switches[EXEC_ARG] || !_command ||
|
||||
@@ -1038,7 +1041,7 @@ static int _process_switches(int *argc, char ***argv)
|
||||
{"uuid", 1, &ind, UUID_ARG},
|
||||
{"verbose", 1, &ind, VERBOSE_ARG},
|
||||
{"version", 0, &ind, VERSION_ARG},
|
||||
{"", 0, NULL, 0}
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
#else
|
||||
struct option long_options;
|
||||
|
||||
@@ -52,19 +52,19 @@ static int lvchange_permission(struct cmd_context *cmd,
|
||||
|
||||
backup(lv->vg);
|
||||
|
||||
if (!suspend_lv(cmd, lv->lvid.s)) {
|
||||
if (!suspend_lv(cmd, lv)) {
|
||||
log_error("Failed to lock %s", lv->name);
|
||||
vg_revert(lv->vg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_commit(lv->vg)) {
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
resume_lv(cmd, lv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
|
||||
if (!resume_lv(cmd, lv->lvid.s)) {
|
||||
if (!resume_lv(cmd, lv)) {
|
||||
log_error("Problem reactivating %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -83,13 +83,13 @@ static int lvchange_availability(struct cmd_context *cmd,
|
||||
if (activate == CHANGE_ALN) {
|
||||
log_verbose("Deactivating logical volume \"%s\" locally",
|
||||
lv->name);
|
||||
if (!deactivate_lv_local(cmd, lv->lvid.s)) {
|
||||
if (!deactivate_lv_local(cmd, lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else if (activate == CHANGE_AN) {
|
||||
log_verbose("Deactivating logical volume \"%s\"", lv->name);
|
||||
if (!deactivate_lv(cmd, lv->lvid.s)) {
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -103,21 +103,21 @@ static int lvchange_availability(struct cmd_context *cmd,
|
||||
if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
|
||||
log_verbose("Activating logical volume \"%s\" "
|
||||
"exclusively", lv->name);
|
||||
if (!activate_lv_excl(cmd, lv->lvid.s)) {
|
||||
if (!activate_lv_excl(cmd, lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else if (activate == CHANGE_ALY) {
|
||||
log_verbose("Activating logical volume \"%s\" locally",
|
||||
lv->name);
|
||||
if (!activate_lv_local(cmd, lv->lvid.s)) {
|
||||
if (!activate_lv_local(cmd, lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
log_verbose("Activating logical volume \"%s\"",
|
||||
lv->name);
|
||||
if (!activate_lv(cmd, lv->lvid.s)) {
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ static int lvchange_availability(struct cmd_context *cmd,
|
||||
static int lvchange_refresh(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
{
|
||||
log_verbose("Refreshing logical volume \"%s\" (if active)", lv->name);
|
||||
if (!suspend_lv(cmd, lv->lvid.s) || !resume_lv(cmd, lv->lvid.s))
|
||||
if (!suspend_lv(cmd, lv) || !resume_lv(cmd, lv))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@@ -216,19 +216,19 @@ static int lvchange_readahead(struct cmd_context *cmd,
|
||||
|
||||
backup(lv->vg);
|
||||
|
||||
if (!suspend_lv(cmd, lv->lvid.s)) {
|
||||
if (!suspend_lv(cmd, lv)) {
|
||||
log_error("Failed to lock %s", lv->name);
|
||||
vg_revert(lv->vg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_commit(lv->vg)) {
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
resume_lv(cmd, lv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
|
||||
if (!resume_lv(cmd, lv->lvid.s)) {
|
||||
if (!resume_lv(cmd, lv)) {
|
||||
log_error("Problem reactivating %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -274,7 +274,7 @@ static int lvchange_persistent(struct cmd_context *cmd,
|
||||
active = 1;
|
||||
}
|
||||
log_verbose("Ensuring %s is inactive.", lv->name);
|
||||
if (!deactivate_lv(cmd, lv->lvid.s)) {
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("%s: deactivation failed", lv->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -286,7 +286,7 @@ static int lvchange_persistent(struct cmd_context *cmd,
|
||||
if (active) {
|
||||
log_verbose("Re-activating logical volume \"%s\"",
|
||||
lv->name);
|
||||
if (!activate_lv(cmd, lv->lvid.s)) {
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("%s: reactivation failed", lv->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -301,19 +301,19 @@ static int lvchange_persistent(struct cmd_context *cmd,
|
||||
|
||||
backup(lv->vg);
|
||||
|
||||
if (!suspend_lv(cmd, lv->lvid.s)) {
|
||||
if (!suspend_lv(cmd, lv)) {
|
||||
log_error("Failed to lock %s", lv->name);
|
||||
vg_revert(lv->vg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_commit(lv->vg)) {
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
resume_lv(cmd, lv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
|
||||
if (!resume_lv(cmd, lv->lvid.s)) {
|
||||
if (!resume_lv(cmd, lv)) {
|
||||
log_error("Problem reactivating %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -15,24 +15,56 @@
|
||||
#include "tools.h"
|
||||
|
||||
struct lvconvert_params {
|
||||
const char *lv_name;
|
||||
uint32_t mirrors;
|
||||
|
||||
alloc_policy_t alloc;
|
||||
|
||||
int pv_count;
|
||||
char **pvs;
|
||||
struct list *pvh;
|
||||
};
|
||||
|
||||
static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
|
||||
int argc, char **argv)
|
||||
{
|
||||
memset(lp, 0, sizeof(*lp));
|
||||
|
||||
lp->alloc = ALLOC_INHERIT;
|
||||
if (arg_count(cmd, alloc_ARG))
|
||||
lp->alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG,
|
||||
lp->alloc);
|
||||
|
||||
if (!arg_count(cmd, mirrors_ARG)) {
|
||||
log_error("--mirrors argument required");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
|
||||
|
||||
if (!argc) {
|
||||
log_error("Please give logical volume path");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp->lv_name = argv[0];
|
||||
argv++, argc--;
|
||||
|
||||
lp->pv_count = argc;
|
||||
lp->pvs = argv;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * lv,
|
||||
struct list *allocatable_pvs)
|
||||
struct lvconvert_params *lp)
|
||||
{
|
||||
struct lv_segment *first_seg;
|
||||
uint32_t mirrors, existing_mirrors;
|
||||
alloc_policy_t alloc = ALLOC_INHERIT;
|
||||
uint32_t existing_mirrors;
|
||||
// struct alloc_handle *ah = NULL;
|
||||
// struct logical_volume *log_lv;
|
||||
|
||||
if (arg_count(cmd, alloc_ARG))
|
||||
alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, alloc);
|
||||
|
||||
mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
|
||||
|
||||
if ((mirrors == 1)) {
|
||||
if ((lp->mirrors == 1)) {
|
||||
if (!(lv->status & MIRRORED)) {
|
||||
log_error("Logical volume %s is already not mirrored.",
|
||||
lv->name);
|
||||
@@ -53,13 +85,13 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
list_iterate_items(first_seg, &lv->segments)
|
||||
break;
|
||||
existing_mirrors = first_seg->area_count;
|
||||
if (mirrors == existing_mirrors) {
|
||||
if (lp->mirrors == existing_mirrors) {
|
||||
log_error("Logical volume %s already has %"
|
||||
PRIu32 " mirror(s).", lv->name,
|
||||
mirrors - 1);
|
||||
lp->mirrors - 1);
|
||||
return 1;
|
||||
}
|
||||
if (mirrors > existing_mirrors) {
|
||||
if (lp->mirrors > existing_mirrors) {
|
||||
/* FIXME Unless anywhere, remove PV of log_lv
|
||||
* from allocatable_pvs & allocate
|
||||
* (mirrors - existing_mirrors) new areas
|
||||
@@ -69,7 +101,7 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
"supported yet.");
|
||||
return 0;
|
||||
} else {
|
||||
if (!remove_mirror_images(first_seg, mirrors)) {
|
||||
if (!remove_mirror_images(first_seg, lp->mirrors)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -93,20 +125,20 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
|
||||
backup(lv->vg);
|
||||
|
||||
if (!suspend_lv(cmd, lv->lvid.s)) {
|
||||
if (!suspend_lv(cmd, lv)) {
|
||||
log_error("Failed to lock %s", lv->name);
|
||||
vg_revert(lv->vg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_commit(lv->vg)) {
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
resume_lv(cmd, lv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Updating \"%s\" in kernel", lv->name);
|
||||
|
||||
if (!resume_lv(cmd, lv->lvid.s)) {
|
||||
if (!resume_lv(cmd, lv)) {
|
||||
log_error("Problem reactivating %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -116,8 +148,8 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvconvert_single(struct cmd_context * cmd, struct logical_volume * lv,
|
||||
int argc, char **argv, void *handle)
|
||||
static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
struct lvconvert_params *lp = handle;
|
||||
|
||||
@@ -146,7 +178,7 @@ static int lvconvert_single(struct cmd_context * cmd, struct logical_volume * lv
|
||||
if (arg_count(cmd, mirrors_ARG)) {
|
||||
if (!archive(lv->vg))
|
||||
return ECMD_FAILED;
|
||||
if (!lvconvert_mirrors(cmd, lv, lp->pvh))
|
||||
if (!lvconvert_mirrors(cmd, lv, lp))
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
@@ -155,7 +187,7 @@ static int lvconvert_single(struct cmd_context * cmd, struct logical_volume * lv
|
||||
|
||||
int lvconvert(struct cmd_context * cmd, int argc, char **argv)
|
||||
{
|
||||
const char *vg_name, *lv_name;
|
||||
const char *vg_name;
|
||||
char *st;
|
||||
int consistent = 1;
|
||||
struct volume_group *vg;
|
||||
@@ -163,28 +195,20 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
|
||||
struct lvconvert_params lp;
|
||||
int ret = ECMD_FAILED;
|
||||
|
||||
if (!arg_count(cmd, mirrors_ARG)) {
|
||||
log_error("--mirrors argument required");
|
||||
if (!_read_params(&lp, cmd, argc, argv)) {
|
||||
stack;
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (!argc) {
|
||||
log_error("Please give logical volume path(s)");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
lv_name = argv[0];
|
||||
argv++, argc--;
|
||||
|
||||
vg_name = extract_vgname(cmd, lv_name);
|
||||
vg_name = extract_vgname(cmd, lp.lv_name);
|
||||
|
||||
if (!validate_name(vg_name)) {
|
||||
log_error("Please provide a valid volume group name");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if ((st = strrchr(lv_name, '/')))
|
||||
lv_name = st + 1;
|
||||
if ((st = strrchr(lp.lv_name, '/')))
|
||||
lp.lv_name = st + 1;
|
||||
|
||||
log_verbose("Checking for existing volume group \"%s\"", vg_name);
|
||||
|
||||
@@ -208,21 +232,22 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(lvl = find_lv_in_vg(vg, lv_name))) {
|
||||
if (!(lvl = find_lv_in_vg(vg, lp.lv_name))) {
|
||||
log_error("Logical volume \"%s\" not found in "
|
||||
"volume group \"%s\"", lv_name, vg_name);
|
||||
"volume group \"%s\"", lp.lv_name, vg_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (argc) {
|
||||
if (!(lp.pvh = create_pv_list(cmd->mem, vg, argc, argv, 1))) {
|
||||
if (lp.pv_count) {
|
||||
if (!(lp.pvh = create_pv_list(cmd->mem, vg, lp.pv_count,
|
||||
lp.pvs, 1))) {
|
||||
stack;
|
||||
goto error;
|
||||
}
|
||||
} else
|
||||
lp.pvh = &vg->pvs;
|
||||
|
||||
ret = lvconvert_single(cmd, lvl->lv, argc, argv, &lp);
|
||||
ret = lvconvert_single(cmd, lvl->lv, &lp);
|
||||
|
||||
error:
|
||||
unlock_vg(cmd, vg_name);
|
||||
|
||||
@@ -414,51 +414,9 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Volumes may be zeroed to remove old application data.
|
||||
*/
|
||||
static int _zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
{
|
||||
struct device *dev;
|
||||
char *name;
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* <clausen> also, more than 4k
|
||||
* <clausen> say, reiserfs puts it's superblock 32k in, IIRC
|
||||
* <ejt_> k, I'll drop a fixme to that effect
|
||||
* (I know the device is at least 4k, but not 32k)
|
||||
*/
|
||||
if (!(name = pool_alloc(cmd->mem, PATH_MAX))) {
|
||||
log_error("Name allocation failed - device not zeroed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir,
|
||||
lv->vg->name, lv->name) < 0) {
|
||||
log_error("Name too long - device not zeroed (%s)", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Zeroing start of logical volume \"%s\"", lv->name);
|
||||
|
||||
if (!(dev = dev_cache_get(name, NULL))) {
|
||||
log_error("%s: not found: device not zeroed", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_open_quiet(dev))
|
||||
return 0;
|
||||
|
||||
dev_zero(dev, UINT64_C(0), (size_t) 4096);
|
||||
dev_close_immediate(dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
{
|
||||
uint32_t size_rest, region_max;
|
||||
uint32_t size_rest;
|
||||
uint32_t status = 0;
|
||||
uint64_t tmp_size;
|
||||
struct volume_group *vg;
|
||||
@@ -497,7 +455,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lp->mirrors && !(vg->fid->fmt->features & FMT_SEGMENTS)) {
|
||||
if (lp->mirrors > 1 && !(vg->fid->fmt->features & FMT_SEGMENTS)) {
|
||||
log_error("Metadata does not support mirroring.");
|
||||
return 0;
|
||||
}
|
||||
@@ -548,6 +506,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
"device-mapper kernel driver");
|
||||
return 0;
|
||||
}
|
||||
/* FIXME Allow exclusive activation. */
|
||||
if (vg->status & CLUSTERED) {
|
||||
log_error("Clustered snapshots are not yet supported.");
|
||||
return 0;
|
||||
}
|
||||
if (!(org = find_lv(vg, lp->origin))) {
|
||||
log_err("Couldn't find origin volume '%s'.",
|
||||
lp->origin);
|
||||
@@ -614,39 +577,20 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
}
|
||||
|
||||
if (lp->mirrors > 1) {
|
||||
/* FIXME Adjust lp->region_size if necessary */
|
||||
region_max = (1 << (ffs(lp->extents) - 1)) * vg->extent_size;
|
||||
|
||||
if (region_max < lp->region_size) {
|
||||
lp->region_size = region_max;
|
||||
log_print("Using reduced mirror region size of %" PRIu32
|
||||
" sectors", lp->region_size);
|
||||
}
|
||||
lp->region_size = adjusted_mirror_region_size(vg->extent_size,
|
||||
lp->extents,
|
||||
lp->region_size);
|
||||
|
||||
/* FIXME Calculate how many extents needed for the log */
|
||||
|
||||
len = strlen(lv_name) + 32;
|
||||
if (!(log_name = alloca(len))) {
|
||||
if (!(log_name = alloca(len)) ||
|
||||
!(generate_log_name_format(vg, lv_name, log_name, len))) {
|
||||
log_error("log_name allocation failed. "
|
||||
"Remove new LV and retry.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(log_name, len, "%s_mlog", lv_name) < 0) {
|
||||
log_error("log_name allocation failed. "
|
||||
"Remove new LV and retry.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (find_lv_in_vg(vg, log_name)) {
|
||||
if (lvm_snprintf(log_name, len, "%s_mlog_%%d",
|
||||
lv_name) < 0) {
|
||||
log_error("log_name allocation failed. "
|
||||
"Remove new LV and retry.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(log_lv = lv_create_empty(vg->fid, log_name, NULL,
|
||||
VISIBLE_LV | LVM_READ | LVM_WRITE,
|
||||
lp->alloc, 0, vg))) {
|
||||
@@ -679,19 +623,19 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!activate_lv(cmd, log_lv->lvid.s)) {
|
||||
if (!activate_lv(cmd, log_lv)) {
|
||||
log_error("Aborting. Failed to activate mirror log. "
|
||||
"Remove new LVs and retry.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (activation() && !_zero_lv(cmd, log_lv)) {
|
||||
if (activation() && !zero_lv(cmd, log_lv)) {
|
||||
log_error("Aborting. Failed to wipe mirror log. "
|
||||
"Remove new LV and retry.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!deactivate_lv(cmd, log_lv->lvid.s)) {
|
||||
if (!deactivate_lv(cmd, log_lv)) {
|
||||
log_error("Aborting. Failed to deactivate mirror log. "
|
||||
"Remove new LV and retry.");
|
||||
goto error;
|
||||
@@ -767,7 +711,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!activate_lv(cmd, lv->lvid.s)) {
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
if (lp->snapshot)
|
||||
/* FIXME Remove the failed lv we just added */
|
||||
log_error("Aborting. Failed to activate snapshot "
|
||||
@@ -778,7 +722,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
}
|
||||
|
||||
if ((lp->zero || lp->snapshot) && activation()) {
|
||||
if (!_zero_lv(cmd, lv) && lp->snapshot) {
|
||||
if (!zero_lv(cmd, lv) && lp->snapshot) {
|
||||
/* FIXME Remove the failed lv we just added */
|
||||
log_error("Aborting. Failed to wipe snapshot "
|
||||
"exception store. Remove new LV and retry.");
|
||||
@@ -793,13 +737,13 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
/* Reset permission after zeroing */
|
||||
if (!(lp->permission & LVM_WRITE))
|
||||
lv->status &= ~LVM_WRITE;
|
||||
if (!deactivate_lv(cmd, lv->lvid.s)) {
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_err("Couldn't deactivate new snapshot.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME write/commit/backup sequence issue */
|
||||
if (!suspend_lv(cmd, org->lvid.s)) {
|
||||
if (!suspend_lv(cmd, org)) {
|
||||
log_error("Failed to suspend origin %s", org->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -814,7 +758,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
if (!vg_write(vg) || !vg_commit(vg))
|
||||
return 0;
|
||||
|
||||
if (!resume_lv(cmd, org->lvid.s)) {
|
||||
if (!resume_lv(cmd, org)) {
|
||||
log_error("Problem reactivating origin %s", org->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -350,21 +350,30 @@ int segtype_arg(struct cmd_context *cmd, struct arg *a)
|
||||
|
||||
char yes_no_prompt(const char *prompt, ...)
|
||||
{
|
||||
int c = 0;
|
||||
int c = 0, ret = 0;
|
||||
va_list ap;
|
||||
|
||||
while (c != 'y' && c != 'n') {
|
||||
if (c == '\n' || c == 0) {
|
||||
do {
|
||||
if (c == '\n' || !c) {
|
||||
va_start(ap, prompt);
|
||||
vprintf(prompt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
c = tolower(getchar());
|
||||
}
|
||||
|
||||
while (getchar() != '\n') ;
|
||||
if ((c = getchar()) == EOF) {
|
||||
ret = 'n';
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
c = tolower(c);
|
||||
if ((c == 'y') || (c == 'n'))
|
||||
ret = c;
|
||||
} while (!ret || c != '\n');
|
||||
|
||||
if (c != '\n')
|
||||
printf("\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __alloc(int size)
|
||||
|
||||
@@ -74,7 +74,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (!archive(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
if (!deactivate_lv(cmd, lv->lvid.s)) {
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Unable to deactivate logical volume \"%s\"",
|
||||
lv->name);
|
||||
return ECMD_FAILED;
|
||||
|
||||
@@ -158,18 +158,18 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
backup(lv->vg);
|
||||
|
||||
if (!suspend_lv(cmd, lv->lvid.s)) {
|
||||
if (!suspend_lv(cmd, lv)) {
|
||||
stack;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!vg_commit(vg)) {
|
||||
stack;
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
resume_lv(cmd, lv);
|
||||
goto error;
|
||||
}
|
||||
|
||||
resume_lv(cmd, lv->lvid.s);
|
||||
resume_lv(cmd, lv);
|
||||
|
||||
unlock_vg(cmd, vg_name);
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
|
||||
uint32_t extents_used = 0;
|
||||
uint32_t size_rest;
|
||||
alloc_policy_t alloc;
|
||||
char *lock_lvid;
|
||||
struct logical_volume *lock_lv;
|
||||
struct lv_list *lvl;
|
||||
int consistent = 1;
|
||||
struct lv_segment *seg;
|
||||
@@ -518,11 +518,11 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
|
||||
|
||||
/* If snapshot, must suspend all associated devices */
|
||||
if ((snap_seg = find_cow(lv)))
|
||||
lock_lvid = snap_seg->origin->lvid.s;
|
||||
lock_lv = snap_seg->origin;
|
||||
else
|
||||
lock_lvid = lv->lvid.s;
|
||||
lock_lv = lv;
|
||||
|
||||
if (!suspend_lv(cmd, lock_lvid)) {
|
||||
if (!suspend_lv(cmd, lock_lv)) {
|
||||
log_error("Failed to suspend %s", lp->lv_name);
|
||||
vg_revert(vg);
|
||||
return ECMD_FAILED;
|
||||
@@ -530,11 +530,11 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
|
||||
|
||||
if (!vg_commit(vg)) {
|
||||
stack;
|
||||
resume_lv(cmd, lock_lvid);
|
||||
resume_lv(cmd, lock_lv);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!resume_lv(cmd, lock_lvid)) {
|
||||
if (!resume_lv(cmd, lock_lv)) {
|
||||
log_error("Problem reactivating %s", lp->lv_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
@@ -170,6 +170,14 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
|
||||
log_print("Skipping mirror LV %s", lv->name);
|
||||
continue;
|
||||
}
|
||||
if (lv->status & MIRROR_LOG) {
|
||||
log_print("Skipping mirror log LV %s", lv->name);
|
||||
continue;
|
||||
}
|
||||
if (lv->status & MIRROR_IMAGE) {
|
||||
log_print("Skipping mirror image LV %s", lv->name);
|
||||
continue;
|
||||
}
|
||||
if (lv->status & LOCKED) {
|
||||
log_print("Skipping locked LV %s", lv->name);
|
||||
continue;
|
||||
@@ -211,7 +219,7 @@ static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
|
||||
|
||||
/* Suspend mirrors on subsequent calls */
|
||||
if (!first_time) {
|
||||
if (!suspend_lv(cmd, lv_mirr->lvid.s)) {
|
||||
if (!suspend_lv(cmd, lv_mirr)) {
|
||||
stack;
|
||||
resume_lvs(cmd, lvs_changed);
|
||||
vg_revert(vg);
|
||||
@@ -223,15 +231,16 @@ static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
|
||||
if (!vg_commit(vg)) {
|
||||
log_error("ABORTING: Volume group metadata update failed.");
|
||||
if (!first_time)
|
||||
resume_lv(cmd, lv_mirr->lvid.s);
|
||||
resume_lv(cmd, lv_mirr);
|
||||
resume_lvs(cmd, lvs_changed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Activate the temporary mirror LV */
|
||||
/* Only the first mirror segment gets activated as a mirror */
|
||||
/* FIXME: Add option to use a log */
|
||||
if (first_time) {
|
||||
if (!activate_lv(cmd, lv_mirr->lvid.s)) {
|
||||
if (!activate_lv_excl(cmd, lv_mirr)) {
|
||||
if (!test_mode())
|
||||
log_error("ABORTING: Temporary mirror "
|
||||
"activation failed. "
|
||||
@@ -240,7 +249,7 @@ static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
|
||||
resume_lvs(cmd, lvs_changed);
|
||||
return 0;
|
||||
}
|
||||
} else if (!resume_lv(cmd, lv_mirr->lvid.s)) {
|
||||
} else if (!resume_lv(cmd, lv_mirr)) {
|
||||
log_error("Unable to reactivate logical volume \"%s\"",
|
||||
lv_mirr->name);
|
||||
resume_lvs(cmd, lvs_changed);
|
||||
@@ -309,7 +318,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
|
||||
}
|
||||
|
||||
/* Ensure mirror LV is active */
|
||||
if (!activate_lv(cmd, lv_mirr->lvid.s)) {
|
||||
if (!activate_lv_excl(cmd, lv_mirr)) {
|
||||
log_error
|
||||
("ABORTING: Temporary mirror activation failed.");
|
||||
unlock_vg(cmd, pv->vg_name);
|
||||
@@ -406,7 +415,7 @@ static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
|
||||
}
|
||||
|
||||
/* Suspend mirror LV to flush pending I/O */
|
||||
if (!suspend_lv(cmd, lv_mirr->lvid.s)) {
|
||||
if (!suspend_lv(cmd, lv_mirr)) {
|
||||
log_error("Suspension of temporary mirror LV failed");
|
||||
r = 0;
|
||||
}
|
||||
@@ -416,13 +425,13 @@ static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
|
||||
log_error("ABORTING: Failed to write new data locations "
|
||||
"to disk.");
|
||||
vg_revert(vg);
|
||||
resume_lv(cmd, lv_mirr->lvid.s);
|
||||
resume_lv(cmd, lv_mirr);
|
||||
resume_lvs(cmd, lvs_changed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Release mirror LV. (No pending I/O because it's been suspended.) */
|
||||
if (!resume_lv(cmd, lv_mirr->lvid.s)) {
|
||||
if (!resume_lv(cmd, lv_mirr)) {
|
||||
log_error("Unable to reactivate logical volume \"%s\"",
|
||||
lv_mirr->name);
|
||||
r = 0;
|
||||
@@ -432,7 +441,7 @@ static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
|
||||
resume_lvs(cmd, lvs_changed);
|
||||
|
||||
/* Deactivate mirror LV */
|
||||
if (!deactivate_lv(cmd, lv_mirr->lvid.s)) {
|
||||
if (!deactivate_lv(cmd, lv_mirr)) {
|
||||
log_error("ABORTING: Unable to deactivate temporary logical "
|
||||
"volume \"%s\"", lv_mirr->name);
|
||||
r = 0;
|
||||
|
||||
@@ -35,7 +35,9 @@ static int _vgs_single(struct cmd_context *cmd, const char *vg_name,
|
||||
static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV))
|
||||
/* FIXME Avoid snapshot special-case */
|
||||
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV) &&
|
||||
!(lv_is_cow(lv)))
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL))
|
||||
@@ -81,7 +83,9 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV))
|
||||
/* FIXME Avoid snapshot special-case */
|
||||
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV) &&
|
||||
!(lv_is_cow(lv)))
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
return process_each_segment_in_lv(cmd, lv, handle, _segs_single);
|
||||
|
||||
@@ -1057,3 +1057,64 @@ int validate_vg_name(struct cmd_context *cmd, const char *vg_name)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int generate_log_name_format(struct volume_group *vg, const char *lv_name,
|
||||
char *buffer, size_t size)
|
||||
{
|
||||
if (lvm_snprintf(buffer, size, "%s_mlog", lv_name) < 0) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (find_lv_in_vg(vg, buffer) &&
|
||||
lvm_snprintf(buffer, size, "%s_mlog_%%d",
|
||||
lv_name) < 0) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Volumes may be zeroed to remove old application data.
|
||||
*/
|
||||
int zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
{
|
||||
struct device *dev;
|
||||
char *name;
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* <clausen> also, more than 4k
|
||||
* <clausen> say, reiserfs puts it's superblock 32k in, IIRC
|
||||
* <ejt_> k, I'll drop a fixme to that effect
|
||||
* (I know the device is at least 4k, but not 32k)
|
||||
*/
|
||||
if (!(name = pool_alloc(cmd->mem, PATH_MAX))) {
|
||||
log_error("Name allocation failed - device not zeroed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir,
|
||||
lv->vg->name, lv->name) < 0) {
|
||||
log_error("Name too long - device not zeroed (%s)", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Zeroing start of logical volume \"%s\"", lv->name);
|
||||
|
||||
if (!(dev = dev_cache_get(name, NULL))) {
|
||||
log_error("%s: not found: device not zeroed", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_open_quiet(dev))
|
||||
return 0;
|
||||
|
||||
dev_zero(dev, UINT64_C(0), (size_t) 4096);
|
||||
dev_close_immediate(dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,4 +94,9 @@ int apply_lvname_restrictions(const char *name);
|
||||
|
||||
int validate_vg_name(struct cmd_context *cmd, const char *vg_name);
|
||||
|
||||
int generate_log_name_format(struct volume_group *vg, const char *lv_name,
|
||||
char *buffer, size_t size);
|
||||
|
||||
int zero_lv(struct cmd_context *cmd, struct logical_volume *lv);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,18 +37,18 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
|
||||
continue;
|
||||
|
||||
if (activate == CHANGE_AN) {
|
||||
if (!deactivate_lv(cmd, lv->lvid.s))
|
||||
if (!deactivate_lv(cmd, lv))
|
||||
continue;
|
||||
} else if (activate == CHANGE_ALN) {
|
||||
if (!deactivate_lv_local(cmd, lv->lvid.s))
|
||||
if (!deactivate_lv_local(cmd, lv))
|
||||
continue;
|
||||
} else if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
|
||||
if (!activate_lv_excl(cmd, lv->lvid.s))
|
||||
if (!activate_lv_excl(cmd, lv))
|
||||
continue;
|
||||
} else if (activate == CHANGE_ALY) {
|
||||
if (!activate_lv_local(cmd, lv->lvid.s))
|
||||
if (!activate_lv_local(cmd, lv))
|
||||
continue;
|
||||
} else if (!activate_lv(cmd, lv->lvid.s))
|
||||
} else if (!activate_lv(cmd, lv))
|
||||
continue;
|
||||
|
||||
if ((lv->status & PVMOVE) &&
|
||||
@@ -182,6 +182,7 @@ static int _vgchange_clustered(struct cmd_context *cmd,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
int clustered = !strcmp(arg_str_value(cmd, clustered_ARG, "n"), "y");
|
||||
struct lv_list *lvl;
|
||||
|
||||
if (clustered && (vg->status & CLUSTERED)) {
|
||||
log_error("Volume group \"%s\" is already clustered",
|
||||
@@ -195,6 +196,17 @@ static int _vgchange_clustered(struct cmd_context *cmd,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (clustered) {
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lvl->lv->origin_count || lvl->lv->snapshot) {
|
||||
log_error("Volume group %s contains snapshots "
|
||||
"that are not yet supported.",
|
||||
vg->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!archive(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ static int _remove_lv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
log_verbose("Deactivating (if active) logical volume %s",
|
||||
lv->name);
|
||||
|
||||
if (!deactivate_lv(cmd, lv->lvid.s)) {
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Failed to deactivate LV %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ static int _remove_lv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
log_verbose("Deactivating (if active) logical volume %s "
|
||||
"(origin of %s)", snap_seg->origin->name, lv->name);
|
||||
|
||||
if (!deactivate_lv(cmd, snap_seg->origin->lvid.s)) {
|
||||
if (!deactivate_lv(cmd, snap_seg->origin)) {
|
||||
log_error("Failed to deactivate LV %s",
|
||||
snap_seg->origin->name);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user