1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-12-24 16:23:50 +03:00

Compare commits

..

76 Commits

Author SHA1 Message Date
Alasdair Kergon
e366b68ad3 pre-release 2007-04-27 20:47:14 +00:00
Alasdair Kergon
fb94fb980a Fix get_config_uint64() to read a 64-bit value not a 32-bit one. 2007-04-27 20:41:50 +00:00
Alasdair Kergon
b10cc18f53 Add -Wformat-security and change one fprintf() to fputs(). 2007-04-27 19:26:57 +00:00
Alasdair Kergon
a249de3b72 Standardise protective include file #defines. 2007-04-27 19:07:43 +00:00
Alasdair Kergon
d04e972d65 Move regex functions into libdevmapper. 2007-04-27 18:52:05 +00:00
Alasdair Kergon
b9f5a18a76 Add regex functions to library. 2007-04-27 18:40:23 +00:00
Alasdair Kergon
d3f157f08a configure.h isn't a system header 2007-04-27 18:01:45 +00:00
Alasdair Kergon
2294fdb496 Change some #include lines to search only standard system directories. 2007-04-27 17:46:16 +00:00
Alasdair Kergon
d7ba0e01a5 Avoid trailing separator in reports when there are hidden sort fields. 2007-04-27 15:22:27 +00:00
Alasdair Kergon
b6172b53fd Fix segfault in 'dmsetup status' without --showkeys against crypt target. [nec] 2007-04-27 15:12:26 +00:00
Alasdair Kergon
477ec611d5 Deal with some more compiler warnings. Hope this doesn't break anything... 2007-04-27 14:52:41 +00:00
Alasdair Kergon
b6194edd67 add preferred_names to man page. 2007-04-26 17:14:57 +00:00
Alasdair Kergon
dcdbbb3ecb Add devices/preferred_names config regex list for displayed device names.
Free a temporary dir string in fcntl_lock_file() after use.
Fix a dm_pool_destroy() in matcher_create().
Introduce goto_bad macro.
2007-04-26 16:44:59 +00:00
Dave Wysochanski
7ef99ee4e6 Fix warnings on x86_64 involving ptrdiff_t:
config/config.c:493: warning: format '%d' expects type 'int', but argument 5 has type 'long int'

Modified original patch from Jim Meyering <jim@meyering.net>
2007-04-26 16:40:46 +00:00
Dave Wysochanski
1ac1418286 Update pvck to include text metadata area and record detection.
--
2007-04-25 21:10:55 +00:00
Dave Wysochanski
8fc854f38e Add support functions for analysis of config sections,
and hence, on-disk LVM2 metadata.

--
2007-04-25 20:38:39 +00:00
Dave Wysochanski
1c2360b335 Update pvck to read labels on disk, with flexible --labelsector
parameter.

--
2007-04-25 20:03:16 +00:00
Dave Wysochanski
dd4477406b Add count_chars and count_chars_len functions, two
generic string utility functions.

--
2007-04-25 18:24:19 +00:00
Bryn M. Reeves
9d67bbb104 Make lvm_dump.sh capture a listing of /sys/block entries. 2007-04-25 14:49:27 +00:00
Patrick Caulfield
d6c8e1df61 Fix thread race in clvmd. 2007-04-24 15:13:13 +00:00
Petr Rockai
5ec7c8fece Fix the regression introduced by dmeventd leak fixes. 2007-04-24 13:29:02 +00:00
Dave Wysochanski
86b21eaf83 Add 'scan_sector' parameter to label_read and _find_labeller to add
flexibility in searching for disk labels.
2007-04-23 18:21:01 +00:00
Petr Rockai
228486a971 Fix some memory leaks in dmeventd. 2007-04-23 15:06:03 +00:00
Patrick Caulfield
88c0caab26 Make clvmd cope with quorum devices in RHEL5
bz#237386
2007-04-23 14:55:28 +00:00
Bryn M. Reeves
5cd4679419 re-commit lvm_dump.sh change 2007-04-19 23:06:05 +00:00
Bryn M. Reeves
eeed5e0d19 Make lvm_dump.sh list /dev recursively to aid identifying devices. 2007-04-19 22:56:16 +00:00
Alasdair Kergon
369ab1e0b2 Introduce _add_field() and _is_same_field() to libdm-report.c. 2007-04-19 20:24:00 +00:00
Milan Broz
2e21519a10 Fix libdevmapper-event memory leaks 2007-04-19 19:10:19 +00:00
Dave Wysochanski
ecc001ed08 Add dev_read_circular, read 2 regions on same device. 2007-04-19 02:10:42 +00:00
Dave Wysochanski
cd96852696 Add stub for pvck, a command to check physical volume consistency. 2007-03-30 21:00:26 +00:00
Patrick Caulfield
b9f7f30158 Add some extra error checking & robustness.
Thanks to the Crosswalk engineering team:
    Leonard Maiorani
    Henry Harris
    Scott Cannata
2007-03-29 13:59:33 +00:00
Alasdair Kergon
ca5e423331 Update lists of attribute characters in man pages.
Change cling alloc policy attribute character from 'C' to l'.
2007-03-27 13:35:33 +00:00
Milan Broz
fa9407089c Fix creation and conversion of mirrors with tags. 2007-03-26 16:10:10 +00:00
Milan Broz
66f28e193a Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
Split metadata areas in vgsplit properly.
2007-03-23 12:43:17 +00:00
Alasdair Kergon
0d93f89f5c post-release 2007-03-19 21:16:49 +00:00
Alasdair Kergon
154e9a2c47 pre-release 2007-03-19 21:12:54 +00:00
Milan Broz
84574a1257 Fix processing of exit status in init scripts 2007-03-16 17:15:36 +00:00
Alasdair Kergon
bf83527b64 Remove unnecessary memset() return value checks. [Jim Meyering] 2007-03-16 14:36:14 +00:00
Milan Broz
12c53622a0 Fix vgremove to require at least one vg argument. 2007-03-15 14:00:30 +00:00
Alasdair Kergon
d8f54cf891 Try to fix reading in of lvm1 striped LVs.
There are two fixes other than improving variable names and updating code
layout etc.
The loop counter is incremented by area_len instead of area_len * stripes;
the 3rd _check_stripe parameter is no longer multiplied by number of stripes.
2007-03-15 13:38:28 +00:00
Patrick Caulfield
625a671189 Flag nolocking as a clustered locking module as we need to be able
to look at clustered LVs at clvmd startup
2007-03-13 14:59:21 +00:00
Alasdair Kergon
6ebdad3102 Add a few missing pieces of vgname command line validation. 2007-03-09 21:25:33 +00:00
Alasdair Kergon
9a8f21aa03 Support the /dev/mapper prefix on most command lines. 2007-03-09 20:47:41 +00:00
Alasdair Kergon
291dd8edc2 post-release 2007-03-08 21:37:48 +00:00
Alasdair Kergon
de4c1daf29 pre-release 2007-03-08 21:28:13 +00:00
Alasdair Kergon
0b55d7d0d8 Fix vgrename active LV check to ignore differing vgids. 2007-03-08 21:08:25 +00:00
Alasdair Kergon
5d86fd8fdb Remove no-longer-used uuid_out parameter from activation info functions. 2007-03-08 19:58:04 +00:00
Alasdair Kergon
1b76eb1f59 Fix two more segfaults if an empty config file section encountered. 2007-03-08 19:22:52 +00:00
Alasdair Kergon
b05678d8bf Move .cache file into a new /etc/lvm/cache directory by default.
Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
Create directory in fcntl_lock_file() if required.
2007-02-28 18:27:13 +00:00
Alasdair Kergon
781f4971c6 Exclude readline support from lvm.static 2007-02-14 16:51:48 +00:00
Alasdair Kergon
d02ac7b99a Fix a leak in a reporting error path. 2007-02-14 15:18:31 +00:00
Alasdair Kergon
b1b6c97f7c Fix a few leaks in reporting error paths. 2007-02-14 15:12:16 +00:00
Alasdair Kergon
baee28ab5c post-release 2007-02-13 16:16:15 +00:00
Alasdair Kergon
83edf68ff9 pre-release 2007-02-13 16:12:24 +00:00
Alasdair Kergon
c7588f91dd Correct -b and -P on a couple of man pages.
Add global/units to example.conf.
2007-02-13 16:04:01 +00:00
Alasdair Kergon
30b432adc5 Fix loading of segment_libraries. [gentoo] 2007-02-08 17:31:02 +00:00
Alasdair Kergon
7c9733eb5d If a PV reappears after it was removed from its VG, make it an orphan. 2007-02-07 13:29:52 +00:00
Alasdair Kergon
a223c3fea3 Improve dmeventd messaging protocol: drain pipe and tag messages. 2007-02-02 17:08:51 +00:00
Alasdair Kergon
d5250f4901 Fix some &->&& vgreduce cmdline validation. [Andre Noll] 2007-01-31 16:26:23 +00:00
Alasdair Kergon
25f29f4712 post-release 2007-01-30 21:37:18 +00:00
Alasdair Kergon
382af5563d pre-release 2007-01-30 18:08:17 +00:00
Alasdair Kergon
8cf3d165d3 Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring. 2007-01-30 18:02:15 +00:00
Alasdair Kergon
0fd6ce546f Fix vgsplit to handle mirrors.
Reorder fields in reporting field definitions.
2007-01-29 23:01:18 +00:00
Alasdair Kergon
b881c372bc post-release 2007-01-29 20:25:19 +00:00
Alasdair Kergon
94c5e7deb0 pre-release 2007-01-29 19:57:24 +00:00
Alasdair Kergon
c344766f3c Add recent reporting options to dmsetup man page.
Revise some report fields names.
2007-01-29 19:35:24 +00:00
Alasdair Kergon
67895de0bc help on help 2007-01-29 18:45:08 +00:00
Alasdair Kergon
ff00cb6990 help unused attr 2007-01-29 18:43:27 +00:00
Alasdair Kergon
2cc75c11ed add help -c for field list 2007-01-29 18:37:57 +00:00
Alasdair Kergon
cd79e58eda Add dmsetup 'help' command and update usage text. 2007-01-29 18:18:41 +00:00
Alasdair Kergon
6fa801f3d8 reorder report field definitions 2007-01-29 17:45:32 +00:00
Alasdair Kergon
684eecba1d Use fixed-size fields in report interface. 2007-01-29 17:23:54 +00:00
Alasdair Kergon
da9cf7e5de fix pvsegs report too 2007-01-27 02:32:31 +00:00
Alasdair Kergon
f57e7445fd Fix vgs to treat args as VGs even when PV fields are displayed. 2007-01-27 02:09:06 +00:00
Alasdair Kergon
fba1388719 Fix md signature check to handle both endiannesses. 2007-01-26 17:15:16 +00:00
Alasdair Kergon
80ed029c17 post-release 2007-01-25 23:40:33 +00:00
108 changed files with 5366 additions and 3409 deletions

View File

@@ -1 +1 @@
2.02.20-cvs (2007-01-25)
2.02.25-cvs (2007-04 27)

View File

@@ -1,3 +1,69 @@
Version 2.02.25 - 27th April 2007
=================================
Fix get_config_uint64() to read a 64-bit value not a 32-bit one.
Add -Wformat-security and change one fprintf() to fputs().
Move regex functions into libdevmapper.
Change some #include lines to search only standard system directories.
Add devices/preferred_names config regex list for displayed device names.
Free a temporary dir string in fcntl_lock_file() after use.
Fix a dm_pool_destroy() in matcher_create().
Introduce goto_bad macro.
Fix warnings on x86_64 involving ptrdiff_t in log_error messages.
Update pvck to include text metadata area and record detection.
Add support functions for token counting in config file extracts.
Update pvck to read labels on disk, with --labelsector parameter.
Add count_chars and count_chars_len functions.
Add /sys/block listings to lvm_dump.sh.
Make lvm_dump.sh list /dev recursively.
Fix thread race in clvmd.
Add scan_sector param to label_read and _find_labeller.
Make clvmd cope with quorum devices.
Add extra internal error checking to clvmd.
Add dev_read_circular.
Add pvck command stub.
Update lists of attribute characters in man pages.
Change cling alloc policy attribute character from 'C' to l'.
Fix creation and conversion of mirrors with tags.
Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
Split metadata areas in vgsplit properly.
Version 2.02.24 - 19th March 2007
=================================
Fix processing of exit status in init scripts
Fix vgremove to require at least one vg argument.
Fix reading of striped LVs in LVM1 format.
Flag nolocking as clustered so clvmd startup sees clustered LVs. (2.02.10)
Add a few missing pieces of vgname command line validation.
Support the /dev/mapper prefix on most command lines.
Version 2.02.23 - 8th March 2007
================================
Fix vgrename active LV check to ignore differing vgids.
Remove no-longer-used uuid_out parameter from activation info functions.
Fix two more segfaults if an empty config file section encountered.
Move .cache file into a new /etc/lvm/cache directory by default.
Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
Create directory in fcntl_lock_file() if required.
Exclude readline support from lvm.static.
Fix a leak in a reporting error path (2.02.19).
Version 2.02.22 - 13th February 2007
====================================
Correct -b and -P on a couple of man pages.
Add global/units to example.conf.
Fix loading of segment_libraries.
If a PV reappears after it was removed from its VG, make it an orphan.
Don't update metadata automatically if VGIDs don't match.
Fix some vgreduce --removemissing command line validation.
Version 2.02.21 - 30th January 2007
===================================
Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
Fix vgsplit to handle mirrors.
Reorder fields in reporting field definitions.
Fix vgs to treat args as VGs even when PV fields are displayed.
Fix md signature check to handle both endiannesses.
Version 2.02.20 - 25th January 2007
===================================
dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.

View File

@@ -1,3 +1,26 @@
Version 1.02.19 - 27th April 2007
=================================
Standardise protective include file #defines.
Add regex functions to library.
Avoid trailing separator in reports when there are hidden sort fields.
Fix segfault in 'dmsetup status' without --showkeys against crypt target.
Deal with some more compiler warnings.
Introduce _add_field() and _is_same_field() to libdm-report.c.
Fix some libdevmapper-event and dmeventd memory leaks.
Remove unnecessary memset() return value checks.
Fix a few leaks in reporting error paths. [1.02.15+]
Version 1.02.18 - 13th February 2007
====================================
Improve dmeventd messaging protocol: drain pipe and tag messages.
Version 1.02.17 - 29th January 2007
===================================
Add recent reporting options to dmsetup man page.
Revise some report fields names.
Add dmsetup 'help' command and update usage text.
Use fixed-size fields in report interface and reorder.
Version 1.02.16 - 25th January 2007
===================================
Add some missing close() and fclose() return value checks.

View File

@@ -36,10 +36,10 @@
#include <fcntl.h>
#include <getopt.h>
#include <errno.h>
#include <libdlm.h>
#include "clvmd-comms.h"
#include "clvm.h"
#include "libdlm.h"
#include "log.h"
#include "clvmd.h"
#include "lvm-functions.h"
@@ -121,7 +121,7 @@ static int _get_num_nodes()
/* return number of ACTIVE nodes */
for (i=0; i<num_nodes; i++) {
if (nodes[i].cn_member)
if (nodes[i].cn_member && nodes[i].cn_nodeid)
nnodes++;
}
return nnodes;
@@ -159,7 +159,7 @@ static int _cluster_do_node_callback(struct local_client *client,
int somedown = 0;
for (i = 0; i < _get_num_nodes(); i++) {
if (nodes[i].cn_member) {
if (nodes[i].cn_member && nodes[i].cn_nodeid) {
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
if (!node_updown[nodes[i].cn_nodeid])
somedown = -1;
@@ -168,8 +168,7 @@ static int _cluster_do_node_callback(struct local_client *client,
return somedown;
}
/* Process OOB message from the cluster socket,
this currently just means that a node has stopped listening on our port */
/* Process OOB messages from the cluster socket */
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
{
char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];

View File

@@ -64,8 +64,9 @@
#include <stddef.h>
#include <unistd.h>
#include <errno.h>
#include <libdevmapper.h>
#include <libdlm.h>
#include "libdevmapper.h"
#include "list.h"
#include "locking.h"
#include "log.h"
@@ -73,7 +74,6 @@
#include "clvmd-comms.h"
#include "clvm.h"
#include "clvmd.h"
#include "libdlm.h"
extern struct cluster_ops *clops;

View File

@@ -40,9 +40,10 @@
#include <utmpx.h>
#include <syslog.h>
#include <assert.h>
#include <libdevmapper.h>
#include <ccs.h>
#include <libgulm.h>
#include "libdevmapper.h"
#include "ccs.h"
#include "list.h"
#include "locking.h"
#include "log.h"
@@ -51,7 +52,6 @@
#include "lvm-functions.h"
#include "clvmd.h"
#include "clvmd-gulm.h"
#include "libgulm.h"
/* Hash list of nodes in the cluster */
static struct dm_hash_table *node_hash;

View File

@@ -37,6 +37,7 @@
#include <getopt.h>
#include <syslog.h>
#include <errno.h>
#include <libdlm.h>
#include "clvmd-comms.h"
#include "lvm-functions.h"
@@ -44,7 +45,6 @@
#include "version.h"
#include "clvmd.h"
#include "refresh_clvmd.h"
#include "libdlm.h"
#include "system-lv.h"
#include "list.h"
#include "log.h"
@@ -56,6 +56,8 @@
#define FALSE 0
#endif
#define MAX_RETRIES 4
/* The maximum size of a message that will fit into a packet. Anything bigger
than this is sent via the system LV */
#define MAX_INLINE_MESSAGE (max_cluster_message-sizeof(struct clvm_header))
@@ -325,7 +327,7 @@ int main(int argc, char *argv[])
/* This needs to be started after cluster initialisation
as it may need to take out locks */
DEBUGLOG("starting LVM thread\n");
pthread_create(&lvm_thread, NULL, lvm_thread_fn,
pthread_create(&lvm_thread, NULL, lvm_thread_fn,
(void *)(long)using_gulm);
/* Tell the rest of the cluster our version number */
@@ -375,6 +377,9 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
socklen_t sl = sizeof(socka);
int client_fd = accept(thisfd->fd, (struct sockaddr *) &socka, &sl);
if (client_fd == -1 && errno == EINTR)
return 1;
if (client_fd >= 0) {
newfd = malloc(sizeof(struct local_client));
if (!newfd) {
@@ -412,6 +417,8 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
int status = -1; /* in error by default */
len = read(thisfd->fd, buffer, sizeof(int));
if (len == -1 && errno == EINTR)
return 1;
if (len == sizeof(int)) {
memcpy(&status, buffer, sizeof(int));
@@ -786,6 +793,8 @@ static int read_from_local_sock(struct local_client *thisfd)
char buffer[PIPE_BUF];
len = read(thisfd->fd, buffer, sizeof(buffer));
if (len == -1 && errno == EINTR)
return 1;
DEBUGLOG("Read on local socket %d, len = %d\n", thisfd->fd, len);
@@ -901,8 +910,12 @@ static int read_from_local_sock(struct local_client *thisfd)
len - strlen(inheader->node) - sizeof(struct clvm_header);
missing_len = inheader->arglen - argslen;
if (missing_len < 0)
missing_len = 0;
/* Save the message */
thisfd->bits.localsock.cmd = malloc(len + missing_len);
if (!thisfd->bits.localsock.cmd) {
struct clvm_header reply;
reply.cmd = CLVMD_CMD_REPLY;
@@ -927,9 +940,8 @@ static int read_from_local_sock(struct local_client *thisfd)
DEBUGLOG
("got %d bytes, need another %d (total %d)\n",
argslen, missing_len, inheader->arglen);
len =
read(thisfd->fd, argptr + argslen,
missing_len);
len = read(thisfd->fd, argptr + argslen,
missing_len);
if (len >= 0) {
missing_len -= len;
argslen += len;
@@ -1215,7 +1227,7 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
/* Version check is internal - don't bother exposing it in
clvmd-command.c */
if (msg->cmd == CLVMD_CMD_VERSION) {
int version_nums[3];
int version_nums[3];
char node[256];
memcpy(version_nums, msg->args, sizeof(version_nums));
@@ -1395,6 +1407,7 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
{
struct local_client *client = (struct local_client *) arg;
int status;
int write_status;
sigset_t ss;
int pipe_fd = client->bits.localsock.pipe;
@@ -1424,8 +1437,19 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
client->bits.localsock.all_success = 0;
DEBUGLOG("Writing status %d down pipe %d\n", status, pipe_fd);
/* Tell the parent process we have finished this bit */
write(pipe_fd, &status, sizeof(int));
do {
write_status = write(pipe_fd, &status, sizeof(int));
if (write_status == sizeof(int))
break;
if (write_status < 0 &&
(errno == EINTR || errno == EAGAIN))
continue;
log_error("Error sending to pipe: %m\n");
break;
} while(1);
if (status)
continue; /* Wait for another PRE command */
@@ -1446,7 +1470,16 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
status = 0;
do_post_command(client);
write(pipe_fd, &status, sizeof(int));
do {
write_status = write(pipe_fd, &status, sizeof(int));
if (write_status == sizeof(int))
break;
if (write_status < 0 &&
(errno == EINTR || errno == EAGAIN))
continue;
log_error("Error sending to pipe: %m\n");
break;
} while(1);
DEBUGLOG("Waiting for next pre command\n");
@@ -1650,6 +1683,11 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
const char *errtext)
{
int len;
int saved_errno = 0;
struct timespec delay;
struct timespec remtime;
int retry_cnt = 0;
/* Send remote messages down the cluster socket */
if (csid == NULL || !ISLOCAL_CSID(csid)) {
@@ -1660,14 +1698,38 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
/* Make sure it all goes */
do {
if (retry_cnt > MAX_RETRIES)
{
errno = saved_errno;
log_error(errtext);
errno = saved_errno;
break;
}
len = write(fd, buf + ptr, msglen - ptr);
if (len <= 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN ||
errno == EIO ||
errno == ENOSPC) {
saved_errno = errno;
retry_cnt++;
delay.tv_sec = 0;
delay.tv_nsec = 100000;
remtime.tv_sec = 0;
remtime.tv_nsec = 0;
(void) nanosleep (&delay, &remtime);
continue;
}
log_error(errtext);
break;
}
ptr += len;
} while (len < msglen);
} while (ptr < msglen);
}
return len;
}

View File

@@ -30,11 +30,11 @@
#include <errno.h>
#include <syslog.h>
#include <assert.h>
#include <libdevmapper.h>
#include <libdlm.h>
#include "libdevmapper.h"
#include "list.h"
#include "lvm-types.h"
#include "libdlm.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
@@ -50,6 +50,7 @@
static struct cmd_context *cmd = NULL;
static struct dm_hash_table *lv_hash = NULL;
static pthread_mutex_t lv_hash_lock;
static pthread_mutex_t lvm_lock;
static char last_error[1024];
struct lv_info {
@@ -311,10 +312,12 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
resource, command, lock_flags);
pthread_mutex_lock(&lvm_lock);
if (!cmd->config_valid || config_files_changed(cmd)) {
/* Reinitialise various settings inc. logging, filters */
if (!refresh_toolcontext(cmd)) {
log_error("Updated config file invalid. Aborting.");
pthread_mutex_unlock(&lvm_lock);
return EINVAL;
}
}
@@ -367,6 +370,7 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
/* clean the pool for another command */
dm_pool_empty(cmd->mem);
pthread_mutex_unlock(&lvm_lock);
DEBUGLOG("Command return is %d\n", status);
return status;
@@ -393,6 +397,8 @@ int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
int post_lock_lv(unsigned char command, unsigned char lock_flags,
char *resource)
{
int status;
/* Opposite of above, done on resume after a metadata update */
if (command == LCK_LV_RESUME) {
int oldmode;
@@ -406,7 +412,10 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
if (oldmode == LKM_PWMODE) {
struct lvinfo lvi;
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
pthread_mutex_lock(&lvm_lock);
status = lv_info_by_lvid(cmd, resource, &lvi, 0);
pthread_mutex_unlock(&lvm_lock);
if (!status)
return EIO;
if (lvi.exists) {
@@ -533,7 +542,7 @@ static void lvm2_log_fn(int level, const char *file, int line,
const char *message)
{
/*
* Ignore non-error messages, but store the latest one for returning
* Ignore non-error messages, but store the latest one for returning
* to the user.
*/
if (level != _LOG_ERR && level != _LOG_FATAL)
@@ -572,6 +581,7 @@ void init_lvhash()
/* Create hash table for keeping LV locks & status */
lv_hash = dm_hash_create(100);
pthread_mutex_init(&lv_hash_lock, NULL);
pthread_mutex_init(&lvm_lock, NULL);
}
/* Called to initialise the LVM context of the daemon */

View File

@@ -36,8 +36,11 @@
#include <dirent.h>
#include <errno.h>
#include <mntent.h>
#include <libdlm.h>
#ifdef HAVE_CCS
#include <ccs.h>
#endif
#include "libdlm.h"
#include "log.h"
#include "list.h"
#include "locking.h"
@@ -45,9 +48,6 @@
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
#ifdef HAVE_CCS
#include "ccs.h"
#endif
#define SYSTEM_LV_FILESYSTEM "ext2"
#define SYSTEM_LV_MOUNTPOINT "/tmp/.clvmd-XXXXXX"

View File

@@ -34,8 +34,8 @@
#include <syslog.h>
#include <netdb.h>
#include <assert.h>
#include <libdevmapper.h>
#include "libdevmapper.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"

View File

@@ -146,6 +146,7 @@ static LIST_INIT(_dso_registry);
/* Structure to keep parsed register variables from client message. */
struct message_data {
char *id;
char *dso_name; /* Name of DSO. */
char *device_uuid; /* Mapped device path. */
union {
@@ -225,8 +226,8 @@ static struct thread_status *_alloc_thread_status(struct message_data *data,
if (!ret)
return NULL;
if (!memset(ret, 0, sizeof(*ret)) ||
!(ret->device.uuid = dm_strdup(data->device_uuid))) {
memset(ret, 0, sizeof(*ret));
if (!(ret->device.uuid = dm_strdup(data->device_uuid))) {
dm_free(ret);
return NULL;
}
@@ -244,6 +245,8 @@ static struct thread_status *_alloc_thread_status(struct message_data *data,
static void _free_thread_status(struct thread_status *thread)
{
if (thread->current_task)
dm_task_destroy(thread->current_task);
dm_free(thread->device.uuid);
dm_free(thread->device.name);
dm_free(thread);
@@ -257,8 +260,8 @@ static struct dso_data *_alloc_dso_data(struct message_data *data)
if (!ret)
return NULL;
if (!memset(ret, 0, sizeof(*ret)) ||
!(ret->dso_name = dm_strdup(data->dso_name))) {
memset(ret, 0, sizeof(*ret));
if (!(ret->dso_name = dm_strdup(data->dso_name))) {
dm_free(ret);
return NULL;
}
@@ -320,6 +323,8 @@ static int _fetch_string(char **ptr, char **src, const int delimiter)
/* Free message memory. */
static void _free_message(struct message_data *message_data)
{
if (message_data->id)
dm_free(message_data->id);
if (message_data->dso_name)
dm_free(message_data->dso_name);
@@ -342,7 +347,8 @@ static int _parse_message(struct message_data *message_data)
* Retrieve application identifier, mapped device
* path and events # string from message.
*/
if (_fetch_string(&message_data->dso_name, &p, ' ') &&
if (_fetch_string(&message_data->id, &p, ' ') &&
_fetch_string(&message_data->dso_name, &p, ' ') &&
_fetch_string(&message_data->device_uuid, &p, ' ') &&
_fetch_string(&message_data->events.str, &p, ' ') &&
_fetch_string(&message_data->timeout.str, &p, ' ')) {
@@ -617,6 +623,8 @@ static int _event_wait(struct thread_status *thread, struct dm_task **task)
} else if (thread->events & DM_EVENT_TIMEOUT && errno == EINTR) {
thread->current_events |= DM_EVENT_TIMEOUT;
ret = DM_WAIT_INTR;
} else if (thread->status == DM_THREAD_SHUTDOWN && errno == EINTR) {
ret = DM_WAIT_FATAL;
} else {
syslog(LOG_NOTICE, "dm_task_run failed, errno = %d, %s",
errno, strerror(errno));
@@ -807,11 +815,6 @@ static int _create_thread(struct thread_status *thread)
static int _terminate_thread(struct thread_status *thread)
{
int ret;
if ((ret = pthread_cancel(thread->thread)))
return ret;
return pthread_kill(thread->thread, SIGALRM);
}
@@ -875,8 +878,8 @@ static struct dso_data *_load_dso(struct message_data *data)
syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name,
dlerr);
data->msg->size =
dm_asprintf(&(data->msg->data), "%s dlopen failed: %s",
data->dso_name, dlerr);
dm_asprintf(&(data->msg->data), "%s %s dlopen failed: %s",
data->id, data->dso_name, dlerr);
return NULL;
}
@@ -1056,7 +1059,8 @@ static int _registered_device(struct message_data *message_data,
{
struct dm_event_daemon_message *msg = message_data->msg;
const char *fmt = "%s %s %u";
const char *fmt = "%s %s %s %u";
const char *id = message_data->id;
const char *dso = thread->dso_data->dso_name;
const char *dev = thread->device.uuid;
unsigned events = ((thread->status == DM_THREAD_RUNNING)
@@ -1066,7 +1070,7 @@ static int _registered_device(struct message_data *message_data,
if (msg->data)
dm_free(msg->data);
msg->size = dm_asprintf(&(msg->data), fmt, dso, dev, events);
msg->size = dm_asprintf(&(msg->data), fmt, id, dso, dev, events);
_unlock_mutex();
@@ -1180,7 +1184,8 @@ static int _get_timeout(struct message_data *message_data)
_lock_mutex();
if ((thread = _lookup_thread_status(message_data))) {
msg->size =
dm_asprintf(&(msg->data), "%" PRIu32, thread->timeout);
dm_asprintf(&(msg->data), "%s %" PRIu32, message_data->id,
thread->timeout);
} else {
msg->data = NULL;
msg->size = 0;
@@ -1375,17 +1380,32 @@ static int _handle_request(struct dm_event_daemon_message *msg,
static int _do_process_request(struct dm_event_daemon_message *msg)
{
int ret;
char *answer;
static struct message_data message_data;
/* Parse the message. */
memset(&message_data, 0, sizeof(message_data));
message_data.msg = msg;
if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
if (msg->cmd == DM_EVENT_CMD_HELLO) {
ret = 0;
answer = msg->data;
if (answer) {
msg->size = dm_asprintf(&(msg->data), "%s HELLO", answer);
dm_free(answer);
} else {
msg->size = 0;
msg->data = NULL;
}
} else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
stack;
ret = -EINVAL;
} else
ret = _handle_request(msg, &message_data);
msg->cmd = ret;
if (!msg->data)
msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
_free_message(&message_data);
return ret;
@@ -1405,16 +1425,9 @@ static void _process_request(struct dm_event_fifos *fifos)
if (!_client_read(fifos, &msg))
return;
msg.cmd = _do_process_request(&msg);
if (!msg.data) {
msg.data = dm_strdup(strerror(-msg.cmd));
if (msg.data)
msg.size = strlen(msg.data) + 1;
else {
msg.size = 0;
stack;
}
}
/* _do_process_request fills in msg (if memory allows for
data, otherwise just cmd and size = 0) */
_do_process_request(&msg);
if (!_client_write(fifos, &msg))
stack;

View File

@@ -20,6 +20,7 @@ enum dm_event_command {
DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
DM_EVENT_CMD_SET_TIMEOUT,
DM_EVENT_CMD_GET_TIMEOUT,
DM_EVENT_CMD_HELLO,
};
/* Message passed between client and daemon. */

View File

@@ -30,6 +30,8 @@
#include <sys/wait.h>
#include <arpa/inet.h> /* for htonl, ntohl */
static int _sequence_nr = 0;
struct dm_event_handler {
char *dso;
@@ -182,6 +184,21 @@ enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler
return dmevh->mask;
}
static int _check_message_id(struct dm_event_daemon_message *msg)
{
int pid, seq_nr;
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
log_error("Ignoring out-of-sequence reply from dmeventd. "
"Expected %d:%d but received %s", getpid(),
_sequence_nr, msg->data);
return 0;
}
return 1;
}
/*
* daemon_read
* @fifos
@@ -260,11 +277,28 @@ static int _daemon_write(struct dm_event_fifos *fifos,
size_t size = 2 * sizeof(uint32_t) + msg->size;
char *buf = alloca(size);
char drainbuf[128];
struct timeval tval = { 0, 0 };
*((uint32_t *)buf) = htonl(msg->cmd);
*((uint32_t *)buf + 1) = htonl(msg->size);
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
/* drain the answer fifo */
while (1) {
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
tval.tv_usec = 100;
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
if ((ret < 0) && (errno != EINTR)) {
log_error("Unable to talk to event daemon");
return 0;
}
if (ret == 0)
break;
read(fifos->server, drainbuf, 127);
}
while (bytes < size) {
do {
/* Watch daemon write FIFO to be ready for output. */
@@ -301,7 +335,7 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
{
const char *dso = dso_name ? dso_name : "";
const char *dev = dev_name ? dev_name : "";
const char *fmt = "%s %s %u %" PRIu32;
const char *fmt = "%d:%d %s %s %u %" PRIu32;
int msg_size;
memset(msg, 0, sizeof(*msg));
@@ -310,8 +344,10 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
* into ASCII message string.
*/
msg->cmd = cmd;
if ((msg_size = dm_asprintf(&(msg->data), fmt, dso, dev, evmask,
timeout)) < 0) {
if (cmd == DM_EVENT_CMD_HELLO)
fmt = "%d:%d HELLO";
if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
dso, dev, evmask, timeout)) < 0) {
log_error("_daemon_talk: message allocation failed");
return -ENOMEM;
}
@@ -323,13 +359,24 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
*/
if (!_daemon_write(fifos, msg)) {
stack;
dm_free(msg->data);
msg->data = 0;
return -EIO;
}
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
do {
if (msg->data)
dm_free(msg->data);
msg->data = 0;
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
} while (!_check_message_id(msg));
_sequence_nr++;
return (int32_t) msg->cmd;
}
@@ -507,7 +554,14 @@ static int _do_event(int cmd, struct dm_event_daemon_message *msg,
return -ESRCH;
}
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0);
if (msg->data)
dm_free(msg->data);
msg->data = 0;
if (!ret)
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
/* what is the opposite of init? */
_dtr_client(&fifos);
@@ -521,7 +575,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -551,7 +605,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -598,15 +652,20 @@ static char *_fetch_string(char **src, const int delimiter)
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
{
char *id = NULL;
char *p = msg->data;
if ((*dso_name = _fetch_string(&p, ' ')) &&
if ((id = _fetch_string(&p, ' ')) &&
(*dso_name = _fetch_string(&p, ' ')) &&
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
dm_free(id);
return 0;
}
if (id)
dm_free(id);
return -ENOMEM;
}
@@ -621,12 +680,12 @@ static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
*/
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
{
int ret;
int ret = 0;
const char *uuid = NULL;
char *reply_dso = NULL, *reply_uuid = NULL;
enum dm_event_mask reply_mask;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
enum dm_event_mask reply_mask = 0;
struct dm_task *dmt = NULL;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -667,6 +726,12 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
dm_event_handler_set_dso(dmevh, reply_dso);
dm_event_handler_set_event_mask(dmevh, reply_mask);
if (reply_dso)
dm_free(reply_dso);
if (reply_uuid)
dm_free(reply_uuid);
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
if (!dmevh->dev_name) {
ret = -ENOMEM;
@@ -689,6 +754,10 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
fail:
if (msg.data)
dm_free(msg.data);
if (reply_dso)
dm_free(reply_dso);
if (reply_uuid)
dm_free(reply_uuid);
_dm_event_handler_clear_dev_info(dmevh);
dm_task_destroy(dmt);
return ret;
@@ -696,9 +765,17 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
#if 0 /* left out for now */
static char *_skip_string(char *src, const int delimiter)
{
src = srtchr(src, delimiter);
if (src && *(src + 1))
return src + 1;
return NULL;
}
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
@@ -710,13 +787,20 @@ int dm_event_set_timeout(const char *device_path, uint32_t timeout)
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
{
int ret;
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
0, 0)))
*timeout = atoi(msg.data);
0, 0))) {
char *p = _skip_string(msg.data, ' ');
if (!p) {
log_error("malformed reply from dmeventd '%s'\n",
msg.data);
return -EIO;
}
*timeout = atoi(p);
}
if (msg.data)
dm_free(msg.data);
return ret;

View File

@@ -12,10 +12,10 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include <libdevmapper.h>
#include <libdevmapper-event.h>
#include <errno.h>
#include <signal.h>
#include <string.h>

View File

@@ -12,10 +12,10 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include <libdevmapper.h>
#include <libdevmapper-event.h>
#include <errno.h>
#include <signal.h>
#include <string.h>

View File

@@ -19,6 +19,14 @@ devices {
# to use with LVM2.
scan = [ "/dev" ]
# If several entries in the scanned directories correspond to the
# same block device and the tools need to display a name for device,
# all the pathnames are matched against each item in the following
# list of regular expressions in turn and the first match is used.
preferred_names = [ ]
# preferred_names = [ "^/dev/mpath/", "^/dev/[hs]d" ]
# A filter that tells LVM2 to only use a restricted set of devices.
# The filter consists of an array of regular expressions. These
# expressions can be delimited by a character of your choice, and
@@ -56,10 +64,14 @@ devices {
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
# The results of the filtering are cached on disk to avoid
# rescanning dud devices (which can take a very long time). By
# default this cache file is hidden in the /etc/lvm directory.
# It is safe to delete this file: the tools regenerate it.
cache = "/etc/lvm/.cache"
# rescanning dud devices (which can take a very long time).
# By default this cache is stored in the /etc/lvm/cache directory
# in a file called '.cache'.
# It is safe to delete the contents: the tools regenerate it.
# (The old setting 'cache' is still respected if neither of
# these new ones is present.)
cache_dir = "/etc/lvm/cache"
cache_file_prefix = ""
# You can turn off writing this cache file by setting this to 0.
write_cache_state = 1
@@ -188,6 +200,9 @@ global {
# command. Defaults to off.
test = 0
# Default value for --units argument
units = "h"
# Whether or not to communicate with the kernel device-mapper.
# Set to 0 if you want to use the tools to manipulate LVM metadata
# without activating any logical volumes.

View File

@@ -43,7 +43,6 @@
../lib/misc/lvm-string.h
../lib/misc/lvm-wrappers.h
../lib/misc/sharedlib.h
../lib/regex/matcher.h
../lib/report/report.h
../lib/uuid/uuid.h
../po/pogen.h

View File

@@ -81,9 +81,6 @@ SOURCES =\
misc/lvm-wrappers.c \
misc/timestamp.c \
mm/memlock.c \
regex/matcher.c \
regex/parse_rx.c \
regex/ttree.c \
report/report.c \
striped/striped.c \
uuid/uuid.c \

View File

@@ -168,6 +168,10 @@ int lvs_in_vg_activated(struct volume_group *vg)
{
return 0;
}
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
{
return 0;
}
int lvs_in_vg_opened(struct volume_group *vg)
{
return 0;
@@ -421,21 +425,23 @@ int target_present(const char *target_name, int use_modprobe)
* Returns 1 if info structure populated, else 0 on failure.
*/
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int with_mknodes,
struct lvinfo *info, int with_open_count)
struct lvinfo *info, int with_open_count, unsigned by_uuid_only)
{
struct dm_info dminfo;
char *name;
char *name = NULL;
if (!activation())
return 0;
if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
if (!by_uuid_only &&
!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
return_0;
log_debug("Getting device info for %s", name);
if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
with_open_count, &dminfo)) {
dm_pool_free(cmd->mem, name);
if (name)
dm_pool_free(cmd->mem, name);
return_0;
}
@@ -448,14 +454,16 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, in
info->live_table = dminfo.live_table;
info->inactive_table = dminfo.inactive_table;
dm_pool_free(cmd->mem, name);
if (name)
dm_pool_free(cmd->mem, name);
return 1;
}
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count)
{
return _lv_info(cmd, lv, 0, info, with_open_count);
return _lv_info(cmd, lv, 0, info, with_open_count, 0);
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
@@ -466,7 +474,7 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
return _lv_info(cmd, lv, 0, info, with_open_count);
return _lv_info(cmd, lv, 0, info, with_open_count, 0);
}
/*
@@ -519,11 +527,12 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
return r;
}
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv,
unsigned by_uuid_only)
{
struct lvinfo info;
if (!lv_info(cmd, lv, &info, 0)) {
if (!_lv_info(cmd, lv, 0, &info, 0, by_uuid_only)) {
stack;
return -1;
}
@@ -607,7 +616,7 @@ static int _lv_suspend_lv(struct logical_volume *lv, int lockfs)
* These two functions return the number of visible LVs in the state,
* or -1 on error.
*/
int lvs_in_vg_activated(struct volume_group *vg)
static int _lvs_in_vg_activated(struct volume_group *vg, unsigned by_uuid_only)
{
struct lv_list *lvl;
int count = 0;
@@ -617,12 +626,22 @@ int lvs_in_vg_activated(struct volume_group *vg)
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & VISIBLE_LV)
count += (_lv_active(vg->cmd, lvl->lv) == 1);
count += (_lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
}
return count;
}
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
{
return _lvs_in_vg_activated(vg, 1);
}
int lvs_in_vg_activated(struct volume_group *vg)
{
return _lvs_in_vg_activated(vg, 0);
}
int lvs_in_vg_opened(struct volume_group *vg)
{
struct lv_list *lvl;
@@ -973,7 +992,7 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
return r;
}
if (!_lv_info(cmd, lv, 1, &info, 0))
if (!_lv_info(cmd, lv, 1, &info, 0, 0))
return_0;
if (info.exists)

View File

@@ -83,6 +83,7 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
* Return number of LVs in the VG that are active.
*/
int lvs_in_vg_activated(struct volume_group *vg);
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
int lvs_in_vg_opened(struct volume_group *vg);

View File

@@ -118,12 +118,10 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
}
static int _info_run(const char *name, const char *dlid, struct dm_info *info,
int mknodes, int with_open_count, struct dm_pool *mem,
char **uuid_out)
int mknodes, int with_open_count)
{
int r = 0;
struct dm_task *dmt;
const char *u;
int dmtask;
dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
@@ -143,11 +141,6 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
if (!dm_task_get_info(dmt, info))
goto_out;
if (info->exists && uuid_out) {
if (!(u = dm_task_get_uuid(dmt)))
goto_out;
*uuid_out = dm_pool_strdup(mem, u);
}
r = 1;
out:
@@ -208,23 +201,20 @@ int device_is_usable(dev_t dev)
}
static int _info(const char *name, const char *dlid, int mknodes,
int with_open_count, struct dm_info *info,
struct dm_pool *mem, char **uuid_out)
int with_open_count, struct dm_info *info)
{
if (!mknodes && dlid && *dlid) {
if (_info_run(NULL, dlid, info, 0, with_open_count, mem,
uuid_out) &&
if (_info_run(NULL, dlid, info, 0, with_open_count) &&
info->exists)
return 1;
else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
0, with_open_count, mem, uuid_out) &&
0, with_open_count) &&
info->exists)
return 1;
}
if (name)
return _info_run(name, NULL, info, mknodes, with_open_count,
mem, uuid_out);
return _info_run(name, NULL, info, mknodes, with_open_count);
return 0;
}
@@ -240,8 +230,7 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
return 0;
}
return _info(name, dlid, with_mknodes, with_open_count, info,
NULL, NULL);
return _info(name, dlid, with_mknodes, with_open_count, info);
}
/* FIXME Interface must cope with multiple targets */
@@ -446,10 +435,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
return NULL;
}
if (!(dm = dm_pool_alloc(mem, sizeof(*dm)))) {
stack;
goto bad;
}
if (!(dm = dm_pool_alloc(mem, sizeof(*dm))))
goto_bad;
dm->cmd = cmd;
dm->mem = mem;
@@ -461,10 +448,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
}
dm->stripe_filler = stripe_filler;
if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name))) {
stack;
goto bad;
}
if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name)))
goto_bad;
dm->target_state = NULL;
@@ -646,7 +631,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
log_debug("Getting device info for %s [%s]", name, dlid);
if (!_info(name, dlid, 0, 1, &info, dm->mem, NULL)) {
if (!_info(name, dlid, 0, 1, &info)) {
log_error("Failed to get info for %s [%s].", name, dlid);
return 0;
}

12
lib/cache/lvmcache.c vendored
View File

@@ -135,7 +135,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
list_iterate_safe(devh, tmp, &devs) {
devl = list_item(devh, struct device_list);
label_read(devl->dev, &label);
label_read(devl->dev, &label, UINT64_C(0));
list_del(&devl->list);
dm_free(devl);
}
@@ -205,7 +205,7 @@ static void _rescan_entry(struct lvmcache_info *info)
struct label *label;
if (info->status & CACHE_INVALID)
label_read(info->dev, &label);
label_read(info->dev, &label, UINT64_C(0));
}
static int _scan_invalid(void)
@@ -247,7 +247,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
}
while ((dev = dev_iter_get(iter)))
label_read(dev, &label);
label_read(dev, &label, UINT64_C(0));
dev_iter_destroy(iter);
@@ -346,7 +346,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Already cached ? */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
@@ -357,7 +357,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
@@ -371,7 +371,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;

View File

@@ -465,10 +465,8 @@ static int _init_dev_cache(struct cmd_context *cmd)
const struct config_node *cn;
struct config_value *cv;
if (!dev_cache_init()) {
stack;
return 0;
}
if (!dev_cache_init(cmd))
return_0;
if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
if (!dev_cache_add_dir("/dev")) {
@@ -575,7 +573,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
{
const char *dev_cache;
const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
struct dev_filter *f3, *f4;
struct stat st;
char cache_file[PATH_MAX];
@@ -585,19 +583,35 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
if (!(f3 = _init_filter_components(cmd)))
return 0;
if (dm_snprintf(cache_file, sizeof(cache_file),
"%s/.cache", cmd->sys_dir) < 0) {
log_error("Persistent cache filename too long ('%s/.cache').",
cmd->sys_dir);
return 0;
}
init_ignore_suspended_devices(find_config_tree_int(cmd,
"devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
dev_cache = find_config_tree_str(cmd, "devices/cache",
cache_file);
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
/*
* If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
*/
cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
if (cache_dir || cache_file_prefix) {
if (dm_snprintf(cache_file, sizeof(cache_file),
"%s%s%s/%s.cache",
cache_dir ? "" : cmd->sys_dir,
cache_dir ? "" : "/",
cache_dir ? : DEFAULT_CACHE_SUBDIR,
cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
log_error("Persistent cache filename too long.");
return 0;
}
} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
(dm_snprintf(cache_file, sizeof(cache_file),
"%s/%s/%s.cache",
cmd->sys_dir, DEFAULT_CACHE_SUBDIR,
DEFAULT_CACHE_FILE_PREFIX) < 0)) {
log_error("Persistent cache filename too long.");
return 0;
}
if (!(f4 = persistent_filter_create(f3, dev_cache ? : cache_file))) {
log_error("Failed to create persistent device filter");
return 0;
}
@@ -754,7 +768,6 @@ static int _init_segtypes(struct cmd_context *cmd)
struct config_value *cv;
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
void *lib;
struct list *sgtl, *tmp;
struct segment_type *segtype2;
for (cv = cn->v; cv; cv = cv->next) {
@@ -781,18 +794,16 @@ static int _init_segtypes(struct cmd_context *cmd)
segtype->library = lib;
list_add(&cmd->segtypes, &segtype->list);
list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
segtype2 = list_item(sgtl, struct segment_type);
if (!strcmp(segtype2->name, segtype->name)) {
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
break;
}
list_iterate_items(segtype2, &cmd->segtypes) {
if ((segtype == segtype2) ||
strcmp(segtype2->name, segtype->name))
continue;
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
}
}
}

View File

@@ -19,6 +19,7 @@
#include "device.h"
#include "str_list.h"
#include "toolcontext.h"
#include "lvm-string.h"
#include <sys/stat.h>
#include <sys/mman.h>
@@ -26,6 +27,9 @@
#include <fcntl.h>
#include <ctype.h>
#define SECTION_B_CHAR '{'
#define SECTION_E_CHAR '}'
enum {
TOK_INT,
TOK_FLOAT,
@@ -79,7 +83,8 @@ static const int sep = '/';
#define match(t) do {\
if (!_match_aux(p, (t))) {\
log_error("Parse error at byte %d (line %d): unexpected token", p->tb - p->fb + 1, p->line); \
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \
p->tb - p->fb + 1, p->line); \
return 0;\
} \
} while(0);
@@ -210,18 +215,10 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
stack;
return 0;
}
if (!dev_read(dev, (uint64_t) offset, size, buf)) {
log_error("Read from %s failed", dev_name(dev));
if (!dev_read_circular(dev, (uint64_t) offset, size,
(uint64_t) offset2, size2, buf)) {
goto out;
}
if (size2) {
if (!dev_read(dev, (uint64_t) offset2, size2,
buf + size)) {
log_error("Circular read from %s failed",
dev_name(dev));
goto out;
}
}
p->fb = buf;
}
@@ -360,7 +357,7 @@ static void _write_value(FILE *fp, struct config_value *v)
break;
case CFG_INT:
fprintf(fp, "%d", v->v.i);
fprintf(fp, "%" PRId64, v->v.i);
break;
case CFG_EMPTY_ARRAY:
@@ -482,7 +479,7 @@ static struct config_node *_file(struct parser *p)
static struct config_node *_section(struct parser *p)
{
/* IDENTIFIER '{' VALUE* '}' */
/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
struct config_node *root, *n, *l = NULL;
if (!(root = _create_node(p))) {
stack;
@@ -571,7 +568,7 @@ static struct config_value *_type(struct parser *p)
switch (p->t) {
case TOK_INT:
v->type = CFG_INT;
v->v.i = strtol(p->tb, NULL, 0); /* FIXME: check error */
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
match(TOK_INT);
break;
@@ -594,7 +591,8 @@ static struct config_value *_type(struct parser *p)
break;
default:
log_error("Parse error at byte %d (line %d): expected a value", p->tb - p->fb + 1, p->line);
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
p->tb - p->fb + 1, p->line);
return 0;
}
return v;
@@ -631,12 +629,12 @@ static void _get_token(struct parser *p, int tok_prev)
p->t = TOK_INT; /* fudge so the fall through for
floats works */
switch (*p->te) {
case '{':
case SECTION_B_CHAR:
p->t = TOK_SECTION_B;
p->te++;
break;
case '}':
case SECTION_E_CHAR:
p->t = TOK_SECTION_E;
p->te++;
break;
@@ -716,8 +714,9 @@ static void _get_token(struct parser *p, int tok_prev)
default:
p->t = TOK_IDENTIFIER;
while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
(*p->te != '#') && (*p->te != '=') && (*p->te != '{') &&
(*p->te != '}'))
(*p->te != '#') && (*p->te != '=') &&
(*p->te != SECTION_B_CHAR) &&
(*p->te != SECTION_E_CHAR))
p->te++;
break;
}
@@ -872,25 +871,26 @@ const char *find_config_str(const struct config_node *cn,
return _find_config_str(cn, NULL, path, fail);
}
static int _find_config_int(const struct config_node *cn1,
const struct config_node *cn2,
const char *path, int fail)
static int64_t _find_config_int64(const struct config_node *cn1,
const struct config_node *cn2,
const char *path, int64_t fail)
{
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
if (n && n->v->type == CFG_INT) {
log_very_verbose("Setting %s to %d", path, n->v->v.i);
if (n && n->v && n->v->type == CFG_INT) {
log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i);
return n->v->v.i;
}
log_very_verbose("%s not found in config: defaulting to %d",
log_very_verbose("%s not found in config: defaulting to %" PRId64,
path, fail);
return fail;
}
int find_config_int(const struct config_node *cn, const char *path, int fail)
{
return _find_config_int(cn, NULL, path, fail);
/* FIXME Add log_error message on overflow */
return (int) _find_config_int64(cn, NULL, path, (int64_t) fail);
}
static float _find_config_float(const struct config_node *cn1,
@@ -899,7 +899,7 @@ static float _find_config_float(const struct config_node *cn1,
{
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
if (n && n->v->type == CFG_FLOAT) {
if (n && n->v && n->v->type == CFG_FLOAT) {
log_very_verbose("Setting %s to %f", path, n->v->v.r);
return n->v->v.r;
}
@@ -932,7 +932,8 @@ const char *find_config_tree_str(struct cmd_context *cmd,
int find_config_tree_int(struct cmd_context *cmd, const char *path,
int fail)
{
return _find_config_int(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
/* FIXME Add log_error message on overflow */
return (int) _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, (int64_t) fail);
}
float find_config_tree_float(struct cmd_context *cmd, const char *path,
@@ -1024,7 +1025,6 @@ int get_config_uint64(const struct config_node *cn, const char *path,
if (!n || !n->v || n->v->type != CFG_INT)
return 0;
/* FIXME Support 64-bit value! */
*result = (uint64_t) n->v->v.i;
return 1;
}
@@ -1154,3 +1154,61 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
return 1;
}
/*
* Convert a token type to the char it represents.
*/
static char _token_type_to_char(int type)
{
switch (type) {
case TOK_SECTION_B:
return SECTION_B_CHAR;
case TOK_SECTION_E:
return SECTION_E_CHAR;
default:
return 0;
}
}
/*
* Returns:
* # of 'type' tokens in 'str'.
*/
static unsigned _count_tokens (const char *str, unsigned len, int type)
{
char c;
c = _token_type_to_char(type);
return(count_chars_len(str, len, c));
}
/*
* Heuristic function to make a quick guess as to whether a text
* region probably contains a valid config "section". (Useful for
* scanning areas of the disk for old metadata.)
* Config sections contain various tokens, may contain other sections
* and strings, and are delimited by begin (type 'TOK_SECTION_B') and
* end (type 'TOK_SECTION_E') tokens. As a quick heuristic, we just
* count the number of begin and end tokens, and see if they are
* non-zero and the counts match.
* Full validation of the section should be done with another function
* (for example, read_config_fd).
*
* Returns:
* 0 - probably is not a valid config section
* 1 - probably _is_ a valid config section
*/
unsigned maybe_config_section(const char *str, unsigned len)
{
int begin_count;
int end_count;
begin_count = _count_tokens(str, len, TOK_SECTION_B);
end_count = _count_tokens(str, len, TOK_SECTION_E);
if (begin_count && end_count && (begin_count - end_count == 0))
return 1;
else
return 0;
}

View File

@@ -31,7 +31,7 @@ enum {
struct config_value {
int type;
union {
int i;
int64_t i;
float r;
char *str;
} v;
@@ -108,4 +108,6 @@ int get_config_uint64(const struct config_node *cn, const char *path,
int get_config_str(const struct config_node *cn, const char *path,
char **result);
unsigned maybe_config_section(const char *str, unsigned len);
#endif

View File

@@ -21,6 +21,8 @@
#define DEFAULT_ARCHIVE_SUBDIR "archive"
#define DEFAULT_BACKUP_SUBDIR "backup"
#define DEFAULT_CACHE_SUBDIR "cache"
#define DEFAULT_CACHE_FILE_PREFIX ""
#define DEFAULT_ARCHIVE_DAYS 30
#define DEFAULT_ARCHIVE_NUMBER 10

View File

@@ -23,6 +23,7 @@
/* Define some portable printing types */
#define PRIsize_t "zu"
#define PRIptrdiff_t "td"
struct str_list {
struct list list;

View File

@@ -19,6 +19,7 @@
#include "btree.h"
#include "filter.h"
#include "filter-persistent.h"
#include "toolcontext.h"
#include <unistd.h>
#include <sys/param.h>
@@ -38,6 +39,7 @@ static struct {
struct dm_pool *mem;
struct dm_hash_table *names;
struct btree *devices;
struct dm_regex *preferred_names_matcher;
int has_scanned;
struct list dirs;
@@ -129,15 +131,52 @@ static struct device *_dev_create(dev_t d)
return dev;
}
void dev_set_preferred_name(struct str_list *sl, struct device *dev)
{
/*
* Don't interfere with ordering specified in config file.
*/
if (_cache.preferred_names_matcher)
return;
log_debug("%s: New preferred name", sl->str);
list_del(&sl->list);
list_add_h(&dev->aliases, &sl->list);
}
/* Return 1 if we prefer path1 else return 0 */
static int _compare_paths(const char *path0, const char *path1)
{
int slash0 = 0, slash1 = 0;
int m0, m1;
const char *p;
char p0[PATH_MAX], p1[PATH_MAX];
char *s0, *s1;
struct stat stat0, stat1;
/*
* FIXME Better to compare patterns one-at-a-time against all names.
*/
if (_cache.preferred_names_matcher) {
m0 = dm_regex_match(_cache.preferred_names_matcher, path0);
m1 = dm_regex_match(_cache.preferred_names_matcher, path1);
if (m0 != m1) {
if (m0 < 0)
return 1;
if (m1 < 0)
return 0;
if (m0 < m1)
return 1;
if (m1 < m0)
return 0;
}
}
/*
* Built-in rules.
*/
/* Return the path with fewer slashes */
for (p = path0; p++; p = (const char *) strchr(p, '/'))
slash0++;
@@ -441,7 +480,65 @@ void dev_cache_scan(int do_scan)
_full_scan(1);
}
int dev_cache_init(void)
static int _init_preferred_names(struct cmd_context *cmd)
{
const struct config_node *cn;
struct config_value *v;
struct dm_pool *scratch = NULL;
char **regex;
unsigned count = 0;
int i, r = 0;
_cache.preferred_names_matcher = NULL;
if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) ||
cn->v->type == CFG_EMPTY_ARRAY) {
log_very_verbose("devices/preferred_names not found in config file: "
"using built-in preferences");
return 1;
}
for (v = cn->v; v; v = v->next) {
if (v->type != CFG_STRING) {
log_error("preferred_names patterns must be enclosed in quotes");
return 0;
}
count++;
}
if (!(scratch = dm_pool_create("preferred device name matcher", 1024)))
return_0;
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
log_error("Failed to allocate preferred device name "
"pattern list.");
goto out;
}
for (v = cn->v, i = count - 1; v; v = v->next, i--) {
if (!(regex[i] = dm_pool_strdup(scratch, v->v.str))) {
log_error("Failed to allocate a preferred device name "
"pattern.");
goto out;
}
}
if (!(_cache.preferred_names_matcher =
dm_regex_create(_cache.mem,(const char **) regex, count))) {
log_error("Preferred device name pattern matcher creation failed.");
goto out;
}
r = 1;
out:
dm_pool_destroy(scratch);
return r;
}
int dev_cache_init(struct cmd_context *cmd)
{
_cache.names = NULL;
_cache.has_scanned = 0;
@@ -466,6 +563,9 @@ int dev_cache_init(void)
list_init(&_cache.dirs);
list_init(&_cache.files);
if (!_init_preferred_names(cmd))
goto_bad;
return 1;
bad:
@@ -489,6 +589,9 @@ void dev_cache_exit(void)
if (_cache.names)
_check_for_open_devices();
if (_cache.preferred_names_matcher)
_cache.preferred_names_matcher = NULL;
if (_cache.mem) {
dm_pool_destroy(_cache.mem);
_cache.mem = NULL;

View File

@@ -30,7 +30,8 @@ struct dev_filter {
/*
* The global device cache.
*/
int dev_cache_init(void);
struct cmd_context;
int dev_cache_init(struct cmd_context *cmd);
void dev_cache_exit(void);
/* Trigger(1) or avoid(0) a scan */
@@ -41,6 +42,8 @@ int dev_cache_add_dir(const char *path);
int dev_cache_add_loopfile(const char *path);
struct device *dev_cache_get(const char *name, struct dev_filter *f);
void dev_set_preferred_name(struct str_list *sl, struct device *dev);
/*
* Object for iterating through the cache.
*/

View File

@@ -564,6 +564,35 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
return _aligned_io(&where, buffer, 0);
}
/*
* Read from 'dev' into 'buf', possibly in 2 distinct regions, denoted
* by (offset,len) and (offset2,len2). Thus, the total size of
* 'buf' should be len+len2.
*/
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, void *buf)
{
if (!dev_read(dev, offset, len, buf)) {
log_error("Read from %s failed", dev_name(dev));
return 0;
}
/*
* The second region is optional, and allows for
* a circular buffer on the device.
*/
if (!len2)
return 1;
if (!dev_read(dev, offset2, len2, buf + len)) {
log_error("Circular read from %s failed",
dev_name(dev));
return 0;
}
return 1;
}
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
* But fails if concurrent processes writing
*/

View File

@@ -53,8 +53,10 @@ int dev_is_md(struct device *dev, uint64_t *sb)
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
/* Check if it is an md component device. */
/* Version 1 is little endian; version 0.90.0 is machine endian */
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
(md_magic == xlate32(MD_SB_MAGIC))) {
((md_magic == xlate32(MD_SB_MAGIC)) ||
(md_magic == MD_SB_MAGIC))) {
if (sb)
*sb = sb_offset;
ret = 1;

View File

@@ -78,6 +78,8 @@ int dev_fd(struct device *dev);
const char *dev_name(const struct device *dev);
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, void *buf);
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_append(struct device *dev, size_t len, void *buffer);
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);

View File

@@ -301,10 +301,9 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
}
memset(pf, 0, sizeof(*pf));
if (!(pf->file = dm_malloc(strlen(file) + 1))) {
stack;
goto bad;
}
if (!(pf->file = dm_malloc(strlen(file) + 1)))
goto_bad;
strcpy(pf->file, file);
pf->real = real;
@@ -313,10 +312,8 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
goto bad;
}
if (!(f = dm_malloc(sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_malloc(sizeof(*f))))
goto_bad;
f->passes_filter = _lookup_p;
f->destroy = _persistent_destroy;

View File

@@ -15,13 +15,12 @@
#include "lib.h"
#include "filter-regex.h"
#include "matcher.h"
#include "device.h"
struct rfilter {
struct dm_pool *mem;
dm_bitset_t accept;
struct matcher *engine;
struct dm_regex *engine;
};
static int _extract_pattern(struct dm_pool *mem, const char *pat,
@@ -98,18 +97,15 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
unsigned count = 0;
int i, r = 0;
if (!(scratch = dm_pool_create("filter matcher", 1024))) {
stack;
return 0;
}
if (!(scratch = dm_pool_create("filter dm_regex", 1024)))
return_0;
/*
* count how many patterns we have.
*/
for (v = val; v; v = v->next) {
if (v->type != CFG_STRING) {
log_info("filter patterns must be enclosed in quotes");
log_error("filter patterns must be enclosed in quotes");
goto out;
}
@@ -119,10 +115,8 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
/*
* allocate space for them
*/
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
stack;
goto out;
}
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count)))
goto_out;
/*
* create the accept/reject bitset
@@ -136,15 +130,15 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
*/
for (v = val, i = count - 1; v; v = v->next, i--)
if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) {
log_info("invalid filter pattern");
log_error("invalid filter pattern");
goto out;
}
/*
* build the matcher.
*/
if (!(rf->engine = matcher_create(rf->mem, (const char **) regex,
count)))
if (!(rf->engine = dm_regex_create(rf->mem, (const char **) regex,
count)))
stack;
r = 1;
@@ -160,17 +154,12 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
struct str_list *sl;
list_iterate_items(sl, &dev->aliases) {
m = matcher_run(rf->engine, sl->str);
m = dm_regex_match(rf->engine, sl->str);
if (m >= 0) {
if (dm_bit(rf->accept, m)) {
if (!first) {
log_debug("%s: New preferred name",
sl->str);
list_del(&sl->list);
list_add_h(&dev->aliases, &sl->list);
}
if (!first)
dev_set_preferred_name(sl, dev);
return 1;
}
@@ -208,22 +197,16 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
return NULL;
}
if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) {
stack;
goto bad;
}
if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
goto_bad;
rf->mem = mem;
if (!_build_matcher(rf, patterns)) {
stack;
goto bad;
}
if (!_build_matcher(rf, patterns))
goto_bad;
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
goto_bad;
f->passes_filter = _accept_p;
f->destroy = _regex_destroy;

View File

@@ -284,10 +284,8 @@ struct dev_filter *sysfs_filter_create(const char *proc)
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
goto_bad;
f->passes_filter = _accept_p;
f->destroy = _destroy;

View File

@@ -357,10 +357,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
list_init(&dl->uuids);
list_init(&dl->lvds);
if (!_read_pvd(dev, &dl->pvd)) {
stack;
goto bad;
}
if (!_read_pvd(dev, &dl->pvd))
goto_bad;
/*
* is it an orphan ?

View File

@@ -131,10 +131,10 @@ static struct volume_group *_build_vg(struct format_instance *fid,
int partial;
if (!vg)
goto bad;
goto_bad;
if (list_empty(pvs))
goto bad;
goto_bad;
memset(vg, 0, sizeof(*vg));
@@ -146,24 +146,24 @@ static struct volume_group *_build_vg(struct format_instance *fid,
list_init(&vg->tags);
if (!_check_vgs(pvs, &partial))
goto bad;
goto_bad;
dl = list_item(pvs->n, struct disk_list);
if (!import_vg(mem, vg, dl, partial))
goto bad;
goto_bad;
if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count))
goto bad;
goto_bad;
if (!import_lvs(mem, vg, pvs))
goto bad;
goto_bad;
if (!import_extents(fid->fmt->cmd, vg, pvs))
goto bad;
goto_bad;
if (!import_snapshots(mem, vg, pvs))
goto bad;
goto_bad;
return vg;
@@ -191,15 +191,11 @@ static struct volume_group *_format1_vg_read(struct format_instance *fid,
vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
if (!read_pvs_in_vg
(fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs)) {
stack;
goto bad;
}
(fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs))
goto_bad;
if (!(vg = _build_vg(fid, &pvs))) {
stack;
goto bad;
}
if (!(vg = _build_vg(fid, &pvs)))
goto_bad;
bad:
dm_pool_destroy(mem);
@@ -415,17 +411,14 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
return 0;
}
if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) {
stack;
goto bad;
}
if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
goto_bad;
dl->mem = mem;
dl->dev = pv->dev;
if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) {
stack;
goto bad;
}
if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv))
goto_bad;
/* must be set to be able to zero gap after PV structure in
dev_write in order to make other disk tools happy */
@@ -434,10 +427,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
list_add(&pvs, &dl->list);
if (!write_disks(fmt, &pvs)) {
stack;
goto bad;
}
if (!write_disks(fmt, &pvs))
goto_bad;
dm_pool_destroy(mem);
return 1;

View File

@@ -59,22 +59,16 @@ static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
if (ll->lv->status & SNAPSHOT)
continue;
if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm)))) {
stack;
goto bad;
}
if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
goto_bad;
lvm->lv = ll->lv;
if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
* ll->lv->le_count))) {
stack;
goto bad;
}
* ll->lv->le_count)))
goto_bad;
if (!dm_hash_insert(maps, ll->lv->name, lvm)) {
stack;
goto bad;
}
if (!dm_hash_insert(maps, ll->lv->name, lvm))
goto_bad;
}
return maps;
@@ -203,6 +197,19 @@ static int _check_maps_are_complete(struct dm_hash_table *maps)
return 1;
}
static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
{
uint32_t len = 0;
do
len++;
while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
(lvm->map[le].pv &&
lvm->map[le + len].pe == lvm->map[le].pe + len));
return len;
}
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t le = 0, len;
@@ -215,13 +222,7 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
while (le < lvm->lv->le_count) {
len = 0;
do
len++;
while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
(lvm->map[le].pv &&
lvm->map[le + len].pe == lvm->map[le].pe + len));
len = _area_length(lvm, le);
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
len, 0, 0, NULL, 1, len, 0, 0, 0))) {
@@ -230,10 +231,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
lvm->map[le].pe)) {
stack;
return 0;
}
lvm->map[le].pe))
return_0;
list_add(&lvm->lv->segments, &seg->list);
@@ -244,7 +243,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
uint32_t seg_len, uint32_t base_le, uint32_t len)
uint32_t area_len, uint32_t base_le,
uint32_t total_area_len)
{
uint32_t st;
@@ -252,11 +252,11 @@ static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
* Is the next physical extent in every stripe adjacent to the last?
*/
for (st = 0; st < area_count; st++)
if ((lvm->map[base_le + st * len + seg_len].pv !=
lvm->map[base_le + st * len].pv) ||
(lvm->map[base_le + st * len].pv &&
lvm->map[base_le + st * len + seg_len].pe !=
lvm->map[base_le + st * len].pe + seg_len))
if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
lvm->map[base_le + st * total_area_len].pv) ||
(lvm->map[base_le + st * total_area_len].pv &&
lvm->map[base_le + st * total_area_len + area_len].pe !=
lvm->map[base_le + st * total_area_len].pe + area_len))
return 0;
return 1;
@@ -264,7 +264,7 @@ static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t st, le = 0, len;
uint32_t st, first_area_le = 0, total_area_len;
uint32_t area_len;
struct lv_segment *seg;
struct segment_type *segtype;
@@ -277,26 +277,25 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
"with logical extent count (%u) for %s",
lvm->stripes, lvm->lv->le_count, lvm->lv->name);
}
len = lvm->lv->le_count / lvm->stripes;
if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
total_area_len = lvm->lv->le_count / lvm->stripes;
while (le < len) {
if (!(segtype = get_segtype_from_string(cmd, "striped")))
return_0;
while (first_area_le < total_area_len) {
area_len = 1;
/*
* Find how many blocks are contiguous in all stripes
* Find how many extents are contiguous in all stripes
* and so can form part of this segment
*/
while (_check_stripe(lvm, lvm->stripes,
area_len * lvm->stripes, le, len))
area_len, first_area_le, total_area_len))
area_len++;
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
lvm->stripes * le,
lvm->stripes * first_area_le,
lvm->stripes * area_len,
0, lvm->stripe_size, NULL,
lvm->stripes,
@@ -310,15 +309,13 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
*/
for (st = 0; st < seg->area_count; st++)
if (!set_lv_segment_area_pv(seg, st,
lvm->map[le + st * len].pv,
lvm->map[le + st * len].pe)) {
stack;
return 0;
}
lvm->map[first_area_le + st * total_area_len].pv,
lvm->map[first_area_le + st * total_area_len].pe))
return_0;
list_add(&lvm->lv->segments, &seg->list);
le += seg->len;
first_area_le += area_len;
}
return 1;

View File

@@ -160,7 +160,7 @@ static int _out_with_comment_file(struct formatter *f, const char *comment,
for (i = 0; i < f->indent; i++)
white_space[i] = '\t';
white_space[i] = '\0';
fprintf(f->data.fp, white_space);
fputs(white_space, f->data.fp);
i = vfprintf(f->data.fp, fmt, ap);
if (comment) {
@@ -176,7 +176,7 @@ static int _out_with_comment_file(struct formatter *f, const char *comment,
while (++i < COMMENT_TAB);
fprintf(f->data.fp, comment);
fputs(comment, f->data.fp);
}
fputc('\n', f->data.fp);

View File

@@ -39,6 +39,9 @@
#define FMT_TEXT_NAME "lvm2"
#define FMT_TEXT_ALIAS "text"
static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
struct device_area *dev_area);
static struct format_instance *_text_create_text_instance(const struct format_type
*fmt, const char *vgname,
const char *vgid,
@@ -80,6 +83,164 @@ static int _text_vg_setup(struct format_instance *fid __attribute((unused)),
return 1;
}
/*
* Check if metadata area belongs to vg
*/
static int _mda_in_vg_raw(struct format_instance *fid __attribute((unused)),
struct volume_group *vg, struct metadata_area *mda)
{
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct pv_list *pvl;
list_iterate_items(pvl, &vg->pvs)
if (pvl->pv->dev == mdac->area.dev)
return 1;
return 0;
}
/*
* For circular region between region_start and region_start + region_size,
* back up one SECTOR_SIZE from 'region_ptr' and return the value.
* This allows reverse traversal through text metadata area to find old
* metadata.
*
* Parameters:
* region_start: start of the region (bytes)
* region_size: size of the region (bytes)
* region_ptr: pointer within the region (bytes)
* NOTE: region_start <= region_ptr <= region_start + region_size
*/
static uint64_t _get_prev_sector_circular(uint64_t region_start,
uint64_t region_size,
uint64_t region_ptr)
{
if (region_ptr >= region_start + SECTOR_SIZE)
return region_ptr - SECTOR_SIZE;
else
return (region_start + region_size - SECTOR_SIZE);
}
/*
* Analyze a metadata area for old metadata records in the circular buffer.
* This function just looks through and makes a first pass at the data in
* the sectors for particular things.
* FIXME: do something with each metadata area (try to extract vg, write
* raw data to file, etc)
*/
static int _pv_analyze_mda_raw (const struct format_type * fmt,
struct metadata_area *mda)
{
struct mda_header *mdah;
struct raw_locn *rlocn;
uint64_t area_start;
uint64_t area_size;
uint64_t prev_sector;
uint64_t latest_mrec_offset;
int i;
uint64_t offset;
uint64_t offset2;
uint64_t size;
uint64_t size2;
char *buf=NULL;
struct device_area *area;
struct mda_context *mdac;
int r=0;
mdac = (struct mda_context *) mda->metadata_locn;
log_print("Found text metadata area, offset=%"PRIu64", size=%"PRIu64,
mdac->area.start,
mdac->area.size);
area = &mdac->area;
if (!dev_open(area->dev))
return_0;
if (!(mdah = _raw_read_mda_header(fmt, area)))
goto_out;
rlocn = mdah->raw_locns;
/*
* The device area includes the metadata header as well as the
* records, so remove the metadata header from the start and size
*/
area_start = area->start + MDA_HEADER_SIZE;
area_size = area->size - MDA_HEADER_SIZE;
latest_mrec_offset = rlocn->offset + area->start;
/*
* Start searching at rlocn (point of live metadata) and go
* backwards.
*/
prev_sector = _get_prev_sector_circular(area_start, area_size,
latest_mrec_offset);
offset = prev_sector;
size = SECTOR_SIZE;
offset2 = size2 = 0;
i = 0;
while (prev_sector != latest_mrec_offset) {
prev_sector = _get_prev_sector_circular(area_start, area_size,
prev_sector);
/*
* FIXME: for some reason, the whole metadata region from
* area->start to area->start+area->size is not used.
* Only ~32KB seems to contain valid metadata records
* (LVM2 format - format_text). As a result, I end up with
* "maybe_config_section" returning true when there's no valid
* metadata in a sector (sectors with all nulls).
*/
if (!(buf = dm_pool_alloc(fmt->cmd->mem, size + size2)))
goto_out;
if (!dev_read_circular(area->dev, offset, size,
offset2, size2, buf))
goto_out;
/*
* FIXME: We could add more sophisticated metadata detection
*/
if (maybe_config_section(buf, size+size2)) {
/* FIXME: Validate region, pull out timestamp?, etc */
/* FIXME: Do something with this region */
log_verbose ("Found LVM2 metadata record at "
"offset=%"PRIu64", size=%"PRIu64", "
"offset2=%"PRIu64" size2=%"PRIu64,
offset, size, offset2, size2);
offset = prev_sector;
size = SECTOR_SIZE;
offset2 = size2 = 0;
} else {
/*
* Not a complete metadata record, assume we have
* metadata and just increase the size and offset.
* Start the second region if the previous sector is
* wrapping around towards the end of the disk.
*/
if (prev_sector > offset) {
offset2 = prev_sector;
size2 += SECTOR_SIZE;
} else {
offset = prev_sector;
size += SECTOR_SIZE;
}
}
dm_pool_free(fmt->cmd->mem, buf);
buf = NULL;
}
r = 1;
out:
if (buf)
dm_pool_free(fmt->cmd->mem, buf);
if (!dev_close(area->dev))
stack;
return r;
}
static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
struct logical_volume *lv)
{
@@ -1271,7 +1432,7 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
}
/* FIXME Optimise out repeated reading when cache lock held */
if (!(label_read(dev, &label))) {
if (!(label_read(dev, &label, UINT64_C(0)))) {
stack;
return 0;
}
@@ -1395,7 +1556,9 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
.vg_remove = _vg_remove_raw,
.vg_precommit = _vg_precommit_raw,
.vg_commit = _vg_commit_raw,
.vg_revert = _vg_revert_raw
.vg_revert = _vg_revert_raw,
.mda_in_vg = _mda_in_vg_raw,
.pv_analyze_mda = _pv_analyze_mda_raw,
};
/* pvmetadatasize in sectors */

View File

@@ -660,15 +660,11 @@ static struct volume_group *_read_vg(struct format_instance *fid,
/* eg Set to instance of fmt1 here if reading a format1 backup? */
vg->fid = fid;
if (!(vg->name = dm_pool_strdup(mem, vgn->key))) {
stack;
goto bad;
}
if (!(vg->name = dm_pool_strdup(mem, vgn->key)))
goto_bad;
if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN))) {
stack;
goto bad;
}
if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN)))
goto_bad;
vgn = vgn->child;

View File

@@ -107,7 +107,8 @@ struct labeller *label_get_handler(const char *name)
}
static struct labeller *_find_labeller(struct device *dev, char *buf,
uint64_t *label_sector)
uint64_t *label_sector,
uint64_t scan_sector)
{
struct labeller_i *li;
struct labeller *r = NULL;
@@ -117,12 +118,13 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
int found = 0;
char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
if (!dev_read(dev, scan_sector << SECTOR_SHIFT,
LABEL_SCAN_SIZE, readbuf)) {
log_debug("%s: Failed to read label area", dev_name(dev));
goto out;
}
/* Scan first few sectors for a valid label */
/* Scan a few sectors for a valid label */
for (sector = 0; sector < LABEL_SCAN_SECTORS;
sector += LABEL_SIZE >> SECTOR_SHIFT) {
lh = (struct label_header *) (readbuf +
@@ -132,13 +134,14 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
if (found) {
log_error("Ignoring additional label on %s at "
"sector %" PRIu64, dev_name(dev),
sector);
sector + scan_sector);
}
if (xlate64(lh->sector_xl) != sector) {
if (xlate64(lh->sector_xl) != sector + scan_sector) {
log_info("%s: Label for sector %" PRIu64
" found at sector %" PRIu64
" - ignoring", dev_name(dev),
xlate64(lh->sector_xl), sector);
xlate64(lh->sector_xl),
sector + scan_sector);
continue;
}
if (calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
@@ -153,19 +156,21 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
}
list_iterate_items(li, &_labellers) {
if (li->l->ops->can_handle(li->l, (char *) lh, sector)) {
if (li->l->ops->can_handle(li->l, (char *) lh,
sector + scan_sector)) {
log_very_verbose("%s: %s label detected",
dev_name(dev), li->name);
if (found) {
log_error("Ignoring additional label "
"on %s at sector %" PRIu64,
dev_name(dev), sector);
dev_name(dev),
sector + scan_sector);
continue;
}
r = li->l;
memcpy(buf, lh, LABEL_SIZE);
if (label_sector)
*label_sector = sector;
*label_sector = sector + scan_sector;
found = 1;
break;
}
@@ -256,7 +261,8 @@ int label_remove(struct device *dev)
}
/* FIXME Avoid repeated re-reading if cache lock held */
int label_read(struct device *dev, struct label **result)
int label_read(struct device *dev, struct label **result,
uint64_t scan_sector)
{
char buf[LABEL_SIZE] __attribute((aligned(8)));
struct labeller *l;
@@ -274,7 +280,7 @@ int label_read(struct device *dev, struct label **result)
return r;
}
if (!(l = _find_labeller(dev, buf, &sector)))
if (!(l = _find_labeller(dev, buf, &sector, scan_sector)))
goto_out;
if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
@@ -354,7 +360,7 @@ int label_verify(struct device *dev)
return_0;
}
if (!(l = _find_labeller(dev, buf, &sector)))
if (!(l = _find_labeller(dev, buf, &sector, UINT64_C(0))))
goto_out;
r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;

View File

@@ -96,7 +96,8 @@ int label_register_handler(const char *name, struct labeller *handler);
struct labeller *label_get_handler(const char *name);
int label_remove(struct device *dev);
int label_read(struct device *dev, struct label **result);
int label_read(struct device *dev, struct label **result,
uint64_t scan_sector);
int label_write(struct device *dev, struct label *label);
int label_verify(struct device *dev);
struct label *label_create(struct labeller *labeller);

View File

@@ -81,7 +81,7 @@ int init_no_locking(struct locking_type *locking, struct cmd_context *cmd)
locking->lock_resource = _no_lock_resource;
locking->reset_locking = _no_reset_locking;
locking->fin_locking = _no_fin_locking;
locking->flags = 0;
locking->flags = LCK_CLUSTERED;
return 1;
}

View File

@@ -138,5 +138,6 @@ void print_log(int level, const char *file, int line, const char *format, ...)
#define return_0 do { stack; return 0; } while (0)
#define return_NULL do { stack; return NULL; } while (0)
#define goto_out do { stack; goto out; } while (0)
#define goto_bad do { stack; goto bad; } while (0)
#endif

View File

@@ -280,10 +280,9 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
vg->seqno = 0;
vg->status = (RESIZEABLE_VG | LVM_READ | LVM_WRITE);
if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN))) {
stack;
goto bad;
}
if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN)))
goto_bad;
*vg->system_id = '\0';
vg->extent_size = extent_size;
@@ -320,7 +319,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
/* attach the pv's */
if (!vg_extend(vg->fid, vg, pv_count, pv_names))
goto bad;
goto_bad;
return vg;
@@ -505,6 +504,34 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
return 1;
}
int vg_split_mdas(struct cmd_context *cmd, struct volume_group *vg_from,
struct volume_group *vg_to)
{
struct metadata_area *mda, *mda2;
struct list *mdas_from, *mdas_to;
int common_mda = 0;
mdas_from = &vg_from->fid->metadata_areas;
mdas_to = &vg_to->fid->metadata_areas;
list_iterate_items_safe(mda, mda2, mdas_from) {
if (!mda->ops->mda_in_vg) {
common_mda = 1;
continue;
}
if (!mda->ops->mda_in_vg(vg_from->fid, vg_from, mda)) {
list_del(&mda->list);
list_add(mdas_to, &mda->list);
}
}
if (list_empty(mdas_from) || list_empty(mdas_to))
return common_mda;
return 1;
}
/* Sizes in sectors */
struct physical_volume *pv_create(const struct format_type *fmt,
struct device *dev,
@@ -533,10 +560,8 @@ struct physical_volume *pv_create(const struct format_type *fmt,
pv->dev = dev;
if (!(pv->vg_name = dm_pool_zalloc(mem, NAME_LEN))) {
stack;
goto bad;
}
if (!(pv->vg_name = dm_pool_zalloc(mem, NAME_LEN)))
goto_bad;
pv->status = ALLOCATABLE_PV;
@@ -759,6 +784,12 @@ int vg_validate(struct volume_group *vg)
r = 0;
}
}
if (strcmp(pvl->pv->vg_name, vg->name)) {
log_error("Internal error: VG name for PV %s is corrupted",
dev_name(pvl->pv->dev));
r = 0;
}
}
if (!check_pv_segments(vg)) {
@@ -963,6 +994,30 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
return vg;
}
static int _update_pv_list(struct list *all_pvs, struct volume_group *vg)
{
struct pv_list *pvl, *pvl2;
list_iterate_items(pvl, &vg->pvs) {
list_iterate_items(pvl2, all_pvs) {
if (pvl->pv->dev == pvl2->pv->dev)
goto next_pv;
}
/* PV is not on list so add it. Note that we don't copy it. */
if (!(pvl2 = dm_pool_zalloc(vg->cmd->mem, sizeof(*pvl2)))) {
log_error("pv_list allocation for '%s' failed",
dev_name(pvl->pv->dev));
return 0;
}
pvl2->pv = pvl->pv;
list_add(all_pvs, &pvl2->list);
next_pv:
;
}
return 1;
}
/* Caller sets consistent to 1 if it's safe for vg_read to correct
* inconsistent metadata on disk (i.e. the VG write lock is held).
* This guarantees only consistent metadata is returned unless PARTIAL_VG.
@@ -982,9 +1037,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
struct volume_group *vg, *correct_vg = NULL;
struct metadata_area *mda;
int inconsistent = 0;
int inconsistent_vgid = 0;
int use_precommitted = precommitted;
struct list *pvids;
struct pv_list *pvl;
struct pv_list *pvl, *pvl2;
struct list all_pvs;
char uuid[64] __attribute((aligned(8)));
if (!*vgname) {
if (use_precommitted) {
@@ -1069,6 +1127,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
}
list_init(&all_pvs);
/* Failed to find VG where we expected it - full scan and retry */
if (!correct_vg) {
inconsistent = 0;
@@ -1104,13 +1164,25 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
if (!correct_vg) {
correct_vg = vg;
if (!_update_pv_list(&all_pvs, correct_vg))
return_NULL;
continue;
}
if (strncmp((char *)vg->id.uuid,
(char *)correct_vg->id.uuid, ID_LEN)) {
inconsistent = 1;
inconsistent_vgid = 1;
}
/* FIXME Also ensure contents same - checksums same? */
if (correct_vg->seqno != vg->seqno) {
inconsistent = 1;
if (vg->seqno > correct_vg->seqno)
if (vg->seqno > correct_vg->seqno) {
if (!_update_pv_list(&all_pvs, vg))
return_NULL;
correct_vg = vg;
}
}
}
@@ -1143,17 +1215,42 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
return correct_vg;
}
log_print("Inconsistent metadata copies found - updating "
"to use version %u", correct_vg->seqno);
/* Don't touch if vgids didn't match */
if (inconsistent_vgid) {
log_error("Inconsistent metadata UUIDs found for "
"volume group %s", vgname);
*consistent = 0;
return correct_vg;
}
log_print("Inconsistent metadata found for VG %s - updating "
"to use version %u", vgname, correct_vg->seqno);
if (!vg_write(correct_vg)) {
log_error("Automatic metadata correction failed");
return NULL;
}
if (!vg_commit(correct_vg)) {
log_error("Automatic metadata correction commit "
"failed");
return NULL;
}
list_iterate_items(pvl, &all_pvs) {
list_iterate_items(pvl2, &correct_vg->pvs) {
if (pvl->pv->dev == pvl2->pv->dev)
goto next_pv;
}
if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
return_NULL;
log_error("Removing PV %s (%s) that no longer belongs to VG %s",
dev_name(pvl->pv->dev), uuid, correct_vg->name);
if (!pv_write_orphan(cmd, pvl->pv))
return_NULL;
next_pv:
;
}
}
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
@@ -1303,7 +1400,7 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
return NULL;
}
if (!(label_read(dev, &label))) {
if (!(label_read(dev, &label, UINT64_C(0)))) {
if (warnings)
log_error("No physical volume label read from %s",
pv_name);
@@ -1433,3 +1530,66 @@ int pv_write(struct cmd_context *cmd __attribute((unused)), struct physical_volu
return 1;
}
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
{
const char *old_vg_name = pv->vg_name;
pv->vg_name = ORPHAN;
pv->status = ALLOCATABLE_PV;
if (!dev_get_size(pv->dev, &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(pv->dev));
return 0;
}
if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
log_error("Failed to clear metadata from physical "
"volume \"%s\" after removal from \"%s\"",
dev_name(pv->dev), old_vg_name);
return 0;
}
return 1;
}
/*
* Returns:
* 0 - fail
* 1 - success
*/
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
int64_t label_sector)
{
struct label *label;
struct device *dev;
struct metadata_area *mda;
struct lvmcache_info *info;
dev = dev_cache_get(pv_name, cmd->filter);
if (!dev) {
log_error("Device %s not found (or ignored by filtering).",
pv_name);
return 0;
}
/*
* First, scan for LVM labels.
*/
if (!label_read(dev, &label, label_sector)) {
log_error("Could not find LVM label on %s",
pv_name);
return 0;
}
log_print("Found label on %s, sector %"PRIu64", type=%s",
pv_name, label->sector, label->type);
/*
* Next, loop through metadata areas
*/
info = label->info;
list_iterate_items(mda, &info->mdas)
mda->ops->pv_analyze_mda(info->fmt, mda);
return 1;
}

View File

@@ -178,6 +178,17 @@ struct metadata_area_ops {
struct volume_group * vg, struct metadata_area * mda);
int (*vg_remove) (struct format_instance * fi, struct volume_group * vg,
struct metadata_area * mda);
/*
* Check if metadata area belongs to vg
*/
int (*mda_in_vg) (struct format_instance * fi,
struct volume_group * vg, struct metadata_area *mda);
/*
* Analyze a metadata area on a PV.
*/
int (*pv_analyze_mda) (const struct format_type * fmt,
struct metadata_area *mda);
};
struct metadata_area {
@@ -423,6 +434,7 @@ struct list *get_vgids(struct cmd_context *cmd, int full_scan);
int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
struct list *mdas, int64_t label_sector);
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
/* pe_start and pe_end relate to any existing data so that new metadata
* areas can avoid overlap */
@@ -437,6 +449,8 @@ struct physical_volume *pv_create(const struct format_type *fmt,
uint64_t pvmetadatasize, struct list *mdas);
int pv_resize(struct physical_volume *pv, struct volume_group *vg,
uint32_t new_pe_count);
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
int64_t label_sector);
struct volume_group *vg_create(struct cmd_context *cmd, const char *name,
uint32_t extent_size, uint32_t max_pv,
@@ -449,6 +463,8 @@ int vg_extend(struct format_instance *fi, struct volume_group *vg,
int pv_count, char **pv_names);
int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
uint32_t new_extent_size);
int vg_split_mdas(struct cmd_context *cmd, struct volume_group *vg_from,
struct volume_group *vg_to);
/* Manipulate LVs */
struct logical_volume *lv_create_empty(struct format_instance *fi,

View File

@@ -21,6 +21,7 @@
#include "activate.h"
#include "lv_alloc.h"
#include "lvm-string.h"
#include "str_list.h"
#include "locking.h" /* FIXME Should not be used in this file */
#include "defaults.h" /* FIXME: should this be defaults.h? */
@@ -77,6 +78,42 @@ static void _move_lv_segments(struct logical_volume *lv_to, struct logical_volum
lv_from->size = 0;
}
/*
* Delete independent/orphan LV, it must acquire lock.
*/
static int _delete_lv(struct lv_segment *mirrored_seg, struct logical_volume *lv)
{
struct cmd_context *cmd = mirrored_seg->lv->vg->cmd;
struct str_list *sl;
/* Inherit tags - maybe needed for activation */
if (!str_list_match_list(&mirrored_seg->lv->tags, &lv->tags)) {
list_iterate_items(sl, &mirrored_seg->lv->tags)
if (!str_list_add(cmd->mem, &lv->tags, sl->str)) {
log_error("Aborting. Unable to tag.");
return 0;
}
if (!vg_write(mirrored_seg->lv->vg) ||
!vg_commit(mirrored_seg->lv->vg)) {
log_error("Intermediate VG commit for orphan volume failed.");
return 0;
}
}
if (!activate_lv(cmd, lv))
return_0;
if (!deactivate_lv(cmd, lv))
return_0;
if (!lv_remove(lv))
return_0;
return 1;
}
/*
* Reduce mirrored_seg to num_mirrors images.
*/
@@ -205,57 +242,15 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
}
/* Delete the 'orphan' LVs */
for (m = num_mirrors; m < old_area_count; m++) {
/* LV is now independent of the mirror so must acquire lock. */
if (!activate_lv(mirrored_seg->lv->vg->cmd, seg_lv(mirrored_seg, m))) {
stack;
for (m = num_mirrors; m < old_area_count; m++)
if (!_delete_lv(mirrored_seg, seg_lv(mirrored_seg, m)))
return 0;
}
if (!deactivate_lv(mirrored_seg->lv->vg->cmd, seg_lv(mirrored_seg, m))) {
stack;
return 0;
}
if (lv1 && !_delete_lv(mirrored_seg, lv1))
return 0;
if (!lv_remove(seg_lv(mirrored_seg, m))) {
stack;
return 0;
}
}
if (lv1) {
if (!activate_lv(mirrored_seg->lv->vg->cmd, lv1)) {
stack;
return 0;
}
if (!deactivate_lv(mirrored_seg->lv->vg->cmd, lv1)) {
stack;
return 0;
}
if (!lv_remove(lv1)) {
stack;
return 0;
}
}
if (log_lv) {
if (!activate_lv(mirrored_seg->lv->vg->cmd, log_lv)) {
stack;
return 0;
}
if (!deactivate_lv(mirrored_seg->lv->vg->cmd, log_lv)) {
stack;
return 0;
}
if (!lv_remove(log_lv)) {
stack;
return 0;
}
}
if (log_lv && !_delete_lv(mirrored_seg, log_lv))
return 0;
return 1;
}

View File

@@ -19,7 +19,7 @@
#ifndef _LVM_LIB_H
#define _LVM_LIB_H
#include <configure.h>
#include "configure.h"
#define _REENTRANT
#define _GNU_SOURCE

View File

@@ -256,6 +256,8 @@ void sync_dir(const char *file)
int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only)
{
int lockfd;
char *dir;
char *c;
struct flock lock = {
.l_type = lock_type,
.l_whence = 0,
@@ -263,6 +265,21 @@ int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only)
.l_len = 0
};
if (!(dir = dm_strdup(file))) {
log_error("fcntl_lock_file failed in strdup.");
return -1;
}
if ((c = strrchr(dir, '/')))
*c = '\0';
if (!create_dir(dir)) {
dm_free(dir);
return -1;
}
dm_free(dir);
log_very_verbose("Locking %s (%s, %hd)", file,
(lock_type == F_WRLCK) ? "F_WRLCK" : "F_RDLCK",
lock_type);

View File

@@ -36,18 +36,38 @@ int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
}
/*
* Device layer names are all of the form <vg>-<lv>-<layer>, any
* other hyphens that appear in these names are quoted with yet
* another hyphen. The top layer of any device has no layer
* name. eg, vg0-lvol0.
* Count occurences of 'c' in 'str' until we reach a null char.
*
* Returns:
* len - incremented for each char we encounter, whether 'c' or not.
* count - number of occurences of 'c'
*/
static void _count_hyphens(const char *str, size_t *len, int *hyphens)
void count_chars(const char *str, size_t *len, int *count,
const char c)
{
const char *ptr;
for (ptr = str; *ptr; ptr++, (*len)++)
if (*ptr == '-')
(*hyphens)++;
if (*ptr == c)
(*count)++;
}
/*
* Count occurences of 'c' in 'str' of length 'size'.
*
* Returns:
* # of occurences of 'c'
*/
unsigned count_chars_len(const char *str, size_t size, const char c)
{
int i;
unsigned count=0;
for (i=0; i < size; i++)
if (str[i] == c)
count++;
return count;
}
/*
@@ -73,11 +93,11 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
int hyphens = 1;
char *r, *out;
_count_hyphens(vgname, &len, &hyphens);
_count_hyphens(lvname, &len, &hyphens);
count_chars(vgname, &len, &hyphens, '-');
count_chars(lvname, &len, &hyphens, '-');
if (layer && *layer) {
_count_hyphens(layer, &len, &hyphens);
count_chars(layer, &len, &hyphens, '-');
hyphens++;
}
@@ -105,6 +125,12 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
return r;
}
/*
* Device layer names are all of the form <vg>-<lv>-<layer>, any
* other hyphens that appear in these names are quoted with yet
* another hyphen. The top layer of any device has no layer
* name. eg, vg0-lvol0.
*/
int validate_name(const char *n)
{
register char c;

View File

@@ -30,4 +30,8 @@ char *build_dm_name(struct dm_pool *mem, const char *vg,
int validate_name(const char *n);
void count_chars(const char *str, size_t *len, int *count,
char c);
unsigned count_chars_len(const char *str, size_t size, char c);
#endif

View File

@@ -1,25 +0,0 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_MATCHER_H
#define _LVM_MATCHER_H
struct matcher;
struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
unsigned num);
int matcher_run(struct matcher *m, const char *begin);
#endif

View File

@@ -49,7 +49,7 @@ static char _alloc_policy_char(alloc_policy_t alloc)
case ALLOC_CONTIGUOUS:
return 'c';
case ALLOC_CLING:
return 'C';
return 'l';
case ALLOC_NORMAL:
return 'n';
case ALLOC_ANYWHERE:
@@ -868,11 +868,11 @@ static const struct dm_report_object_type _report_types[] = {
#define STR DM_REPORT_FIELD_TYPE_STRING
#define NUM DM_REPORT_FIELD_TYPE_NUMBER
#define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, id, (off_t)((void *)&_dummy._ ## strct.field - (void *)&_dummy._ ## strct), head, width, sorttype, &_ ## func ## _disp, desc},
#define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, sorttype, (off_t)((void *)&_dummy._ ## strct.field - (void *)&_dummy._ ## strct), width, id, head, &_ ## func ## _disp, desc},
static struct dm_report_field_type _fields[] = {
#include "columns.h"
{0, "", 0, "", 0, 0, NULL, NULL},
{0, 0, 0, 0, "", "", NULL, NULL},
};
#undef STR

View File

@@ -127,3 +127,5 @@ dm_report_field_int32
dm_report_field_uint32
dm_report_field_uint64
dm_report_field_set_value
dm_regex_create
dm_regex_match

View File

@@ -27,6 +27,9 @@ SOURCES =\
libdm-report.c \
mm/dbg_malloc.c \
mm/pool.c \
regex/matcher.c \
regex/parse_rx.c \
regex/ttree.c \
$(interface)/libdm-iface.c
INCLUDES = -I$(interface)

View File

@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_BITSET_H
#define _LVM_BITSET_H
#ifndef _DM_BITSET_H
#define _DM_BITSET_H
#include "pool.h"

View File

@@ -68,14 +68,14 @@ static struct dm_hash_node *_create_node(const char *str, unsigned len)
return n;
}
static unsigned long _hash(const unsigned char *str, unsigned len)
static unsigned long _hash(const char *str, unsigned len)
{
unsigned long h = 0, g;
unsigned i;
for (i = 0; i < len; i++) {
h <<= 4;
h += _nums[*str++];
h += _nums[(unsigned char) *str++];
g = h & ((unsigned long) 0xf << 16u);
if (g) {
h ^= g >> 16u;

View File

@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_HASH_H
#define _LVM_HASH_H
#ifndef _DM_HASH_H
#define _DM_HASH_H
struct hash_table;
struct hash_node;

View File

@@ -433,12 +433,12 @@ static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info)
return 1;
}
static const char *_dm_task_get_name_v1(struct dm_task *dmt)
static const char *_dm_task_get_name_v1(const struct dm_task *dmt)
{
return (dmt->dmi.v1->name);
}
static const char *_dm_task_get_uuid_v1(struct dm_task *dmt)
static const char *_dm_task_get_uuid_v1(const struct dm_task *dmt)
{
return (dmt->dmi.v1->uuid);
}
@@ -924,7 +924,7 @@ int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
return 1;
}
const char *dm_task_get_name(struct dm_task *dmt)
const char *dm_task_get_name(const struct dm_task *dmt)
{
#ifdef DM_COMPAT
if (_dm_version == 1)
@@ -934,7 +934,7 @@ const char *dm_task_get_name(struct dm_task *dmt)
return (dmt->dmi.v4->name);
}
const char *dm_task_get_uuid(struct dm_task *dmt)
const char *dm_task_get_uuid(const struct dm_task *dmt)
{
#ifdef DM_COMPAT
if (_dm_version == 1)
@@ -1555,7 +1555,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
dmi->flags |= DM_SKIP_BDGET_FLAG;
log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s"
"%s%c%c%s %.0llu %s [%u]",
"%s%c%c%s %.0" PRIu64 " %s [%u]",
_cmd_data_v4[dmt->type].name,
dmi->name, dmi->uuid, dmt->newname ? " " : "",
dmt->newname ? dmt->newname : "",

View File

@@ -133,8 +133,8 @@ struct dm_versions {
int dm_get_library_version(char *version, size_t size);
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
const char *dm_task_get_name(struct dm_task *dmt);
const char *dm_task_get_uuid(struct dm_task *dmt);
const char *dm_task_get_name(const struct dm_task *dmt);
const char *dm_task_get_uuid(const struct dm_task *dmt);
struct dm_deps *dm_task_get_deps(struct dm_task *dmt);
struct dm_names *dm_task_get_names(struct dm_task *dmt);
@@ -630,6 +630,25 @@ char *dm_basename(const char *path);
*/
int dm_asprintf(char **buf, const char *format, ...);
/*********************
* regular expressions
*********************/
struct dm_regex;
/*
* Initialise an array of num patterns for matching.
* Uses memory from mem.
*/
struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
unsigned num_patterns);
/*
* Match string s against the patterns.
* Returns the index of the highest pattern in the array that matches,
* or -1 if none match.
*/
int dm_regex_match(struct dm_regex *regex, const char *s);
/*********************
* reporting functions
*********************/
@@ -657,11 +676,11 @@ struct dm_report_field;
struct dm_report;
struct dm_report_field_type {
uint32_t type; /* object type id */
const char id[32]; /* string used to specify the field */
unsigned int offset; /* byte offset in the object */
const char heading[32]; /* string printed in header */
int width; /* default width */
uint32_t flags; /* DM_REPORT_FIELD_* */
uint32_t offset; /* byte offset in the object */
int32_t width; /* default width */
const char id[32]; /* string used to specify the field */
const char heading[32]; /* string printed in header */
int (*report_fn)(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private);

View File

@@ -60,7 +60,7 @@ struct field_properties {
struct list list;
uint32_t field_num;
uint32_t sort_posn;
unsigned width;
int32_t width;
const struct dm_report_object_type *type;
uint32_t flags;
};
@@ -296,35 +296,74 @@ static int _copy_field(struct dm_report *rh, struct field_properties *dest,
return 1;
}
static struct field_properties * _add_field(struct dm_report *rh,
uint32_t field_num, uint32_t flags)
{
struct field_properties *fp;
rh->report_types |= rh->fields[field_num].type;
if (!(fp = dm_pool_zalloc(rh->mem, sizeof(struct field_properties)))) {
log_error("dm_report: struct field_properties allocation "
"failed");
return NULL;
}
if (!_copy_field(rh, fp, field_num)) {
stack;
dm_pool_free(rh->mem, fp);
return NULL;
}
fp->flags |= flags;
/*
* Place hidden fields at the front so list_end() will
* tell us when we've reached the last visible field.
*/
if (fp->flags & FLD_HIDDEN)
list_add_h(&rh->field_props, &fp->list);
else
list_add(&rh->field_props, &fp->list);
return fp;
}
/*
* Compare name1 against name2 or prefix plus name2
* name2 is not necessarily null-terminated.
* len2 is the length of name2.
*/
static int _is_same_field(const char *name1, const char *name2,
size_t len2, const char *prefix)
{
size_t prefix_len;
/* Exact match? */
if (!strncasecmp(name1, name2, len2) && strlen(name1) == len2)
return 1;
/* Match including prefix? */
prefix_len = strlen(prefix);
if (!strncasecmp(prefix, name1, prefix_len) &&
!strncasecmp(name1 + prefix_len, name2, len2) &&
strlen(name1) == prefix_len + len2)
return 1;
return 0;
}
static int _field_match(struct dm_report *rh, const char *field, size_t flen)
{
uint32_t f, l;
struct field_properties *fp;
uint32_t f;
if (!flen)
return 0;
for (f = 0; rh->fields[f].report_fn; f++) {
if ((!strncasecmp(rh->fields[f].id, field, flen) &&
strlen(rh->fields[f].id) == flen) ||
(l = strlen(rh->field_prefix),
!strncasecmp(rh->field_prefix, rh->fields[f].id, l) &&
!strncasecmp(rh->fields[f].id + l, field, flen) &&
strlen(rh->fields[f].id) == l + flen)) {
rh->report_types |= rh->fields[f].type;
if (!(fp = dm_pool_zalloc(rh->mem, sizeof(*fp)))) {
log_error("dm_report: "
"struct field_properties allocation "
"failed");
return 0;
}
if (!_copy_field(rh, fp, f))
return 0;
list_add(&rh->field_props, &fp->list);
return 1;
}
}
for (f = 0; rh->fields[f].report_fn; f++)
if (_is_same_field(rh->fields[f].id, field, flen,
rh->field_prefix))
return _add_field(rh, f, 0) ? 1 : 0;
return 0;
}
@@ -341,21 +380,8 @@ static int _add_sort_key(struct dm_report *rh, uint32_t field_num,
}
}
if (!found) {
rh->report_types |= rh->fields[field_num].type;
if (!(found = dm_pool_zalloc(rh->mem, sizeof(*found)))) {
log_error("dm_report: "
"struct field_properties allocation failed");
return 0;
}
if (!_copy_field(rh, found, field_num))
return 0;
/* Add as a non-display field */
found->flags |= FLD_HIDDEN;
list_add(&rh->field_props, &found->list);
}
if (!found && !(found = _add_field(rh, field_num, FLD_HIDDEN)))
return_0;
if (found->flags & FLD_SORT_KEY) {
log_error("dm_report: Ignoring duplicate sort field: %s",
@@ -372,7 +398,7 @@ static int _add_sort_key(struct dm_report *rh, uint32_t field_num,
static int _key_match(struct dm_report *rh, const char *key, size_t len)
{
uint32_t f, l;
uint32_t f;
uint32_t flags;
if (!len)
@@ -394,16 +420,10 @@ static int _key_match(struct dm_report *rh, const char *key, size_t len)
return 0;
}
for (f = 0; rh->fields[f].report_fn; f++) {
if ((!strncasecmp(rh->fields[f].id, key, len) &&
strlen(rh->fields[f].id) == len) ||
(l = strlen(rh->field_prefix),
!strncasecmp(rh->field_prefix, rh->fields[f].id, l) &&
!strncasecmp(rh->fields[f].id + l, key, len) &&
strlen(rh->fields[f].id) == l + len)) {
for (f = 0; rh->fields[f].report_fn; f++)
if (_is_same_field(rh->fields[f].id, key, len,
rh->field_prefix))
return _add_sort_key(rh, f, flags);
}
}
return 0;
}
@@ -504,15 +524,20 @@ struct dm_report *dm_report_init(uint32_t *report_types,
if (!(rh->mem = dm_pool_create("report", 10 * 1024))) {
log_error("dm_report_init: allocation of memory pool failed");
dm_free(rh);
return NULL;
}
/* Generate list of fields for output based on format string & flags */
if (!_parse_options(rh, output_fields))
if (!_parse_options(rh, output_fields)) {
dm_report_free(rh);
return NULL;
}
if (!_parse_keys(rh, sort_keys))
if (!_parse_keys(rh, sort_keys)) {
dm_report_free(rh);
return NULL;
}
/* Return updated types value for further compatility check by caller */
if (report_types)
@@ -750,7 +775,7 @@ int dm_report_output(struct dm_report *rh)
struct dm_report_field *field;
const char *repstr;
char buf[4096];
unsigned width;
int32_t width;
uint32_t align;
if (list_empty(&rh->rows))

View File

@@ -117,7 +117,7 @@ int dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
n = vsnprintf(buf, bufsize, format, ap);
va_end(ap);
if (n < 0 || (n > bufsize - 1))
if (n < 0 || ((unsigned) n + 1 > bufsize))
return -1;
return n;

View File

@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_DBG_MALLOC_H
#define _LVM_DBG_MALLOC_H
#ifndef _DM_DBG_MALLOC_H
#define _DM_DBG_MALLOC_H
#include <stdlib.h>
#include <string.h>

View File

@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_POOL_H
#define _LVM_POOL_H
#ifndef _DM_POOL_H
#define _DM_POOL_H
#include <string.h>
#include <stdlib.h>

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
@@ -14,9 +14,9 @@
*/
#include "lib.h"
#include "matcher.h"
#include "parse_rx.h"
#include "ttree.h"
#include "assert.h"
struct dfa_state {
int final;
@@ -29,7 +29,7 @@ struct state_queue {
struct state_queue *next;
};
struct matcher { /* Instance variables for the lexer */
struct dm_regex { /* Instance variables for the lexer */
struct dfa_state *start;
unsigned num_nodes;
int nodes_entered;
@@ -52,7 +52,7 @@ static int _count_nodes(struct rx_node *rx)
return r;
}
static void _fill_table(struct matcher *m, struct rx_node *rx)
static void _fill_table(struct dm_regex *m, struct rx_node *rx)
{
assert((rx->type != OR) || (rx->left && rx->right));
@@ -65,7 +65,7 @@ static void _fill_table(struct matcher *m, struct rx_node *rx)
m->nodes[m->nodes_entered++] = rx;
}
static void _create_bitsets(struct matcher *m)
static void _create_bitsets(struct dm_regex *m)
{
int i;
@@ -77,7 +77,7 @@ static void _create_bitsets(struct matcher *m)
}
}
static void _calc_functions(struct matcher *m)
static void _calc_functions(struct dm_regex *m)
{
int i, j, final = 1;
struct rx_node *rx, *c1, *c2;
@@ -189,7 +189,7 @@ static struct state_queue *_create_state_queue(struct dm_pool *mem,
return r;
}
static int _calc_states(struct matcher *m, struct rx_node *rx)
static int _calc_states(struct dm_regex *m, struct rx_node *rx)
{
unsigned iwidth = (m->num_nodes / DM_BITS_PER_INT) + 1;
struct ttree *tt = ttree_create(m->scratch, iwidth);
@@ -263,43 +263,38 @@ static int _calc_states(struct matcher *m, struct rx_node *rx)
return 1;
}
struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
unsigned num)
struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
unsigned num_patterns)
{
char *all, *ptr;
int i;
size_t len = 0;
struct rx_node *rx;
struct dm_pool *scratch = dm_pool_create("regex matcher", 10 * 1024);
struct matcher *m;
struct dm_regex *m;
if (!scratch) {
stack;
return NULL;
}
if (!scratch)
return_NULL;
if (!(m = dm_pool_alloc(mem, sizeof(*m)))) {
stack;
dm_pool_destroy(scratch);
return NULL;
return_NULL;
}
memset(m, 0, sizeof(*m));
/* join the regexps together, delimiting with zero */
for (i = 0; i < num; i++)
for (i = 0; i < num_patterns; i++)
len += strlen(patterns[i]) + 8;
ptr = all = dm_pool_alloc(scratch, len + 1);
if (!all) {
stack;
goto bad;
}
if (!all)
goto_bad;
for (i = 0; i < num; i++) {
for (i = 0; i < num_patterns; i++) {
ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS);
if (i < (num - 1))
if (i < (num_patterns - 1))
*ptr++ = '|';
}
@@ -314,10 +309,8 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
m->num_nodes = _count_nodes(rx);
m->nodes = dm_pool_alloc(scratch, sizeof(*m->nodes) * m->num_nodes);
if (!m->nodes) {
stack;
goto bad;
}
if (!m->nodes)
goto_bad;
_fill_table(m, rx);
_create_bitsets(m);
@@ -330,7 +323,7 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
bad:
dm_pool_destroy(scratch);
dm_pool_destroy(mem);
dm_pool_free(mem, m);
return NULL;
}
@@ -345,16 +338,16 @@ static struct dfa_state *_step_matcher(int c, struct dfa_state *cs, int *r)
return cs;
}
int matcher_run(struct matcher *m, const char *b)
int dm_regex_match(struct dm_regex *regex, const char *s)
{
struct dfa_state *cs = m->start;
struct dfa_state *cs = regex->start;
int r = 0;
if (!(cs = _step_matcher(HAT_CHAR, cs, &r)))
goto out;
for (; *b; b++)
if (!(cs = _step_matcher(*b, cs, &r)))
for (; *s; s++)
if (!(cs = _step_matcher(*s, cs, &r)))
goto out;
_step_matcher(DOLLAR_CHAR, cs, &r);

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_PARSE_REGEX_H
#define _LVM_PARSE_REGEX_H
#ifndef _DM_PARSE_REGEX_H
#define _DM_PARSE_REGEX_H
enum {
CAT,

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_TTREE_H
#define _LVM_TTREE_H
#ifndef _DM_TTREE_H
#define _DM_TTREE_H
struct ttree;

View File

@@ -56,7 +56,7 @@ endif
.SUFFIXES: .c .d .o .so .a .po .pot .mo .dylib
CFLAGS += -fPIC -Wall -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wmissing-noreturn
CFLAGS += -fPIC -Wall -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wmissing-noreturn -Wformat-security
#CFLAGS += -W -Wconversion -Wpointer-arith -Wredundant-decls -Wbad-function-cast -Wcast-qual
#CFLAGS += -pedantic -std=gnu99
@@ -94,7 +94,7 @@ STRIP=
LIB_VERSION := $(shell cat $(top_srcdir)/VERSION | \
awk -F '.' '{printf "%s.%s",$$1,$$2}')
INCLUDES += -I. -I$(top_srcdir)/include
INCLUDES += -I$(top_srcdir)/include
ifneq ("@DMDIR@", "")
INCLUDES += -I@DMDIR@/include

View File

@@ -20,7 +20,7 @@ MAN5=lvm.conf.5
MAN8=lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 \
lvmchange.8 lvmdiskscan.8 lvmdump.8 \
lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
lvscan.8 pvchange.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
vgimport.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \

View File

@@ -3,6 +3,9 @@
dmsetup \- low level logical volume management
.SH SYNOPSIS
.ad l
.B dmsetup help
.I [-c|-C|--columns]
.br
.B dmsetup create
.I device_name [-u uuid] [--notable | --table <table> | table_file]
.br
@@ -33,21 +36,25 @@ dmsetup \- low level logical volume management
.B dmsetup message
.I device_name sector message
.br
.B dmsetup ls [--target target_type] [--exec command] [--tree [-o options]]
.B dmsetup ls
.I [--target target_type] [--exec command] [--tree [-o options]]
.br
.B dmsetup info
.I [device_name]
.br
.B dmsetup info -c|-C|--columns [--noheadings] [-o name]
.B dmsetup info -c|-C|--columns
.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
.I [device_name]
.br
.B dmsetup deps
.I [device_name]
.br
.B dmsetup status [--target target_type]
.B dmsetup status
.I [--target target_type]
.I [device_name]
.br
.B dmsetup table [--target target_type]
.B dmsetup table
.I [--target target_type]
.I [device_name]
.br
.B dmsetup wait
@@ -103,7 +110,7 @@ Tell the kernel not to supply the open reference count for the device.
When creating a device, don't load any table.
.IP \fB-o|--options
.br
Specify which fields to display. Only \fB-o\ name\fP is supported.
Specify which fields to display.
.IP \fB-r|--readonly
.br
Set the table being loaded read-only.
@@ -136,6 +143,11 @@ See below for information on the table format.
.br
Outputs a list of (major, minor) pairs for devices referenced by the
live table for the specified device.
.IP \fBhelp
.I [-c|-C|--columns]
.br
Outputs a summary of the commands available, optionally including
the list of report fields.
.IP \fBinfo
.I [device_name]
.br
@@ -154,6 +166,17 @@ Outputs some brief information about the device in the form:
Number of targets in the live table
.br
UUID
.IP \fBinfo -c|-C|--columns
.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
.I [device_name]
.br
Output you can customise.
Fields are comma-separated and chosen from the following list:
name, major, minor, attr, open, segments, events, uuid.
Attributes are: (L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.
Precede the list with '+' to append
to the default selection of columns instead of replacing it.
Precede any sort_field with - for a reverse sort on that column.
.IP \fBls
.I [--target target_type]
.I [--exec command]

View File

@@ -12,7 +12,7 @@ lvchange \- change attributes of a logical volume
[\-\-ignorelockingfailure]
[\-\-monitor {y|n}]
[\-M/\-\-persistent y/n] [\-\-minor minor]
[\-P/\-\-partial y/n]
[\-P/\-\-partial]
[\-p/\-\-permission r/w] [\-r/\-\-readahead ReadAheadSectors]
[\-\-refresh]
[\-t/\-\-test]

View File

@@ -194,6 +194,7 @@ All tools return a status code of zero on success or non-zero on failure.
.BR lvs (8),
.BR lvscan (8),
.BR pvchange (8),
.BR pvck (8),
.BR pvcreate (8),
.BR pvdisplay (8),
.BR pvmove (8),

View File

@@ -81,6 +81,11 @@ LVM physical volumes.
Devices in directories outside this hierarchy will be ignored.
Defaults to "/dev".
.IP
\fBpreferred_names\fP \(em List of patterns compared in turn against
all the pathnames referencing the same device in in the scanned directories.
The pathname that matches the earliest pattern in the list is the
one used in any output.
.IP
\fBfilter\fP \(em List of patterns to apply to devices found by a scan.
Patterns are regular expressions delimited by any character and preceded
by \fBa\fP (for accept) or \fBr\fP (for reject). The list is traversed
@@ -95,8 +100,8 @@ pattern it is rejected; otherwise it is accepted.
As an example, to ignore /dev/cdrom you could use:
\fBdevices { filter=["r|cdrom|"] }\fP
.IP
\fBcache\fP \(em Persistent filter cache file.
Defaults to "/etc/lvm/.cache".
\fBcache_dir\fP \(em Persistent filter cache file directory.
Defaults to "/etc/lvm/cache".
.IP
\fBwrite_cache_state\fP \(em Set to 0 to disable the writing out of the
persistent filter cache file when \fBlvm\fP exits.
@@ -364,9 +369,9 @@ understand how things work: to make changes you should always use
the tools as normal, or else vgcfgbackup, edit backup, vgcfgrestore.
.SH FILES
.I /etc/lvm/lvm.conf
.I /etc/lvm/.cache
.I /etc/lvm/archive
.I /etc/lvm/backup
.I /etc/lvm/cache/.cache
.I /var/lock/lvm
.SH SEE ALSO
.BR lvm (8),

View File

@@ -51,7 +51,7 @@ invalid (S)napshot, (v)irtual
.IP 2 3
Permissions: (w)riteable, (r)ead-only
.IP 3 3
Allocation policy: (c)ontiguous, (n)ormal, (a)nywhere, (i)nherited
Allocation policy: (c)ontiguous, c(l)ing, (n)ormal, (a)nywhere, (i)nherited
This is capitalised if the volume is currently locked against allocation
changes, for example during \fBpvmove\fP (8).
.IP 4 3

33
man/pvck.8 Normal file
View File

@@ -0,0 +1,33 @@
.TH PVCK 8 "LVM TOOLS" "Sistina Software UK" \" -*- nroff -*-
.SH NAME
pvck \- check physical volume metadata
.SH SYNOPSIS
.B pvck
.RB [ \-d | \-\-debug ]
.RB [ \-h | \-\-help ]
.RB [ \-v | \-\-verbose ]
.RB [ \-\-labelsector ]
.IR PhysicalVolume " [" PhysicalVolume ...]
.SH DESCRIPTION
pvck checks physical volume LVM metadata for consistency.
.SH OPTIONS
See \fBlvm\fP for common options.
.TP
.BR \-\-labelsector " sector"
By default, 4 sectors of \fBPhysicalVolume\fP are scanned for an LVM label,
starting at sector 0. This parameter allows you to specify a different
starting sector for the scan and is useful for recovery situations. For
example, suppose the partition table is corrupted or lost on /dev/sda,
but you suspect there was an LVM partition at approximately 100 MB. This
area of the disk may be scanned by using the \fB--labelsector\fP parameter
with a value of 204800 (100 * 1024 * 1024 / 512 = 204800):
.sp
.BI "pvck --labelsector 204800 /dev/sda"
.sp
Note that a script can be used with \fB--labelsector\fP to automate the
process of finding LVM labels.
.SH SEE ALSO
.BR lvm (8),
.BR pvcreate (8),
.BR pvscan (8)
.BR vgck (8)

View File

@@ -5,7 +5,7 @@ pvmove \- move physical extents
.B pvmove
[\-\-abort]
[\-\-alloc AllocationPolicy]
[\-\-background]
[\-b/\-\-background]
[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
[\-n/\-\-name LogicalVolume]
[SourcePhysicalVolume[:PE[-PE]...] [DestinationPhysicalVolume[:PE[-PE]...]...]]
@@ -73,7 +73,7 @@ type of on-disk metadata. Metadata can be converted using \fBvgconvert\fP(8).
.I \-\-abort
Abort any moves in progress.
.TP
.I \-\-background
.I \-b, \-\-background
Run the daemon in the background.
.TP
.I \-i, \-\-interval Seconds

View File

@@ -36,9 +36,24 @@ vg_free_count, max_lv, max_pv, pv_count, lv_count, snap_count, vg_seqno,
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 and (c)lustered.
at the same time.
Use \fb-o help\fP to view the full list of fields available.
.IP
The vg_attr bits are:
.RS
.IP 1 3
Permissions: (w)riteable, (r)ead-only
.IP 2 3
Resi(z)eable
.IP 3 3
E(x)ported
.IP 4 3
(p)artial
.IP 5 3
Allocation policy: (c)ontiguous, c(l)ing, (n)ormal, (a)nywhere, (i)nherited
.IP 6 3
(c)lustered
.RE
.TP
.I \-O, \-\-sort
Comma-separated ordered list of columns to sort by. Replaces the default

5619
po/lvm2.po

File diff suppressed because it is too large Load Diff

View File

@@ -43,16 +43,10 @@ start()
then
for vg in $LVM_VGS
do
if ! action "Activating VG $vg:" $VGCHANGE -ayl $vg
then
rtrn=$?
fi
action "Activating VG $vg:" $VGCHANGE -ayl $vg || rtrn=$?
done
else
if ! action "Activating VGs:" $VGCHANGE -ayl
then
rtrn=$?
fi
action "Activating VGs:" $VGCHANGE -ayl || rtrn=$?
fi
done
@@ -67,19 +61,13 @@ stop()
then
for vg in $LVM_VGS
do
if ! action "Deactivating VG $vg:" $VGCHANGE -anl $vg
then
rtrn=$?
fi
action "Deactivating VG $vg:" $VGCHANGE -anl $vg || rtrn=$?
done
else
# Hack to only deactivate clustered volumes
clustervgs=`$VGDISPLAY 2> /dev/null | awk 'BEGIN {RS="VG Name"} {if (/Clustered/) print $1;}'`
for vg in $clustervgs; do
if ! action "Deactivating VG $vg:" $VGCHANGE -anl $vg
then
rtrn=$?
fi
action "Deactivating VG $vg:" $VGCHANGE -anl $vg || rtrn=$?
done
fi

View File

@@ -25,65 +25,67 @@
. /etc/init.d/functions
VGCHANGE="/usr/sbin/vgchange"
WARN=1
start()
{
for ret in 0
do
ret=0
# TODO do we want to separate out already active groups only?
VGS=`vgs --noheadings -o name`
for vg in $VGS
do
if ! action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y $vg
then
ret=$?
fi
action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y $vg || ret=$?
done
done
return $ret
return $ret
}
stop()
{
for ret in 0
do
ret=0
# TODO do we want to separate out already active groups only?
if test "$WARN" = "1"; then
echo "Not stopping monitoring, this is a dangerous operation. Please use force-stop to override."
return 1
fi
VGS=`vgs --noheadings -o name`
for vg in $VGS
do
if ! action "Starting monitoring for VG $vg:" $VGCHANGE --monitor n $vg
then
ret=$?
fi
action "Stopping monitoring for VG $vg:" $VGCHANGE --monitor n $vg || ret=$?
done
done
return $ret
}
ret=1
result=1
# See how we were called.
case "$1" in
start)
start
ret=$?
result=$?
;;
force-stop)
WARN=0
stop
result=$?
;;
stop)
test "$runlevel" = "0" && WARN=0
test "$runlevel" = "6" && WARN=0
stop
ret=$?
result=$?
;;
restart)
WARN=0
if stop
then
start
fi
ret=$?
result=$?
;;
status)
@@ -91,8 +93,8 @@ case "$1" in
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
echo $"Usage: $0 {start|stop|restart|status|force-stop}"
;;
esac
exit $ret
exit $result

View File

@@ -147,7 +147,10 @@ myecho "Gathering /etc/lvm info..."
log "$CP -a /etc/lvm $dir/lvm 2>> $log"
myecho "Gathering /dev listing..."
log "$LS -la /dev > $dir/dev_listing 2>> $log"
log "$LS -laR /dev > $dir/dev_listing 2>> $log"
myecho "Gathering /sys/block listing..."
log "$LS -laR /sys/block > $dir/sysblock_listing"
if (( $metadata )); then
myecho "Gathering LVM metadata from Physical Volumes..."

View File

@@ -38,6 +38,7 @@ SOURCES =\
lvscan.c \
polldaemon.c \
pvchange.c \
pvck.c \
pvcreate.c \
pvdisplay.c \
pvmove.c \

View File

@@ -407,6 +407,18 @@ xx(pvresize,
physicalvolumesize_ARG, test_ARG)
xx(pvck,
"Check the consistency of physical volume(s)",
"pvck "
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
"\t[--labelsector sector] " "\n"
"\t[-v|--verbose]\n"
"\t[--version]" "\n"
"\tPhysicalVolume [PhysicalVolume...]\n",
labelsector_ARG)
xx(pvcreate,
"Initialize physical volume(s) for use by LVM",
"pvcreate " "\n"

View File

@@ -19,7 +19,7 @@
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <configure.h>
#include "configure.h"
#include "libdevmapper.h"
#include "log.h"
@@ -749,7 +749,7 @@ static int _error_device(int argc __attribute((unused)), char **argv __attribute
if (!_set_task_device(dmt, name, 0))
goto error;
if (!dm_task_add_target(dmt, 0, size, "error", ""))
if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
goto error;
if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
@@ -962,17 +962,18 @@ static int _status(int argc, char **argv, void *data)
if (data && !_switches[VERBOSE_ARG])
printf("%s: ", name);
if (target_type) {
/* Suppress encryption key */
if (!_switches[SHOWKEYS_ARG] &&
!strcmp(target_type, "crypt")) {
c = params;
while (*c && *c != ' ')
c++;
c++;
while (*c && *c != ' ')
*c++ = '0';
}
/* Suppress encryption key */
if (!_switches[SHOWKEYS_ARG] &&
cmd == DM_DEVICE_TABLE &&
!strcmp(target_type, "crypt")) {
c = params;
while (*c && *c != ' ')
c++;
if (*c)
c++;
while (*c && *c != ' ')
*c++ = '0';
}
printf("%" PRIu64 " %" PRIu64 " %s %s",
start, length, target_type, params);
}
@@ -1261,10 +1262,10 @@ static void _out_char(const unsigned c)
}
}
static void _out_string(const unsigned char *str)
static void _out_string(const char *str)
{
while (*str)
_out_char(*str++);
_out_char((unsigned char) *str++);
}
/* non-negative integers only */
@@ -1502,7 +1503,7 @@ static int _dm_name_disp(struct dm_report *rh,
struct dm_report_field *field, const void *data,
void *private __attribute((unused)))
{
const char *name = dm_task_get_name((struct dm_task *) data);
const char *name = dm_task_get_name((const struct dm_task *) data);
return dm_report_field_string(rh, field, &name);
}
@@ -1512,7 +1513,7 @@ static int _dm_uuid_disp(struct dm_report *rh,
struct dm_report_field *field,
const void *data, void *private __attribute((unused)))
{
const char *uuid = dm_task_get_uuid((struct dm_task *) data);
const char *uuid = dm_task_get_uuid((const struct dm_task *) data);
if (!uuid || !*uuid)
uuid = "";
@@ -1527,7 +1528,7 @@ static int _dm_info_status_disp(struct dm_report *rh,
{
char buf[5];
const char *s = buf;
struct dm_info *info = (struct dm_info *) data;
const struct dm_info *info = data;
buf[0] = info->live_table ? 'L' : '-';
buf[1] = info->inactive_table ? 'I' : '-';
@@ -1561,20 +1562,20 @@ static const struct dm_report_object_type _report_types[] = {
#define OFFSET_OF(strct, field) ((unsigned int) &((struct strct *)NULL)->field)
#define STR (DM_REPORT_FIELD_TYPE_STRING)
#define NUM (DM_REPORT_FIELD_TYPE_NUMBER)
#define FIELD_O(type, strct, sorttype, head, field, width, func, id, desc) {DR_ ## type, id, OFFSET_OF(strct, field), head, width, sorttype, &_ ## func ## _disp, desc},
#define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, id, 0, head, width, sorttype, &_ ## func ## _disp, desc},
#define FIELD_O(type, strct, sorttype, head, field, width, func, id, desc) {DR_ ## type, sorttype, OFFSET_OF(strct, field), width, id, head, &_ ## func ## _disp, desc},
#define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, sorttype, 0, width, id, head, &_ ## func ## _disp, desc},
static const struct dm_report_field_type _report_fields[] = {
/* *INDENT-OFF* */
FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.")
FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique identifier for mapped device (optional).")
FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "status", "Attributes.")
FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Major number.")
FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Minor number.")
FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open_count", "Number of references to open device, if requested.")
FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "target_count", "Number of segments in live table, if present.")
FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "event_nr", "Current event number.")
{0, "", 0, "", 0, 0, NULL, NULL},
FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")
FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.")
FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.")
FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.")
FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.")
FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.")
FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.")
{0, 0, 0, 0, "", "", NULL, NULL},
/* *INDENT-ON* */
};
@@ -1583,7 +1584,7 @@ FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "event_nr", "Current e
#undef FIELD_O
#undef FIELD_F
static const char *default_report_options = "name,major,minor,status,open_count,target_count,event_nr,uuid";
static const char *default_report_options = "name,major,minor,attr,open,segments,events,uuid";
static int _report_init(struct command *c)
{
@@ -1625,7 +1626,7 @@ static int _report_init(struct command *c)
if (_switches[SORT_ARG] && _string_args[SORT_ARG]) {
keys = _string_args[SORT_ARG];
buffered = 1;
if (!strcmp(c->name, "status") || !strcmp(c->name, "table")) {
if (c && (!strcmp(c->name, "status") || !strcmp(c->name, "table"))) {
err("--sort is not yet supported with status and table");
goto out;
}
@@ -1673,10 +1674,13 @@ static int _ls(int argc, char **argv, void *data)
return _process_all(argc, argv, 0, _display_name);
}
static int _help(int argc, char **argv, void *data);
/*
* Dispatch table
*/
static struct command _commands[] = {
{"help", "[-c|-C|--columns]", 0, 0, _help},
{"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
"\t [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
"\t [-u|uuid <uuid>]\n"
@@ -1710,14 +1714,18 @@ static void _usage(FILE *out)
fprintf(out, "Usage:\n\n");
fprintf(out, "dmsetup [--version] [-v|--verbose [-v|--verbose ...]]\n"
" [-r|--readonly] [--noopencount] [--nolockfs]\n\n");
" [-r|--readonly] [--noopencount] [--nolockfs]\n"
" [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>]\n"
" [--noheadings] [--separator <separator>]\n\n");
for (i = 0; _commands[i].name; i++)
fprintf(out, "\t%s %s\n", _commands[i].name, _commands[i].help);
fprintf(out, "\n<device> may be device name or -u <uuid> or "
"-j <major> -m <minor>\n");
fprintf(out, "<fields> are comma-separated. Use 'help -c' for list.\n");
fprintf(out, "Table_file contents may be supplied on stdin.\n");
fprintf(out, "Tree options are: ascii, utf, vt100; compact, inverted, notrunc;\n"
" [no]device, active, open, rw and uuid.\n\n");
" [no]device, active, open, rw and uuid.\n");
fprintf(out, "\n");
return;
}
@@ -1728,6 +1736,23 @@ static void _losetup_usage(FILE *out)
"[-o offset] [-f|loop_device] [file]\n\n");
}
static int _help(int argc __attribute((unused)),
char **argv __attribute((unused)),
void *data __attribute((unused)))
{
_usage(stderr);
if (_switches[COLS_ARG]) {
_switches[OPTIONS_ARG] = 1;
_string_args[OPTIONS_ARG] = (char *) "help";
_switches[SORT_ARG] = 0;
(void) _report_init(NULL);
}
return 1;
}
static struct command *_find_command(const char *name)
{
int i;
@@ -1743,7 +1768,7 @@ static int _process_tree_options(const char *options)
{
const char *s, *end;
struct winsize winsz;
int len;
size_t len;
/* Symbol set default */
if (!strcmp(nl_langinfo(CODESET), "UTF-8"))
@@ -1799,7 +1824,7 @@ static int _process_tree_options(const char *options)
/* Truncation doesn't work well with vt100 drawing char */
if (_tsym != &_tsym_vt100)
if (ioctl(1, TIOCGWINSZ, &winsz) >= 0 && winsz.ws_col > 3)
if (ioctl(1, (unsigned long) TIOCGWINSZ, &winsz) >= 0 && winsz.ws_col > 3)
_termwidth = winsz.ws_col - 3;
return 1;
@@ -1836,13 +1861,13 @@ static char *parse_loop_device_name(char *dev)
if (strncmp(device, DEV_PATH, strlen(DEV_PATH)))
goto error;
strncpy(buf, strrchr(device, '/') + 1, PATH_MAX);
strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX);
dm_free(device);
} else {
/* check for device number */
if (!strncmp(dev, "loop", strlen("loop")))
strncpy(buf, dev, PATH_MAX);
strncpy(buf, dev, (size_t) PATH_MAX);
else
goto error;
}
@@ -1885,8 +1910,9 @@ static int _loop_table(char *table, size_t tlen, char *file,
sectors = size >> SECTOR_SHIFT;
if (_switches[VERBOSE_ARG])
fprintf(stderr, "losetup: set loop size to %llukB (%llu sectors)\n",
sectors >> 1, sectors);
fprintf(stderr, "losetup: set loop size to %llukB "
"(%llu sectors)\n", (long long unsigned) sectors >> 1,
(long long unsigned) sectors);
#ifdef HAVE_SYS_STATVFS_H
if (fstatvfs(fd, &fsbuf))
@@ -1995,6 +2021,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv)
if (*argc != 2) {
fprintf(stderr, "%s: Too few arguments\n", base);
_losetup_usage(stderr);
dm_free(device_name);
return 0;
}
@@ -2003,13 +2030,15 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv)
fprintf(stderr, "%s: Could not parse loop file name %s\n",
base, (*argv)[1]);
_losetup_usage(stderr);
dm_free(device_name);
return 0;
}
/* FIXME Missing free */
_table = dm_malloc(LOOP_TABLE_SIZE);
if (!_loop_table(_table, LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
if (!_loop_table(_table, (size_t) LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
fprintf(stderr, "Could not build device-mapper table for %s\n", (*argv)[0]);
dm_free(device_name);
return 0;
}
_switches[TABLE_ARG]++;
@@ -2096,7 +2125,7 @@ static int _process_switches(int *argc, char ***argv)
return 1;
}
if(!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
r = _process_losetup_switches(base, argc, argv);
free(namebase);
return r;

View File

@@ -307,7 +307,7 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
if (!(log_lv = create_mirror_log(cmd, lv->vg, ah,
lp->alloc, lv->name,
(sync_percent >= 100.0) ?
1 : 0))) {
1 : 0, &lv->tags))) {
log_error("Failed to create mirror log.");
return 0;
}
@@ -385,7 +385,7 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
if (!arg_count(cmd, corelog_ARG) &&
!(log_lv = create_mirror_log(cmd, lv->vg, ah,
lp->alloc,
lv->name, 0))) {
lv->name, 0, &lv->tags))) {
log_error("Failed to create mirror log.");
return 0;
}

View File

@@ -95,7 +95,7 @@ static int _lvcreate_name_params(struct lvcreate_params *lp,
}
} else {
vg_name = skip_dev_dir(cmd, argv[0]);
vg_name = skip_dev_dir(cmd, argv[0], NULL);
if (strrchr(vg_name, '/')) {
log_error("Volume group name expected "
"(no slash)");
@@ -476,8 +476,8 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
uint64_t tmp_size;
struct volume_group *vg;
struct logical_volume *lv, *org = NULL, *log_lv = NULL;
struct list *pvh;
const char *tag;
struct list *pvh, tags;
const char *tag = NULL;
int consistent = 1;
struct alloc_handle *ah = NULL;
char lv_name_buf[128];
@@ -675,6 +675,19 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
lv_name = &lv_name_buf[0];
}
if (arg_count(cmd, addtag_ARG)) {
if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
log_error("Failed to get tag");
return 0;
}
if (!(vg->fid->fmt->features & FMT_TAGS)) {
log_error("Volume group %s does not support tags",
vg->name);
return 0;
}
}
if (lp->mirrors > 1) {
/* FIXME Calculate how many extents needed for the log */
@@ -698,9 +711,13 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
status |= MIRROR_NOTSYNCED;
}
list_init(&tags);
if (tag)
str_list_add(cmd->mem, &tags, tag);
if (!lp->corelog &&
!(log_lv = create_mirror_log(cmd, vg, ah, lp->alloc,
lv_name, lp->nosync))) {
lv_name, lp->nosync, &tags))) {
log_error("Failed to create mirror log.");
return 0;
}
@@ -725,23 +742,10 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
lv->minor);
}
if (arg_count(cmd, addtag_ARG)) {
if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
log_error("Failed to get tag");
goto error;
}
if (!(lv->vg->fid->fmt->features & FMT_TAGS)) {
log_error("Volume group %s does not support tags",
lv->vg->name);
goto error;
}
if (!str_list_add(cmd->mem, &lv->tags, tag)) {
log_error("Failed to add tag %s to %s/%s",
tag, lv->vg->name, lv->name);
goto error;
}
if (tag && !str_list_add(cmd->mem, &lv->tags, tag)) {
log_error("Failed to add tag %s to %s/%s",
tag, lv->vg->name, lv->name);
goto error;
}
if (lp->mirrors > 1) {

View File

@@ -19,3 +19,8 @@ int main(int argc, char **argv)
{
return lvm2_main(argc, argv, 1);
}
int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline)
{
return 0;
}

View File

@@ -13,9 +13,233 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tools.h"
#include "lvm2cmdline.h"
int main(int argc, char **argv)
{
return lvm2_main(argc, argv, 0);
}
#ifdef READLINE_SUPPORT
# include <readline/readline.h>
# include <readline/history.h>
# ifndef HAVE_RL_COMPLETION_MATCHES
# define rl_completion_matches(a, b) completion_matches((char *)a, b)
# endif
static struct cmdline_context *_cmdline;
/* List matching commands */
static char *_list_cmds(const char *text, int state)
{
static int i = 0;
static size_t len = 0;
/* Initialise if this is a new completion attempt */
if (!state) {
i = 0;
len = strlen(text);
}
while (i < _cmdline->num_commands)
if (!strncmp(text, _cmdline->commands[i++].name, len))
return strdup(_cmdline->commands[i - 1].name);
return NULL;
}
/* List matching arguments */
static char *_list_args(const char *text, int state)
{
static int match_no = 0;
static size_t len = 0;
static struct command *com;
/* Initialise if this is a new completion attempt */
if (!state) {
char *s = rl_line_buffer;
int j = 0;
match_no = 0;
com = NULL;
len = strlen(text);
/* Find start of first word in line buffer */
while (isspace(*s))
s++;
/* Look for word in list of commands */
for (j = 0; j < _cmdline->num_commands; j++) {
const char *p;
char *q = s;
p = _cmdline->commands[j].name;
while (*p == *q) {
p++;
q++;
}
if ((!*p) && *q == ' ') {
com = _cmdline->commands + j;
break;
}
}
if (!com)
return NULL;
}
/* Short form arguments */
if (len < 3) {
while (match_no < com->num_args) {
char s[3];
char c;
if (!(c = (_cmdline->the_args +
com->valid_args[match_no++])->short_arg))
continue;
sprintf(s, "-%c", c);
if (!strncmp(text, s, len))
return strdup(s);
}
}
/* Long form arguments */
if (match_no < com->num_args)
match_no = com->num_args;
while (match_no - com->num_args < com->num_args) {
const char *l;
l = (_cmdline->the_args +
com->valid_args[match_no++ - com->num_args])->long_arg;
if (*(l + 2) && !strncmp(text, l, len))
return strdup(l);
}
return NULL;
}
/* Custom completion function */
static char **_completion(const char *text, int start_pos, int end_pos)
{
char **match_list = NULL;
int p = 0;
while (isspace((int) *(rl_line_buffer + p)))
p++;
/* First word should be one of our commands */
if (start_pos == p)
match_list = rl_completion_matches(text, _list_cmds);
else if (*text == '-')
match_list = rl_completion_matches(text, _list_args);
/* else other args */
/* No further completion */
rl_attempted_completion_over = 1;
return match_list;
}
static int _hist_file(char *buffer, size_t size)
{
char *e = getenv("HOME");
if (dm_snprintf(buffer, size, "%s/.lvm_history", e) < 0) {
log_error("$HOME/.lvm_history: path too long");
return 0;
}
return 1;
}
static void _read_history(struct cmd_context *cmd)
{
char hist_file[PATH_MAX];
if (!_hist_file(hist_file, sizeof(hist_file)))
return;
if (read_history(hist_file))
log_very_verbose("Couldn't read history from %s.", hist_file);
stifle_history(find_config_tree_int(cmd, "shell/history_size",
DEFAULT_MAX_HISTORY));
}
static void _write_history(void)
{
char hist_file[PATH_MAX];
if (!_hist_file(hist_file, sizeof(hist_file)))
return;
if (write_history(hist_file))
log_very_verbose("Couldn't write history to %s.", hist_file);
}
int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline)
{
int argc, ret;
char *input = NULL, *args[MAX_ARGS], **argv;
rl_readline_name = "lvm";
rl_attempted_completion_function = (CPPFunction *) _completion;
_read_history(cmd);
_cmdline = cmdline;
_cmdline->interactive = 1;
while (1) {
free(input);
input = readline("lvm> ");
/* EOF */
if (!input) {
printf("\n");
break;
}
/* empty line */
if (!*input)
continue;
add_history(input);
argv = args;
if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
log_error("Too many arguments, sorry.");
continue;
}
if (!strcmp(argv[0], "lvm")) {
argv++;
argc--;
}
if (!argc)
continue;
if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
remove_history(history_length - 1);
log_error("Exiting.");
break;
}
ret = lvm_run_command(cmd, argc, argv);
if (ret == ENO_SUCH_CMD)
log_error("No such command '%s'. Try 'help'.",
argv[0]);
_write_history();
}
free(input);
return 0;
}
#endif /* READLINE_SUPPORT */

View File

@@ -18,6 +18,14 @@
struct cmd_context;
struct cmdline_context {
struct arg *the_args;
struct command *commands;
int num_commands;
int commands_size;
int interactive;
};
int lvm2_main(int argc, char **argv, unsigned is_static);
void *cmdlib_lvm2_init(unsigned is_static);
@@ -27,5 +35,6 @@ struct cmd_context *init_lvm(unsigned is_static);
void lvm_register_commands(void);
int lvm_split(char *str, int *argc, char **argv, int max);
int lvm_run_command(struct cmd_context *cmd, int argc, char **argv);
int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline);
#endif

View File

@@ -41,30 +41,16 @@ extern char *optarg;
# define OPTIND_INIT 1
#endif
#ifdef READLINE_SUPPORT
# include <readline/readline.h>
# include <readline/history.h>
# ifndef HAVE_RL_COMPLETION_MATCHES
# define rl_completion_matches(a, b) completion_matches((char *)a, b)
# endif
#endif
/*
* Exported table of valid switches
* Table of valid switches
*/
struct arg the_args[ARG_COUNT + 1] = {
static struct arg _the_args[ARG_COUNT + 1] = {
#define arg(a, b, c, d) {b, "", "--" c, d, 0, NULL, 0, 0, INT64_C(0), UINT64_C(0), SIGN_NONE, PERCENT_NONE, NULL},
#include "args.h"
#undef arg
};
static int _array_size;
static int _num_commands;
static struct command *_commands;
static int _interactive;
static struct cmdline_context _cmdline;
int yes_no_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
{
@@ -412,21 +398,21 @@ char yes_no_prompt(const char *prompt, ...)
static void __alloc(int size)
{
if (!(_commands = dm_realloc(_commands, sizeof(*_commands) * size))) {
if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) {
log_fatal("Couldn't allocate memory.");
exit(ECMD_FAILED);
}
_array_size = size;
_cmdline.commands_size = size;
}
static void _alloc_command(void)
{
if (!_array_size)
if (!_cmdline.commands_size)
__alloc(32);
if (_array_size <= _num_commands)
__alloc(2 * _array_size);
if (_cmdline.commands_size <= _cmdline.num_commands)
__alloc(2 * _cmdline.commands_size);
}
static void _create_new_command(const char *name, command_fn command,
@@ -437,7 +423,7 @@ static void _create_new_command(const char *name, command_fn command,
_alloc_command();
nc = _commands + _num_commands++;
nc = _cmdline.commands + _cmdline.num_commands++;
nc->name = name;
nc->desc = desc;
@@ -495,17 +481,17 @@ static struct command *_find_command(const char *name)
namebase = strdup(name);
base = basename(namebase);
for (i = 0; i < _num_commands; i++) {
if (!strcmp(base, _commands[i].name))
for (i = 0; i < _cmdline.num_commands; i++) {
if (!strcmp(base, _cmdline.commands[i].name))
break;
}
free(namebase);
if (i >= _num_commands)
if (i >= _cmdline.num_commands)
return 0;
return _commands + i;
return _cmdline.commands + i;
}
static void _usage(const char *name)
@@ -527,7 +513,7 @@ static void _usage(const char *name)
*/
static void _add_getopt_arg(int arg, char **ptr, struct option **o)
{
struct arg *a = the_args + arg;
struct arg *a = _cmdline.the_args + arg;
if (a->short_arg) {
*(*ptr)++ = a->short_arg;
@@ -556,12 +542,12 @@ static struct arg *_find_arg(struct command *com, int opt)
for (i = 0; i < com->num_args; i++) {
arg = com->valid_args[i];
a = the_args + arg;
a = _cmdline.the_args + arg;
/*
* opt should equal either the
* short arg, or the index into
* 'the_args'.
* the_args.
*/
if ((a->short_arg && (opt == a->short_arg)) ||
(!a->short_arg && (opt == arg)))
@@ -580,7 +566,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
struct arg *a;
for (i = 0; i < ARG_COUNT; i++) {
a = the_args + i;
a = _cmdline.the_args + i;
/* zero the count and arg */
a->count = 0;
@@ -651,15 +637,15 @@ static int _merge_synonym(struct cmd_context *cmd, int oldarg, int newarg)
if (arg_count(cmd, oldarg) && arg_count(cmd, newarg)) {
log_error("%s and %s are synonyms. Please only supply one.",
the_args[oldarg].long_arg, the_args[newarg].long_arg);
_cmdline.the_args[oldarg].long_arg, _cmdline.the_args[newarg].long_arg);
return 0;
}
if (!arg_count(cmd, oldarg))
return 1;
old = the_args + oldarg;
new = the_args + newarg;
old = _cmdline.the_args + oldarg;
new = _cmdline.the_args + newarg;
new->count = old->count;
new->value = old->value;
@@ -782,8 +768,8 @@ static void _display_help(void)
log_error("Use 'lvm help <command>' for more information");
log_error(" ");
for (i = 0; i < _num_commands; i++) {
struct command *com = _commands + i;
for (i = 0; i < _cmdline.num_commands; i++) {
struct command *com = _cmdline.commands + i;
log_error("%-16.16s%s", com->name, com->desc);
}
@@ -841,30 +827,30 @@ static char *_copy_command_line(struct cmd_context *cmd, int argc, char **argv)
* description for backups.
*/
if (!dm_pool_begin_object(cmd->mem, 128))
goto bad;
goto_bad;
for (i = 0; i < argc; i++) {
space = strchr(argv[i], ' ') ? 1 : 0;
if (space && !dm_pool_grow_object(cmd->mem, "'", 1))
goto bad;
goto_bad;
if (!dm_pool_grow_object(cmd->mem, argv[i], strlen(argv[i])))
goto bad;
goto_bad;
if (space && !dm_pool_grow_object(cmd->mem, "'", 1))
goto bad;
goto_bad;
if (i < (argc - 1))
if (!dm_pool_grow_object(cmd->mem, " ", 1))
goto bad;
goto_bad;
}
/*
* Terminate.
*/
if (!dm_pool_grow_object(cmd->mem, "\0", 1))
goto bad;
goto_bad;
return dm_pool_end_object(cmd->mem);
@@ -959,7 +945,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
*/
dm_pool_empty(cmd->mem);
if (ret == EINVALID_CMD_LINE && !_interactive)
if (ret == EINVALID_CMD_LINE && !_cmdline.interactive)
_usage(cmd->command->name);
log_debug("Completed: %s", cmd->cmd_line);
@@ -1030,7 +1016,9 @@ struct cmd_context *init_lvm(unsigned is_static)
{
struct cmd_context *cmd;
if (!(cmd = create_toolcontext(&the_args[0], is_static, 0))) {
_cmdline.the_args = &_the_args[0];
if (!(cmd = create_toolcontext(_cmdline.the_args, is_static, 0))) {
stack;
return NULL;
}
@@ -1046,10 +1034,10 @@ static void _fin_commands(void)
{
int i;
for (i = 0; i < _num_commands; i++)
dm_free(_commands[i].valid_args);
for (i = 0; i < _cmdline.num_commands; i++)
dm_free(_cmdline.commands[i].valid_args);
dm_free(_commands);
dm_free(_cmdline.commands);
}
void lvm_fin(struct cmd_context *cmd)
@@ -1106,218 +1094,6 @@ static int _run_script(struct cmd_context *cmd, int argc, char **argv)
return ret;
}
#ifdef READLINE_SUPPORT
/* List matching commands */
static char *_list_cmds(const char *text, int state)
{
static int i = 0;
static size_t len = 0;
/* Initialise if this is a new completion attempt */
if (!state) {
i = 0;
len = strlen(text);
}
while (i < _num_commands)
if (!strncmp(text, _commands[i++].name, len))
return strdup(_commands[i - 1].name);
return NULL;
}
/* List matching arguments */
static char *_list_args(const char *text, int state)
{
static int match_no = 0;
static size_t len = 0;
static struct command *com;
/* Initialise if this is a new completion attempt */
if (!state) {
char *s = rl_line_buffer;
int j = 0;
match_no = 0;
com = NULL;
len = strlen(text);
/* Find start of first word in line buffer */
while (isspace(*s))
s++;
/* Look for word in list of commands */
for (j = 0; j < _num_commands; j++) {
const char *p;
char *q = s;
p = _commands[j].name;
while (*p == *q) {
p++;
q++;
}
if ((!*p) && *q == ' ') {
com = _commands + j;
break;
}
}
if (!com)
return NULL;
}
/* Short form arguments */
if (len < 3) {
while (match_no < com->num_args) {
char s[3];
char c;
if (!(c = (the_args +
com->valid_args[match_no++])->short_arg))
continue;
sprintf(s, "-%c", c);
if (!strncmp(text, s, len))
return strdup(s);
}
}
/* Long form arguments */
if (match_no < com->num_args)
match_no = com->num_args;
while (match_no - com->num_args < com->num_args) {
const char *l;
l = (the_args +
com->valid_args[match_no++ - com->num_args])->long_arg;
if (*(l + 2) && !strncmp(text, l, len))
return strdup(l);
}
return NULL;
}
/* Custom completion function */
static char **_completion(const char *text, int start_pos, int end_pos)
{
char **match_list = NULL;
int p = 0;
while (isspace((int) *(rl_line_buffer + p)))
p++;
/* First word should be one of our commands */
if (start_pos == p)
match_list = rl_completion_matches(text, _list_cmds);
else if (*text == '-')
match_list = rl_completion_matches(text, _list_args);
/* else other args */
/* No further completion */
rl_attempted_completion_over = 1;
return match_list;
}
static int _hist_file(char *buffer, size_t size)
{
char *e = getenv("HOME");
if (dm_snprintf(buffer, size, "%s/.lvm_history", e) < 0) {
log_error("$HOME/.lvm_history: path too long");
return 0;
}
return 1;
}
static void _read_history(struct cmd_context *cmd)
{
char hist_file[PATH_MAX];
if (!_hist_file(hist_file, sizeof(hist_file)))
return;
if (read_history(hist_file))
log_very_verbose("Couldn't read history from %s.", hist_file);
stifle_history(find_config_tree_int(cmd, "shell/history_size",
DEFAULT_MAX_HISTORY));
}
static void _write_history(void)
{
char hist_file[PATH_MAX];
if (!_hist_file(hist_file, sizeof(hist_file)))
return;
if (write_history(hist_file))
log_very_verbose("Couldn't write history to %s.", hist_file);
}
static int _shell(struct cmd_context *cmd)
{
int argc, ret;
char *input = NULL, *args[MAX_ARGS], **argv;
rl_readline_name = "lvm";
rl_attempted_completion_function = (CPPFunction *) _completion;
_read_history(cmd);
_interactive = 1;
while (1) {
free(input);
input = readline("lvm> ");
/* EOF */
if (!input) {
printf("\n");
break;
}
/* empty line */
if (!*input)
continue;
add_history(input);
argv = args;
if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
log_error("Too many arguments, sorry.");
continue;
}
if (!strcmp(argv[0], "lvm")) {
argv++;
argc--;
}
if (!argc)
continue;
if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
remove_history(history_length - 1);
log_error("Exiting.");
break;
}
ret = lvm_run_command(cmd, argc, argv);
if (ret == ENO_SUCH_CMD)
log_error("No such command '%s'. Try 'help'.",
argv[0]);
_write_history();
}
free(input);
return 0;
}
#endif
/*
* Determine whether we should fall back and exec the equivalent LVM1 tool
*/
@@ -1403,7 +1179,7 @@ int lvm2_main(int argc, char **argv, unsigned is_static)
}
#ifdef READLINE_SUPPORT
if (!alias && argc == 1) {
ret = _shell(cmd);
ret = lvm_shell(cmd, &_cmdline);
goto out;
}
#endif

View File

@@ -112,7 +112,7 @@ int lvmdiskscan(struct cmd_context *cmd, int argc __attribute((unused)),
/* Do scan */
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
/* Try if it is a PV first */
if ((label_read(dev, &label))) {
if ((label_read(dev, &label, UINT64_C(0)))) {
if (!dev_get_size(dev, &size)) {
log_error("Couldn't get size of \"%s\"",
dev_name(dev));

View File

@@ -29,7 +29,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
struct lv_list *lvl;
if (argc == 3) {
vg_name = skip_dev_dir(cmd, argv[0]);
vg_name = skip_dev_dir(cmd, argv[0], NULL);
lv_name_old = argv[1];
lv_name_new = argv[2];
if (strchr(lv_name_old, '/') &&

40
tools/pvck.c Normal file
View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tools.h"
int pvck(struct cmd_context *cmd, int argc, char **argv)
{
int i;
/* FIXME: validate cmdline options */
/* FIXME: what does the cmdline look like? */
/*
* Use what's on the cmdline directly, and avoid calling into
* some of the other infrastructure functions, so as to avoid
* hitting some of the lvmcache behavior, scanning other devices,
* etc.
*/
for (i = 0; i < argc; i++) {
/* FIXME: warning and/or check if in use? */
log_verbose("Scanning %s", argv[i]);
pv_analyze(cmd, argv[i],
arg_int64_value(cmd, labelsector_ARG,
UINT64_C(0)));
}
return ECMD_PROCESSED;
}

View File

@@ -27,7 +27,7 @@ static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
if (!strchr(arg, '/'))
return arg;
lvname = skip_dev_dir(cmd, arg);
lvname = skip_dev_dir(cmd, arg, NULL);
while (*lvname == '/')
lvname++;
if (!strchr(lvname, '/')) {

View File

@@ -138,6 +138,30 @@ out:
return ret;
}
static int _pvs_in_vg(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg, int consistent,
void *handle)
{
if (!vg) {
log_error("Volume group %s not found", vg_name);
return ECMD_FAILED;
}
return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvs_single);
}
static int _pvsegs_in_vg(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg, int consistent,
void *handle)
{
if (!vg) {
log_error("Volume group %s not found", vg_name);
return ECMD_FAILED;
}
return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvsegs_single);
}
static int _report(struct cmd_context *cmd, int argc, char **argv,
report_type_t report_type)
{
@@ -146,8 +170,8 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
char *str;
const char *keys = NULL, *options = NULL, *separator;
int r = ECMD_PROCESSED;
int aligned, buffered, headings;
unsigned args_are_pvs;
aligned = find_config_tree_int(cmd, "report/aligned",
DEFAULT_REP_ALIGNED);
@@ -158,6 +182,8 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
separator = find_config_tree_str(cmd, "report/separator",
DEFAULT_REP_SEPARATOR);
args_are_pvs = (report_type == PVS || report_type == PVSEGS) ? 1 : 0;
switch (report_type) {
case LVS:
keys = find_config_tree_str(cmd, "report/lvs_sort",
@@ -260,7 +286,7 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
if (!(report_handle = report_init(cmd, options, keys, &report_type,
separator, aligned, buffered,
headings)))
return 0;
return_0;
/* Ensure options selected are compatible */
if (report_type & SEGS)
@@ -269,6 +295,7 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
report_type |= PVS;
if ((report_type & LVS) && (report_type & PVS)) {
log_error("Can't report LV and PV fields at the same time");
dm_report_free(report_handle);
return 0;
}
@@ -292,16 +319,24 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
report_handle, &_vgs_single);
break;
case PVS:
r = process_each_pv(cmd, argc, argv, NULL, report_handle,
&_pvs_single);
if (args_are_pvs)
r = process_each_pv(cmd, argc, argv, NULL,
report_handle, &_pvs_single);
else
r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
report_handle, &_pvs_in_vg);
break;
case SEGS:
r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle,
&_lvsegs_single);
break;
case PVSEGS:
r = process_each_pv(cmd, argc, argv, NULL, report_handle,
&_pvsegs_single);
if (args_are_pvs)
r = process_each_pv(cmd, argc, argv, NULL,
report_handle, &_pvsegs_single);
else
r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
report_handle, &_pvsegs_in_vg);
break;
}

View File

@@ -88,21 +88,53 @@ const char *command_name(struct cmd_context *cmd)
/*
* Strip dev_dir if present
*/
char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name)
char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
unsigned *dev_dir_found)
{
/* FIXME Do this properly */
const char *dmdir = dm_dir();
size_t dmdir_len = strlen(dmdir), vglv_sz;
char *vgname, *lvname, *layer, *vglv;
/* FIXME Do this properly */
if (*vg_name == '/') {
while (*vg_name == '/')
vg_name++;
vg_name--;
}
/* Reformat string if /dev/mapper found */
if (!strncmp(vg_name, dmdir, dmdir_len) && vg_name[dmdir_len] == '/') {
if (dev_dir_found)
*dev_dir_found = 1;
vg_name += dmdir_len;
while (*vg_name == '/')
vg_name++;
if (!dm_split_lvm_name(cmd->mem, vg_name, &vgname, &lvname, &layer) ||
*layer) {
log_error("skip_dev_dir: Couldn't split up device name %s",
vg_name);
return (char *) vg_name;
}
vglv_sz = strlen(vgname) + strlen(lvname) + 2;
if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
dm_snprintf(vglv, vglv_sz, "%s%s%s", vgname,
*lvname ? "/" : "",
lvname) < 0) {
log_error("vg/lv string alloc failed");
return (char *) vg_name;
}
return vglv;
}
if (!strncmp(vg_name, cmd->dev_dir, strlen(cmd->dev_dir))) {
if (dev_dir_found)
*dev_dir_found = 1;
vg_name += strlen(cmd->dev_dir);
while (*vg_name == '/')
vg_name++;
}
} else if (dev_dir_found)
*dev_dir_found = 0;
return (char *) vg_name;
}
@@ -222,7 +254,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
for (; opt < argc; opt++) {
const char *lv_name = argv[opt];
char *vgname_def;
int dev_dir_found = 0;
unsigned dev_dir_found = 0;
/* Do we have a tag or vgname or lvname? */
vgname = lv_name;
@@ -243,18 +275,8 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
}
/* FIXME Jumbled parsing */
if (*vgname == '/') {
while (*vgname == '/')
vgname++;
vgname--;
}
if (!strncmp(vgname, cmd->dev_dir,
strlen(cmd->dev_dir))) {
vgname += strlen(cmd->dev_dir);
dev_dir_found = 1;
while (*vgname == '/')
vgname++;
}
vgname = skip_dev_dir(cmd, vgname, &dev_dir_found);
if (*vgname == '/') {
log_error("\"%s\": Invalid path for Logical "
"Volume", argv[opt]);
@@ -528,7 +550,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
continue;
}
vg_name = skip_dev_dir(cmd, vg_name);
vg_name = skip_dev_dir(cmd, vg_name, NULL);
if (strchr(vg_name, '/')) {
log_error("Invalid volume group name: %s",
vg_name);
@@ -830,7 +852,7 @@ char *default_vgname(struct cmd_context *cmd)
if (!vg_path)
return 0;
vg_path = skip_dev_dir(cmd, vg_path);
vg_path = skip_dev_dir(cmd, vg_path, NULL);
if (strchr(vg_path, '/')) {
log_error("Environment Volume Group in LVM_VG_NAME invalid: "
@@ -1288,11 +1310,13 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
struct alloc_handle *ah,
alloc_policy_t alloc,
const char *lv_name,
int in_sync)
int in_sync,
struct list *tags)
{
struct logical_volume *log_lv;
char *log_name;
size_t len;
struct str_list *sl;
len = strlen(lv_name) + 32;
if (!(log_name = alloca(len)) ||
@@ -1314,6 +1338,13 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
goto error;
}
/* Temporary tag mirror log */
list_iterate_items(sl, tags)
if (!str_list_add(cmd->mem, &log_lv->tags, sl->str)) {
log_error("Aborting. Unable to tag mirror log.");
goto error;
}
/* store mirror log on disk(s) */
if (!vg_write(vg)) {
stack;
@@ -1339,6 +1370,11 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
goto error;
}
list_iterate_items(sl, tags)
if (!str_list_del(&log_lv->tags, sl->str))
log_error("Failed to remove tag %s from mirror log.",
sl->str);
if (activation() && !set_lv(cmd, log_lv, log_lv->size,
in_sync ? -1 : 0)) {
log_error("Aborting. Failed to wipe mirror log. "

View File

@@ -76,7 +76,8 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
char *default_vgname(struct cmd_context *cmd);
const char *extract_vgname(struct cmd_context *cmd, const char *lv_name);
char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name);
char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
unsigned *dev_dir_found);
/*
* Builds a list of pv's from the names in argv. Used in
@@ -99,7 +100,8 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
struct alloc_handle *ah,
alloc_policy_t alloc,
const char *lv_name,
int in_sync);
int in_sync,
struct list *tags);
int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
uint64_t sectors, int value);

Some files were not shown because too many files have changed in this diff Show More