1
0
mirror of git://sourceware.org/git/lvm2.git synced 2026-01-06 08:32:48 +03:00

Compare commits

..

61 Commits

Author SHA1 Message Date
Alasdair Kergon
893ec9a302 1.01.05 2005-09-26 20:44:12 +00:00
Alasdair Kergon
05f65c38e6 Fix chunksize field in reports. 2005-09-23 17:06:01 +00:00
Alasdair Kergon
2e9d062ec0 Don't hide snapshots from default 'lvs' output. 2005-09-23 16:22:17 +00:00
Alasdair Kergon
6b0b394e61 Resync list.h with LVM2. 2005-09-22 12:06:34 +00:00
Alasdair Kergon
25621396c9 Remember increased buffer size and use for subsequent calls. 2005-09-20 18:04:28 +00:00
Alasdair Kergon
82aa0271f3 Explicitly initialise no_open_count 2005-09-20 16:39:12 +00:00
Alasdair Kergon
653cab13f8 On 'buffer full' condition, double buffer size and repeat ioctl. [Untested] 2005-09-19 14:29:17 +00:00
Alasdair Kergon
b526f86b49 Add is_dm_major() for use in duplicate device detection in lvmcache_add(). 2005-09-16 18:53:01 +00:00
Alasdair Kergon
53c0f00888 Really switch device number in lvmcache when it says it is doing so. 2005-09-16 18:44:52 +00:00
Alasdair Kergon
f0c4d9de40 Option for bitset memory allocation using malloc as well as pool. 2005-09-16 18:40:53 +00:00
Alasdair Kergon
03ef8cec83 Don't assume exactly two mirrors when parsing mirror status 2005-09-02 16:59:46 +00:00
Alasdair Kergon
85f2a2e8c2 Suppress fsync() error message on filesystems that don't support it. 2005-09-01 18:37:22 +00:00
Alasdair Kergon
584b3e6642 Fix yes_no_prompt() error handling. 2005-08-31 19:32:10 +00:00
Alasdair Kergon
39b7ef841d add comments to example conf file to warn about common filter line mistakes 2005-08-31 15:05:47 +00:00
Alasdair Kergon
aa16a9098d Fix termination of getopt_long() option array. 2005-08-18 19:40:19 +00:00
Alasdair Kergon
7b8c2707bc lvmconf.sh 2005-08-16 20:42:28 +00:00
Alasdair Kergon
60e26a31a7 Add copyright notice to lvmconf.sh and use unique exit codes. 2005-08-16 20:38:33 +00:00
Alasdair Kergon
3473c25c14 Add format1 dev_write debug messages. 2005-08-16 19:00:55 +00:00
Patrick Caulfield
e52f022026 clvmd no longer takes out locks for non-clusteed LVs,
and non-clustered LVs are only activated on the local node.
2005-08-16 08:25:09 +00:00
Alasdair Kergon
b1a7df8e43 Add clustered VG attribute to report. 2005-08-15 23:34:11 +00:00
Alasdair Kergon
0fd2479b7c Move lvconvert parameters into struct lvconvert_params. 2005-08-15 14:10:28 +00:00
Alasdair Kergon
273857f914 Add clustered VG flag to LV lock requests. 2005-08-15 13:24:46 +00:00
Alasdair Kergon
a08b85dbc8 Change LV locking macros to take lv instead of lvid. 2005-08-15 12:00:04 +00:00
Alasdair Kergon
a0aedf299a Prepare tools to support clustered mirrors. 2005-08-14 23:18:28 +00:00
Alasdair Kergon
3c61426844 Factor out generate_log_name_format(). 2005-08-12 20:02:21 +00:00
Alasdair Kergon
786f228076 Factor out adjusted_mirror_region_size() 2005-08-12 19:23:08 +00:00
Alasdair Kergon
004da28792 Move compose_log_line() into mirror directory. 2005-08-10 17:19:46 +00:00
Alasdair Kergon
6e2be6efb6 Don't kill idling clvmd threads. 2005-08-09 17:29:04 +00:00
Alasdair Kergon
a994dfcfbc Factor out _get_library_path(). 2005-08-09 17:24:21 +00:00
Patrick Caulfield
7a8ea2ac93 Don't send a signal to kill threads that are idling nicely as it upsets them.
This seems to cure bz#159727 on SMP systems.

Alasdair, can you include this patch in the lvm2-cluster package please ?
2005-08-09 10:39:57 +00:00
Alasdair Kergon
0da3965d19 Report 'buffer full' condition with v4 ioctl as well as with v1. 2005-08-08 18:40:17 +00:00
Alasdair Kergon
885fd7bb46 aoe 2005-08-08 17:55:35 +00:00
Alasdair Kergon
08771f9c89 Recognise aoe devices. 2005-08-08 17:54:23 +00:00
Alasdair Kergon
8be48195a5 post-release 2005-08-04 02:07:34 +00:00
Alasdair Kergon
98ce2d650e update po 2005-08-04 02:02:37 +00:00
Alasdair Kergon
3af327116a Fix lvconvert PV parameter in help string. 2005-08-04 01:50:17 +00:00
Alasdair Kergon
b75434db93 fix last checkin 2005-08-04 01:29:18 +00:00
Alasdair Kergon
04e912aacd Prevent snapshots getting activated in a clustered VG. 2005-08-04 01:27:25 +00:00
Alasdair Kergon
d7be352f87 Separate out _build_dev_string. 2005-08-04 01:15:30 +00:00
Alasdair Kergon
96be3ec22c Move zero_lv to toollib. 2005-08-04 01:14:36 +00:00
Alasdair Kergon
32e7e0d790 post-release 2005-08-02 21:46:49 +00:00
Alasdair Kergon
becc320e62 update vsn 2005-08-02 18:00:32 +00:00
Alasdair Kergon
7666ed57d1 Fix dmsetup ls -j and status --target with empty table. 2005-07-29 16:11:23 +00:00
AJ Lewis
5e61d0955e fix pool format handler to work with pvseg code 2005-07-26 21:48:18 +00:00
Alasdair Kergon
e8a4662ae7 post-release 2005-07-13 19:28:09 +00:00
Alasdair Kergon
a48da3bd3b update po 2005-07-13 19:23:48 +00:00
Alasdair Kergon
5f1a5d7b99 2.01.13 2005-07-13 19:15:09 +00:00
Alasdair Kergon
3e28a9db8f Fix pvmove segment splitting.
Abstract vg_validate.
2005-07-12 19:40:59 +00:00
Alasdair Kergon
ebf6071d77 Only make one attempt at contiguous allocation. 2005-07-12 14:50:45 +00:00
Alasdair Kergon
47a35fb9fb Fix lvm1 format metadata read. 2005-06-22 15:31:29 +00:00
Alasdair Kergon
48e88aba44 fix lvm1 non-mirror lvcreate 2005-06-22 14:56:14 +00:00
Benjamin Marzinski
b85f99c140 Fixing some makesfiles, so that the correct things link against pthreads.
Also changed dmevent so that in no longer links against pthreads, and
dynamically loads libdmevent.so.  Everything seems to work just fine like this.
2005-06-14 19:06:26 +00:00
Alasdair Kergon
0a5e0e1f71 preset pl to NULL 2005-06-14 18:29:12 +00:00
Alasdair Kergon
85dc22ebb7 missing fn defs 2005-06-14 18:22:31 +00:00
Alasdair Kergon
5c21526009 post-release 2005-06-14 18:22:22 +00:00
Alasdair Kergon
14dff1cefc 2.01.12 2005-06-14 17:59:57 +00:00
Alasdair Kergon
39fbb844f9 Various allocation-related pvmove fixes. 2005-06-14 17:54:48 +00:00
Patrick Caulfield
ca4e0c973a Log an error if clvmd can't resolve a host name got from CCS
Fix potential spin loop in clvmd
2005-06-14 10:35:02 +00:00
Alasdair Kergon
ecb42bee80 post-release 2005-06-13 14:53:07 +00:00
Alasdair Kergon
674ed2a9f3 2.01.11 2005-06-13 14:43:28 +00:00
Alasdair Kergon
252daf9717 Use matchpathcon mode parameter. 2005-06-13 13:13:15 +00:00
69 changed files with 2609 additions and 1685 deletions

View File

@@ -1 +1 @@
2.01.11-cvs (2005-05-03)
2.01.15-cvs (2005-08-04)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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/.*/" ]

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -57,6 +57,7 @@ static struct flag _lv_flags[] = {
{MIRRORED, NULL},
{VIRTUAL, NULL},
{SNAPSHOT, NULL},
{ACTIVATE_EXCL, NULL},
{0, NULL}
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -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, &params);
/* 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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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