mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-27 00:23:49 +03:00
Compare commits
33 Commits
dm_v1_02_0
...
dm_v1_02_0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3feba82ccc | ||
|
|
db924da231 | ||
|
|
fc55ae7e6d | ||
|
|
86e757a6ad | ||
|
|
4790715cd3 | ||
|
|
e7e9c60042 | ||
|
|
1c3bc52cc4 | ||
|
|
5227dff0e1 | ||
|
|
33f0b5b7c2 | ||
|
|
0a02968303 | ||
|
|
f7bf658c07 | ||
|
|
8d16a0abad | ||
|
|
c974b97ca3 | ||
|
|
b8025bfebd | ||
|
|
30323b253f | ||
|
|
535c3ede96 | ||
|
|
89fed8ca33 | ||
|
|
f43c77aaed | ||
|
|
96c676b371 | ||
|
|
113047e1a2 | ||
|
|
abed57cb53 | ||
|
|
c01a800a6b | ||
|
|
d648832a2d | ||
|
|
f06833fbd2 | ||
|
|
c561addc94 | ||
|
|
702f5f1f4c | ||
|
|
1273f179e8 | ||
|
|
5d02f60bde | ||
|
|
4cf7a108e8 | ||
|
|
42635c3938 | ||
|
|
ed43dc842b | ||
|
|
49d4db6cd2 | ||
|
|
ea80ab2cae |
22
WHATS_NEW
22
WHATS_NEW
@@ -1,3 +1,25 @@
|
||||
Version 2.02.03 - 14th April 2006
|
||||
=================================
|
||||
vgrename accepts vgid and exported VG.
|
||||
Add --partial to pvs.
|
||||
When choosing between identically-named VGs, also consider creation_host.
|
||||
Provide total log suppression with 2.
|
||||
Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
|
||||
Add vgid to struct physical_volume and pass with vg_name to some functions.
|
||||
If two or more VGs are found with the same name, use one that is not exported.
|
||||
Whenever vgname is captured, also capture vgid and whether exported.
|
||||
Remove an incorrect unlock_vg() from process_each_lv().
|
||||
Update extent size information in vgchange and vgcreate man pages.
|
||||
Introduce origin_from_cow() and lv_is_visible().
|
||||
pvremove without -f now fails if there's no PV label.
|
||||
Support lvconvert -s.
|
||||
Suppress locking library load failure message if --ignorelockingfailure.
|
||||
Propagate partial mode around cluster.
|
||||
Fix archive file expiration.
|
||||
Fix dmeventd build.
|
||||
clvmd now uses libcman rather than cman ioctls.
|
||||
clvmd will allow new cman to shutdown on request.
|
||||
|
||||
Version 2.02.02 - 7th February 2006
|
||||
===================================
|
||||
Add %.so: %.a make template rule.
|
||||
|
||||
10
WHATS_NEW_DM
10
WHATS_NEW_DM
@@ -1,3 +1,13 @@
|
||||
Version 1.02.04 - 14 Apr 2006
|
||||
=============================
|
||||
Bring dmsetup man page up-to-date.
|
||||
Use name-based device refs if kernel doesn't support device number refs.
|
||||
Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
|
||||
If _create_and_load_v4 fails part way through, revert the creation.
|
||||
dmeventd thread/fifo fixes.
|
||||
Add file & line to dm_strdup_aux().
|
||||
Add setgeometry.
|
||||
|
||||
Version 1.02.03 - 7 Feb 2006
|
||||
============================
|
||||
Add exported functions to set uid, gid and mode.
|
||||
|
||||
@@ -46,17 +46,17 @@ endif
|
||||
|
||||
ifeq ("$(CMAN)", "yes")
|
||||
SOURCES += clvmd-cman.c
|
||||
LMLIBS += -ldlm
|
||||
LMLIBS += -ldlm -lcman
|
||||
CFLAGS += -DUSE_CMAN
|
||||
endif
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
LVMLIBS = -llvm
|
||||
LVMLIBS = -llvm -lpthread
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
LVMLIBS += -ldevmapper-event -lpthread
|
||||
LVMLIBS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
ifeq ("@DEVMAPPER@", "yes")
|
||||
|
||||
@@ -46,19 +46,23 @@
|
||||
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
static int cluster_sock;
|
||||
static int num_nodes;
|
||||
static struct cl_cluster_node *nodes = NULL;
|
||||
static struct cman_node *nodes = NULL;
|
||||
static struct cman_node this_node;
|
||||
static int count_nodes; /* size of allocated nodes array */
|
||||
static int max_updown_nodes = 50; /* Current size of the allocated array */
|
||||
/* Node up/down status, indexed by nodeid */
|
||||
static int *node_updown = NULL;
|
||||
static dlm_lshandle_t *lockspace;
|
||||
static cman_handle_t c_handle;
|
||||
|
||||
static void count_clvmds_running(void);
|
||||
static void get_members(void);
|
||||
static int nodeid_from_csid(char *csid);
|
||||
static int name_from_nodeid(int nodeid, char *name);
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
|
||||
static void data_callback(cman_handle_t handle, void *private,
|
||||
char *buf, int len, uint8_t port, int nodeid);
|
||||
|
||||
struct lock_wait {
|
||||
pthread_cond_t cond;
|
||||
@@ -68,30 +72,23 @@ struct lock_wait {
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
struct sockaddr_cl saddr;
|
||||
int port = CLUSTER_PORT_CLVMD;
|
||||
|
||||
/* Open the cluster communication socket */
|
||||
cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT);
|
||||
if (cluster_sock == -1) {
|
||||
/* Don't print an error here because we could be just probing for CMAN */
|
||||
c_handle = cman_init(NULL);
|
||||
if (!c_handle) {
|
||||
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
|
||||
return -1;
|
||||
}
|
||||
/* Set Close-on-exec */
|
||||
fcntl(cluster_sock, F_SETFD, 1);
|
||||
|
||||
/* Bind to our port number on the cluster.
|
||||
Writes to this will block if the cluster loses quorum */
|
||||
saddr.scl_family = AF_CLUSTER;
|
||||
saddr.scl_port = port;
|
||||
|
||||
if (bind
|
||||
(cluster_sock, (struct sockaddr *) &saddr,
|
||||
sizeof(struct sockaddr_cl))) {
|
||||
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
|
||||
syslog(LOG_ERR, "Can't bind cluster socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cman_start_notification(c_handle, event_callback)) {
|
||||
syslog(LOG_ERR, "Can't start cluster event listening");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the cluster members list */
|
||||
get_members();
|
||||
count_clvmds_running();
|
||||
@@ -114,63 +111,46 @@ static void _cluster_init_completed(void)
|
||||
|
||||
static int _get_main_cluster_fd()
|
||||
{
|
||||
return cluster_sock;
|
||||
return cman_get_fd(c_handle);
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
return num_nodes;
|
||||
int i;
|
||||
int nnodes = 0;
|
||||
|
||||
/* return number of ACTIVE nodes */
|
||||
for (i=0; i<num_nodes; i++) {
|
||||
if (nodes[i].cn_member)
|
||||
nnodes++;
|
||||
}
|
||||
return nnodes;
|
||||
}
|
||||
|
||||
/* send_message with the fd check removed */
|
||||
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct msghdr msg;
|
||||
struct sockaddr_cl saddr;
|
||||
int len = 0;
|
||||
int nodeid = 0;
|
||||
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_flags = 0;
|
||||
iov[0].iov_len = msglen;
|
||||
iov[0].iov_base = buf;
|
||||
if (csid)
|
||||
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
|
||||
saddr.scl_family = AF_CLUSTER;
|
||||
saddr.scl_port = CLUSTER_PORT_CLVMD;
|
||||
if (csid) {
|
||||
msg.msg_name = &saddr;
|
||||
msg.msg_namelen = sizeof(saddr);
|
||||
memcpy(&saddr.scl_nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
} else { /* Cluster broadcast */
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
}
|
||||
|
||||
do {
|
||||
len = sendmsg(cluster_sock, &msg, 0);
|
||||
if (len < 0 && errno != EAGAIN)
|
||||
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
|
||||
{
|
||||
log_error(errtext);
|
||||
|
||||
} while (len == -1 && errno == EAGAIN);
|
||||
return len;
|
||||
}
|
||||
return msglen;
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
int i;
|
||||
memset(csid, 0, CMAN_MAX_CSID_LEN);
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (nodes[i].us)
|
||||
memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
|
||||
if (this_node.cn_nodeid == 0) {
|
||||
cman_get_node(c_handle, 0, &this_node);
|
||||
}
|
||||
memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
/* Call a callback routine for each node that known (down mean not running a clvmd) */
|
||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
|
||||
static int _cluster_do_node_callback(struct local_client *client,
|
||||
void (*callback) (struct local_client *, char *,
|
||||
int))
|
||||
@@ -179,8 +159,8 @@ static int _cluster_do_node_callback(struct local_client *client,
|
||||
int somedown = 0;
|
||||
|
||||
for (i = 0; i < _get_num_nodes(); i++) {
|
||||
callback(client, (char *)&nodes[i].node_id, node_updown[nodes[i].node_id]);
|
||||
if (!node_updown[nodes[i].node_id])
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
|
||||
if (!node_updown[nodes[i].cn_nodeid])
|
||||
somedown = -1;
|
||||
}
|
||||
return somedown;
|
||||
@@ -188,78 +168,63 @@ static int _cluster_do_node_callback(struct local_client *client,
|
||||
|
||||
/* Process OOB message from the cluster socket,
|
||||
this currently just means that a node has stopped listening on our port */
|
||||
static void process_oob_msg(char *buf, int len, int nodeid)
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
|
||||
{
|
||||
char namebuf[256];
|
||||
switch (buf[0]) {
|
||||
case CLUSTER_OOB_MSG_PORTCLOSED:
|
||||
name_from_nodeid(nodeid, namebuf);
|
||||
log_notice("clvmd on node %s has died\n", namebuf);
|
||||
DEBUGLOG("Got OOB message, removing node %s\n", namebuf);
|
||||
char namebuf[MAX_CLUSTER_NAME_LEN];
|
||||
|
||||
node_updown[nodeid] = 0;
|
||||
switch (reason) {
|
||||
case CMAN_REASON_PORTCLOSED:
|
||||
name_from_nodeid(arg, namebuf);
|
||||
log_notice("clvmd on node %s has died\n", namebuf);
|
||||
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
|
||||
|
||||
node_updown[arg] = 0;
|
||||
break;
|
||||
|
||||
case CLUSTER_OOB_MSG_STATECHANGE:
|
||||
DEBUGLOG("Got OOB message, Cluster state change\n");
|
||||
case CMAN_REASON_STATECHANGE:
|
||||
DEBUGLOG("Got state change message, re-reading members list\n");
|
||||
get_members();
|
||||
break;
|
||||
|
||||
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
|
||||
case CMAN_REASON_PORTOPENED:
|
||||
/* Ignore this, wait for startup message from clvmd itself */
|
||||
break;
|
||||
|
||||
case CMAN_REASON_TRY_SHUTDOWN:
|
||||
DEBUGLOG("Got try shutdown, sending OK\n");
|
||||
cman_replyto_shutdown(c_handle, 1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* ERROR */
|
||||
DEBUGLOG("Got unknown OOB message: %d\n", buf[0]);
|
||||
DEBUGLOG("Got unknown event callback message: %d\n", reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
|
||||
static struct local_client *cman_client;
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct msghdr msg;
|
||||
struct sockaddr_cl saddr;
|
||||
|
||||
/* Save this for data_callback */
|
||||
cman_client = fd;
|
||||
|
||||
/* We never return a new client */
|
||||
*new_client = NULL;
|
||||
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_name = &saddr;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_namelen = sizeof(saddr);
|
||||
iov[0].iov_len = len;
|
||||
iov[0].iov_base = buf;
|
||||
return cman_dispatch(c_handle, 0);
|
||||
}
|
||||
|
||||
len = recvmsg(cluster_sock, &msg, MSG_OOB | O_NONBLOCK);
|
||||
if (len < 0 && errno == EAGAIN)
|
||||
return len;
|
||||
|
||||
DEBUGLOG("Read on cluster socket, len = %d\n", len);
|
||||
|
||||
/* A real error */
|
||||
if (len < 0) {
|
||||
log_error("read error on cluster socket: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF - we have left the cluster */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* Is it OOB? probably a node gone down */
|
||||
if (msg.msg_flags & MSG_OOB) {
|
||||
process_oob_msg(iov[0].iov_base, len, saddr.scl_nodeid);
|
||||
|
||||
/* Tell the upper layer to ignore this message */
|
||||
len = -1;
|
||||
errno = EAGAIN;
|
||||
}
|
||||
else {
|
||||
memcpy(csid, &saddr.scl_nodeid, sizeof(saddr.scl_nodeid));
|
||||
/* Send it back to clvmd */
|
||||
process_message(client, buf, len, csid);
|
||||
}
|
||||
return len;
|
||||
static void data_callback(cman_handle_t handle, void *private,
|
||||
char *buf, int len, uint8_t port, int nodeid)
|
||||
{
|
||||
/* Ignore looped back messages */
|
||||
if (nodeid == this_node.cn_nodeid)
|
||||
return;
|
||||
process_message(cman_client, buf, len, (char *)&nodeid);
|
||||
}
|
||||
|
||||
static void _add_up_node(char *csid)
|
||||
@@ -290,19 +255,15 @@ static void _cluster_closedown()
|
||||
{
|
||||
unlock_all();
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
close(cluster_sock);
|
||||
cman_finish(c_handle);
|
||||
}
|
||||
|
||||
static int is_listening(int nodeid)
|
||||
{
|
||||
struct cl_listen_request rq;
|
||||
int status;
|
||||
|
||||
rq.port = CLUSTER_PORT_CLVMD;
|
||||
rq.nodeid = nodeid;
|
||||
|
||||
do {
|
||||
status = ioctl(cluster_sock, SIOCCLUSTER_ISLISTENING, &rq);
|
||||
status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
|
||||
if (status < 0 && errno == EBUSY) { /* Don't busywait */
|
||||
sleep(1);
|
||||
errno = EBUSY; /* In case sleep trashes it */
|
||||
@@ -320,19 +281,22 @@ static void count_clvmds_running(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
node_updown[nodes[i].node_id] = is_listening(nodes[i].node_id);
|
||||
node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a list of active cluster members */
|
||||
static void get_members()
|
||||
{
|
||||
struct cl_cluster_nodelist nodelist;
|
||||
int retnodes;
|
||||
int status;
|
||||
|
||||
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
|
||||
num_nodes = cman_get_node_count(c_handle);
|
||||
if (num_nodes == -1) {
|
||||
log_error("Unable to get node count");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not enough room for new nodes list ? */
|
||||
if (num_nodes > count_nodes && nodes) {
|
||||
free(nodes);
|
||||
@@ -341,28 +305,19 @@ static void get_members()
|
||||
|
||||
if (nodes == NULL) {
|
||||
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||
nodes = malloc(count_nodes * sizeof(struct cl_cluster_node));
|
||||
nodes = malloc(count_nodes * sizeof(struct cman_node));
|
||||
if (!nodes) {
|
||||
log_error("Unable to allocate nodes array\n");
|
||||
exit(5);
|
||||
}
|
||||
}
|
||||
nodelist.max_members = count_nodes;
|
||||
nodelist.nodes = nodes;
|
||||
|
||||
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
|
||||
if (num_nodes <= 0) {
|
||||
status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
|
||||
if (status < 0) {
|
||||
log_error("Unable to get node details");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
/* Sanity check struct */
|
||||
if (nodes[0].size != sizeof(struct cl_cluster_node)) {
|
||||
log_error
|
||||
("sizeof(cl_cluster_node) does not match size returned from the kernel: aborting\n");
|
||||
exit(10);
|
||||
}
|
||||
|
||||
if (node_updown == NULL) {
|
||||
node_updown =
|
||||
(int *) malloc(sizeof(int) *
|
||||
@@ -371,7 +326,6 @@ static void get_members()
|
||||
sizeof(int) * max(num_nodes, max_updown_nodes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a node name to a CSID */
|
||||
static int _csid_from_name(char *csid, char *name)
|
||||
@@ -379,8 +333,8 @@ static int _csid_from_name(char *csid, char *name)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (strcmp(name, nodes[i].name) == 0) {
|
||||
memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
|
||||
if (strcmp(name, nodes[i].cn_name) == 0) {
|
||||
memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -393,8 +347,8 @@ static int _name_from_csid(char *csid, char *name)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (memcmp(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN) == 0) {
|
||||
strcpy(name, nodes[i].name);
|
||||
if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
|
||||
strcpy(name, nodes[i].cn_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -409,8 +363,8 @@ static int name_from_nodeid(int nodeid, char *name)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (nodeid == nodes[i].node_id) {
|
||||
strcpy(name, nodes[i].name);
|
||||
if (nodeid == nodes[i].cn_nodeid) {
|
||||
strcpy(name, nodes[i].cn_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -431,7 +385,7 @@ static int nodeid_from_csid(char *csid)
|
||||
|
||||
static int _is_quorate()
|
||||
{
|
||||
return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
|
||||
return cman_is_quorate(c_handle);
|
||||
}
|
||||
|
||||
static void sync_ast_routine(void *arg)
|
||||
|
||||
@@ -56,15 +56,19 @@ struct cluster_ops *init_gulm_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_CMAN
|
||||
# include "cnxman-socket.h"
|
||||
# include <netinet/in.h>
|
||||
# include "libcman.h"
|
||||
# define CMAN_MAX_CSID_LEN 4
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
|
||||
# endif
|
||||
# undef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE 1500
|
||||
# define CLUSTER_PORT_CLVMD 11
|
||||
struct cluster_ops *init_cman_cluster(void);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -247,7 +247,7 @@ int main(int argc, char *argv[])
|
||||
if ((clops = init_cman_cluster())) {
|
||||
max_csid_len = CMAN_MAX_CSID_LEN;
|
||||
max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
|
||||
max_cluster_member_name_len = CMAN_MAX_CLUSTER_MEMBER_NAME_LEN;
|
||||
max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
|
||||
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
|
||||
}
|
||||
#endif
|
||||
@@ -509,6 +509,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
int quorate = clops->is_quorate();
|
||||
|
||||
/* Wait on the cluster FD and all local sockets/pipes */
|
||||
local_client_head.fd = clops->get_main_cluster_fd();
|
||||
FD_ZERO(&in);
|
||||
for (thisfd = &local_client_head; thisfd != NULL;
|
||||
thisfd = thisfd->next) {
|
||||
|
||||
@@ -303,6 +303,9 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
}
|
||||
}
|
||||
|
||||
if (lock_flags & LCK_PARTIAL_MODE)
|
||||
init_partial(1);
|
||||
|
||||
switch (command) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
|
||||
@@ -331,6 +334,9 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock_flags & LCK_PARTIAL_MODE)
|
||||
init_partial(0);
|
||||
|
||||
/* clean the pool for another command */
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
|
||||
@@ -1032,21 +1032,32 @@ static int open_fifos(struct dm_event_fifos *fifos)
|
||||
|
||||
/*
|
||||
* Read message from client making sure that data is available
|
||||
* and a complete message is read.
|
||||
* and a complete message is read. Must not block indefinitely.
|
||||
*/
|
||||
static int client_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
|
||||
{
|
||||
struct timeval t;
|
||||
unsigned bytes = 0;
|
||||
int ret = 0;
|
||||
fd_set fds;
|
||||
|
||||
errno = 0;
|
||||
while (bytes < sizeof(*msg) && errno != EOF) {
|
||||
do {
|
||||
/* Watch client read FIFO for input. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->client, &fds);
|
||||
} while (select(fifos->client+1, &fds, NULL, NULL, NULL) != 1);
|
||||
/* Watch client read FIFO for input. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->client, &fds);
|
||||
t.tv_sec = 1;
|
||||
t.tv_usec = 0;
|
||||
ret = select(fifos->client+1, &fds, NULL, NULL, &t);
|
||||
|
||||
if (!ret && !bytes) /* nothing to read */
|
||||
return 0;
|
||||
|
||||
if (!ret) /* trying to finish read */
|
||||
continue;
|
||||
|
||||
if (ret < 0) /* error */
|
||||
return 0;
|
||||
|
||||
ret = read(fifos->client, msg, sizeof(*msg) - bytes);
|
||||
bytes += ret > 0 ? ret : 0;
|
||||
@@ -1138,12 +1149,16 @@ static void process_request(struct dm_event_fifos *fifos)
|
||||
|
||||
/* FIXME: better error handling */
|
||||
|
||||
/* Read the request from the client. */
|
||||
if (!memset(&msg, 0, sizeof(msg)) ||
|
||||
!client_read(fifos, &msg)) {
|
||||
stack;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
/*
|
||||
* Read the request from the client.
|
||||
* Of course, it's tough to tell what to do when
|
||||
* we use fucking retarded return codes like
|
||||
* 0 for error.
|
||||
*/
|
||||
if (!client_read(fifos, &msg))
|
||||
return;
|
||||
}
|
||||
|
||||
msg.opcode.status = do_process_request(&msg);
|
||||
|
||||
@@ -1276,25 +1291,25 @@ void dmeventd(void)
|
||||
/*
|
||||
* We exit when there are no more devices to watch.
|
||||
* That is, when the last unregister happens.
|
||||
*
|
||||
* We must be careful though. One of our threads which is
|
||||
* watching a device may receive an event and:
|
||||
* 1) Alter the device and unregister it
|
||||
* or
|
||||
* 2) Alter the device, unregister, [alter again,] and reregister
|
||||
*
|
||||
* We must be capable of answering a request to unregister
|
||||
* that comes from the very thread that must be unregistered.
|
||||
* Additionally, if that thread unregisters itself and it was the
|
||||
* only thread being monitored, we must also handle the case where
|
||||
* that thread may perform a register before exiting. (In other
|
||||
* words, we can not simply exit if all threads have been unregistered
|
||||
* unless all threads are done processing.
|
||||
*/
|
||||
do {
|
||||
process_request(&fifos);
|
||||
cleanup_unused_threads();
|
||||
} while(!list_empty(&thread_registry));
|
||||
|
||||
/*
|
||||
* There may still have been some threads that were doing work,
|
||||
* make sure these are cleaned up
|
||||
*
|
||||
* I don't necessarily like the sleep there, but otherwise,
|
||||
* cleanup_unused_threads could get called many many times.
|
||||
* It's worth noting that the likelyhood of it being called
|
||||
* here is slim.
|
||||
*/
|
||||
while(!list_empty(&thread_registry_unused)) {
|
||||
sleep(1);
|
||||
cleanup_unused_threads();
|
||||
}
|
||||
} while(!list_empty(&thread_registry) || !list_empty(&thread_registry_unused));
|
||||
|
||||
exit_dm_lib();
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CFLAGS += -I${top_srcdir}/tools -I${top_srcdir}/include
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
@@ -32,5 +32,5 @@ include $(top_srcdir)/make.tmpl
|
||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $(libdir)/$<.$(LIB_VERSION) $(libdir)/$<
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CFLAGS += -I${top_srcdir}/tools -I${top_srcdir}/include
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
@@ -32,5 +32,5 @@ include $(top_srcdir)/make.tmpl
|
||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $(libdir)/$<.$(LIB_VERSION) $(libdir)/$<
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
|
||||
@@ -95,12 +95,12 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
||||
uint32_t *event_nr)
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -407,7 +407,7 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
/*
|
||||
* Returns 1 if percent set, else 0 on failure.
|
||||
*/
|
||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -427,8 +427,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
}
|
||||
|
||||
/* FIXME Merge with snapshot_percent */
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
|
||||
uint32_t *event_nr)
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
@@ -70,9 +70,9 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
/*
|
||||
* Returns 1 if percent has been set, else 0.
|
||||
*/
|
||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
|
||||
uint32_t *event_nr);
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr);
|
||||
|
||||
/*
|
||||
* Return number of LVs in the VG that are active.
|
||||
|
||||
@@ -432,7 +432,8 @@ void dev_manager_exit(void)
|
||||
}
|
||||
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, float *percent)
|
||||
const struct logical_volume *lv,
|
||||
float *percent)
|
||||
{
|
||||
char *name;
|
||||
const char *dlid;
|
||||
|
||||
@@ -41,7 +41,8 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
|
||||
const struct logical_volume *lv,
|
||||
int mknodes, int with_open_count, struct dm_info *info);
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, float *percent);
|
||||
const struct logical_volume *lv,
|
||||
float *percent);
|
||||
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, int wait,
|
||||
float *percent, uint32_t *event_nr);
|
||||
|
||||
315
lib/cache/lvmcache.c
vendored
315
lib/cache/lvmcache.c
vendored
@@ -86,7 +86,8 @@ int vgs_locked(void)
|
||||
return _vgs_locked;
|
||||
}
|
||||
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
|
||||
/* If vgid supplied, require a match. */
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
@@ -96,10 +97,16 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
|
||||
if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
|
||||
return NULL;
|
||||
|
||||
if (vgid)
|
||||
do
|
||||
if (!strncmp(vgid, vginfo->vgid, sizeof(vginfo->vgid)))
|
||||
return vginfo;
|
||||
while ((vginfo = vginfo->next));
|
||||
|
||||
return vginfo;
|
||||
}
|
||||
|
||||
const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
@@ -107,8 +114,9 @@ const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
struct list *devh, *tmp;
|
||||
struct list devs;
|
||||
struct device_list *devl;
|
||||
char vgid_found[ID_LEN + 1];
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(vgname)))
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
|
||||
return NULL;
|
||||
|
||||
/* This function is normally called before reading metadata so
|
||||
@@ -120,6 +128,8 @@ const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
list_add(&devs, &devl->list);
|
||||
}
|
||||
|
||||
memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
|
||||
|
||||
list_iterate_safe(devh, tmp, &devs) {
|
||||
devl = list_item(devh, struct device_list);
|
||||
label_read(devl->dev, &label);
|
||||
@@ -127,6 +137,11 @@ const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
dm_free(devl);
|
||||
}
|
||||
|
||||
/* If vginfo changed, caller needs to rescan */
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
|
||||
strncmp(vginfo->vgid, vgid_found, sizeof(vgid_found)))
|
||||
return NULL;
|
||||
|
||||
return vginfo->fmt;
|
||||
}
|
||||
|
||||
@@ -148,6 +163,19 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
|
||||
return vginfo;
|
||||
}
|
||||
|
||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if ((vginfo = vginfo_from_vgid(vgid))) {
|
||||
if (mem)
|
||||
return dm_pool_strdup(mem, vginfo->vgname);
|
||||
return vginfo->vgname;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
@@ -232,10 +260,33 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
return r;
|
||||
}
|
||||
|
||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
struct list *vgids;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
lvmcache_label_scan(cmd, full_scan);
|
||||
|
||||
if (!(vgids = str_list_create(cmd->mem))) {
|
||||
log_error("vgids list allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgids,
|
||||
dm_pool_strdup(cmd->mem, vginfo->vgid))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return vgids;
|
||||
}
|
||||
|
||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
struct list *vgnames;
|
||||
struct lvmcache_vginfo *vgi;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
lvmcache_label_scan(cmd, full_scan);
|
||||
|
||||
@@ -244,9 +295,9 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(vgi, &_vginfos) {
|
||||
list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgnames,
|
||||
dm_pool_strdup(cmd->mem, vgi->vgname))) {
|
||||
dm_pool_strdup(cmd->mem, vginfo->vgname))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
@@ -297,7 +348,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _drop_vginfo(struct lvmcache_info *info)
|
||||
static int _drop_vginfo(struct lvmcache_info *info)
|
||||
{
|
||||
if (!list_empty(&info->list)) {
|
||||
list_del(&info->list);
|
||||
@@ -306,8 +357,18 @@ static void _drop_vginfo(struct lvmcache_info *info)
|
||||
|
||||
if (info->vginfo && list_empty(&info->vginfo->infos)) {
|
||||
dm_hash_remove(_vgname_hash, info->vginfo->vgname);
|
||||
if (info->vginfo->next) {
|
||||
if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
info->vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->vginfo->vgname)
|
||||
dm_free(info->vginfo->vgname);
|
||||
if (info->vginfo->creation_host)
|
||||
dm_free(info->vginfo->creation_host);
|
||||
if (*info->vginfo->vgid)
|
||||
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||
list_del(&info->vginfo->list);
|
||||
@@ -315,6 +376,8 @@ static void _drop_vginfo(struct lvmcache_info *info)
|
||||
}
|
||||
|
||||
info->vginfo = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Unused
|
||||
@@ -356,8 +419,10 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
|
||||
|
||||
if (info->vginfo && *info->vginfo->vgid)
|
||||
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||
if (!vgid)
|
||||
if (!vgid) {
|
||||
log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
|
||||
return 1;
|
||||
}
|
||||
|
||||
strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
|
||||
info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
|
||||
@@ -367,19 +432,110 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
|
||||
info->vginfo->vgname, info->vginfo->vgid);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
|
||||
uint32_t vgstatus, const char *creation_host,
|
||||
struct lvmcache_vginfo *primary_vginfo)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_vginfo *last_vginfo = primary_vginfo;
|
||||
char uuid_primary[64], uuid_new[64];
|
||||
int use_new = 0;
|
||||
|
||||
/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
|
||||
if (primary_vginfo) {
|
||||
if (!id_write_format((struct id *)vgid, uuid_new, sizeof(uuid_new)))
|
||||
return_0;
|
||||
|
||||
if (!id_write_format((struct id *)&primary_vginfo->vgid, uuid_primary,
|
||||
sizeof(uuid_primary)))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* If Primary not exported, new exported => keep
|
||||
* Else Primary exported, new not exported => change
|
||||
* Else Primary has hostname for this machine => keep
|
||||
* Else Primary has no hostname, new has one => change
|
||||
* Else New has hostname for this machine => change
|
||||
* Else Keep primary.
|
||||
*/
|
||||
if (!(primary_vginfo->status & EXPORTED_VG) &&
|
||||
(vgstatus & EXPORTED_VG))
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"Existing %s takes precedence over "
|
||||
"exported %s", new_vginfo->vgname,
|
||||
uuid_primary, uuid_new);
|
||||
else if ((primary_vginfo->status & EXPORTED_VG) &&
|
||||
!(vgstatus & EXPORTED_VG)) {
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"%s takes precedence over exported %s",
|
||||
new_vginfo->vgname, uuid_new,
|
||||
uuid_primary);
|
||||
use_new = 1;
|
||||
} else if (primary_vginfo->creation_host &&
|
||||
!strcmp(primary_vginfo->creation_host,
|
||||
primary_vginfo->fmt->cmd->hostname))
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"Existing %s (created here) takes precedence "
|
||||
"over %s", new_vginfo->vgname, uuid_primary,
|
||||
uuid_new);
|
||||
else if (!primary_vginfo->creation_host && creation_host) {
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"%s (with creation_host) takes precedence over %s",
|
||||
new_vginfo->vgname, uuid_new,
|
||||
uuid_primary);
|
||||
use_new = 1;
|
||||
} else if (creation_host &&
|
||||
!strcmp(creation_host,
|
||||
primary_vginfo->fmt->cmd->hostname)) {
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"%s (created here) takes precedence over %s",
|
||||
new_vginfo->vgname, uuid_new,
|
||||
uuid_primary);
|
||||
use_new = 1;
|
||||
}
|
||||
|
||||
if (!use_new) {
|
||||
while (last_vginfo->next)
|
||||
last_vginfo = last_vginfo->next;
|
||||
last_vginfo->next = new_vginfo;
|
||||
return 1;
|
||||
}
|
||||
|
||||
dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
|
||||
}
|
||||
|
||||
if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
|
||||
log_error("cache_update: vg hash insertion failed: %s",
|
||||
new_vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (primary_vginfo)
|
||||
new_vginfo->next = primary_vginfo;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *creation_host)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo, *primary_vginfo;
|
||||
// struct lvmcache_vginfo *old_vginfo, *next;
|
||||
|
||||
/* If vgname is NULL and we don't already have a vgname,
|
||||
* assume ORPHAN - we want every entry to have a vginfo
|
||||
* attached for scanning reasons.
|
||||
*/
|
||||
if (!vgname && !info->vginfo)
|
||||
if (!vgname && !info->vginfo) {
|
||||
vgname = ORPHAN;
|
||||
vgid = ORPHAN;
|
||||
}
|
||||
|
||||
if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
|
||||
return 1;
|
||||
@@ -388,7 +544,43 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
_drop_vginfo(info);
|
||||
|
||||
/* Get existing vginfo or create new one */
|
||||
if (!(vginfo = vginfo_from_vgname(vgname))) {
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
|
||||
/*** FIXME - vginfo ends up duplicated instead of renamed.
|
||||
// Renaming? This lookup fails.
|
||||
if ((vginfo = vginfo_from_vgid(vgid))) {
|
||||
next = vginfo->next;
|
||||
old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
|
||||
if (old_vginfo == vginfo) {
|
||||
dm_hash_remove(_vgname_hash, old_vginfo->vgname);
|
||||
if (old_vginfo->next) {
|
||||
if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
old_vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else do {
|
||||
if (old_vginfo->next == vginfo) {
|
||||
old_vginfo->next = vginfo->next;
|
||||
break;
|
||||
}
|
||||
} while ((old_vginfo = old_vginfo->next));
|
||||
vginfo->next = NULL;
|
||||
|
||||
dm_free(vginfo->vgname);
|
||||
if (!(vginfo->vgname = dm_strdup(vgname))) {
|
||||
log_error("cache vgname alloc failed for %s", vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rename so can assume new name does not already exist
|
||||
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
***/
|
||||
if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
|
||||
log_error("lvmcache_update_vgname: list alloc failed");
|
||||
return 0;
|
||||
@@ -400,9 +592,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
return 0;
|
||||
}
|
||||
list_init(&vginfo->infos);
|
||||
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
|
||||
log_error("cache_update: vg hash insertion failed: %s",
|
||||
vginfo->vgname);
|
||||
primary_vginfo = vginfo_from_vgname(vgname, NULL);
|
||||
if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
|
||||
primary_vginfo)) {
|
||||
dm_free(vginfo->vgname);
|
||||
dm_free(vginfo);
|
||||
return 0;
|
||||
@@ -412,6 +604,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
list_add(&_vginfos, &vginfo->list);
|
||||
else
|
||||
list_add_h(&_vginfos, &vginfo->list);
|
||||
/***
|
||||
}
|
||||
***/
|
||||
}
|
||||
|
||||
info->vginfo = vginfo;
|
||||
@@ -420,8 +615,59 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
/* FIXME Check consistency of list! */
|
||||
vginfo->fmt = info->fmt;
|
||||
|
||||
log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
|
||||
*vgname ? "in VG " : "orphaned", vgname);
|
||||
log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
|
||||
*vgname ? "in VG " : "orphaned", vgname,
|
||||
vginfo->vgid[0] ? " (" : "",
|
||||
vginfo->vgid[0] ? vginfo->vgid : "",
|
||||
vginfo->vgid[0] ? ")" : "");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
|
||||
const char *creation_host)
|
||||
{
|
||||
if (!info || !info->vginfo)
|
||||
return 1;
|
||||
|
||||
if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
|
||||
log_debug("lvmcache: %s: VG %s %s exported",
|
||||
dev_name(info->dev), info->vginfo->vgname,
|
||||
vgstatus & EXPORTED_VG ? "now" : "no longer");
|
||||
|
||||
info->vginfo->status = vgstatus;
|
||||
|
||||
if (!creation_host)
|
||||
return 1;
|
||||
|
||||
if (info->vginfo->creation_host && !strcmp(creation_host,
|
||||
info->vginfo->creation_host))
|
||||
return 1;
|
||||
|
||||
if (info->vginfo->creation_host)
|
||||
dm_free(info->vginfo->creation_host);
|
||||
|
||||
if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
|
||||
log_error("cache creation host alloc failed for %s",
|
||||
creation_host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
|
||||
dev_name(info->dev), info->vginfo->vgname, creation_host);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *creation_host)
|
||||
{
|
||||
if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
|
||||
creation_host) ||
|
||||
!_lvmcache_update_vgid(info, vgid) ||
|
||||
!_lvmcache_update_vgstatus(info, vgstatus, creation_host))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -431,20 +677,17 @@ int lvmcache_update_vg(struct volume_group *vg)
|
||||
struct pv_list *pvl;
|
||||
struct lvmcache_info *info;
|
||||
char pvid_s[ID_LEN + 1];
|
||||
int vgid_updated = 0;
|
||||
|
||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
|
||||
/* FIXME Could pvl->pv->dev->pvid ever be different? */
|
||||
if ((info = info_from_pvid(pvid_s))) {
|
||||
lvmcache_update_vgname(info, vg->name);
|
||||
if (!vgid_updated) {
|
||||
_lvmcache_update_vgid(info, (char *) &vg->id);
|
||||
vgid_updated = 1;
|
||||
}
|
||||
}
|
||||
if ((info = info_from_pvid(pvid_s)) &&
|
||||
!lvmcache_update_vgname_and_id(info, vg->name,
|
||||
(char *) &vg->id,
|
||||
vg->status, NULL))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -452,7 +695,8 @@ int lvmcache_update_vg(struct volume_group *vg)
|
||||
|
||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
struct device *dev,
|
||||
const char *vgname, const char *vgid)
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus)
|
||||
{
|
||||
struct label *label;
|
||||
struct lvmcache_info *existing, *info;
|
||||
@@ -548,7 +792,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!lvmcache_update_vgname(info, vgname)) {
|
||||
if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
|
||||
if (!existing) {
|
||||
dm_hash_remove(_pvid_hash, pvid_s);
|
||||
strcpy(info->dev->pvid, "");
|
||||
@@ -558,10 +802,6 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_lvmcache_update_vgid(info, vgid))
|
||||
/* Non-critical */
|
||||
stack;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -576,9 +816,16 @@ static void _lvmcache_destroy_entry(struct lvmcache_info *info)
|
||||
|
||||
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
if (vginfo->vgname)
|
||||
dm_free(vginfo->vgname);
|
||||
dm_free(vginfo);
|
||||
struct lvmcache_vginfo *next;
|
||||
|
||||
do {
|
||||
next = vginfo->next;
|
||||
if (vginfo->vgname)
|
||||
dm_free(vginfo->vgname);
|
||||
if (vginfo->creation_host)
|
||||
dm_free(vginfo->creation_host);
|
||||
dm_free(vginfo);
|
||||
} while ((vginfo = next));
|
||||
}
|
||||
|
||||
static void _lvmcache_destroy_lockname(int present)
|
||||
|
||||
22
lib/cache/lvmcache.h
vendored
22
lib/cache/lvmcache.h
vendored
@@ -33,15 +33,20 @@ struct cmd_context;
|
||||
struct format_type;
|
||||
struct volume_group;
|
||||
|
||||
/* One per VG */
|
||||
struct lvmcache_vginfo {
|
||||
struct list list; /* Join these vginfos together */
|
||||
struct list infos; /* List head for lvmcache_infos */
|
||||
const struct format_type *fmt;
|
||||
char *vgname; /* "" == orphan */
|
||||
uint32_t status;
|
||||
char vgid[ID_LEN + 1];
|
||||
char _padding[7];
|
||||
struct lvmcache_vginfo *next; /* Another VG with same name? */
|
||||
char *creation_host;
|
||||
};
|
||||
|
||||
/* One per device */
|
||||
struct lvmcache_info {
|
||||
struct list list; /* Join VG members together */
|
||||
struct list mdas; /* list head for metadata areas */
|
||||
@@ -64,21 +69,26 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
|
||||
/* Add/delete a device */
|
||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
struct device *dev,
|
||||
const char *vgname, const char *vgid);
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus);
|
||||
void lvmcache_del(struct lvmcache_info *info);
|
||||
|
||||
/* Update things */
|
||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname);
|
||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *hostname);
|
||||
int lvmcache_update_vg(struct volume_group *vg);
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
|
||||
void lvmcache_unlock_vgname(const char *vgname);
|
||||
|
||||
/* Queries */
|
||||
const struct format_type *fmt_from_vgname(const char *vgname);
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname);
|
||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
|
||||
const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid);
|
||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
|
||||
int vgs_locked(void);
|
||||
int vgname_is_locked(const char *vgname);
|
||||
@@ -87,4 +97,8 @@ int vgname_is_locked(const char *vgname);
|
||||
/* Set full_scan to 1 to reread every filtered device label */
|
||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
/* Returns list of struct str_lists containing pool-allocated copy of vgids */
|
||||
/* Set full_scan to 1 to reread every filtered device label */
|
||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -657,7 +657,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
|
||||
"format"))) {
|
||||
"format", 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -753,7 +753,7 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
|
||||
"segment type"))) {
|
||||
"segment type", 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -223,11 +223,11 @@ static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_vgd(struct disk_list *data)
|
||||
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
|
||||
{
|
||||
struct vg_disk *vgd = &data->vgd;
|
||||
uint64_t pos = data->pvd.vg_on_disk.base;
|
||||
if (!dev_read(data->dev, pos, sizeof(*vgd), vgd))
|
||||
uint64_t pos = pvd->vg_on_disk.base;
|
||||
|
||||
if (!dev_read(dev, pos, sizeof(*vgd), vgd))
|
||||
fail;
|
||||
|
||||
_xlate_vgd(vgd);
|
||||
@@ -319,13 +319,31 @@ static int _read_extents(struct disk_list *data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void __update_lvmcache(const struct format_type *fmt,
|
||||
struct disk_list *dl,
|
||||
struct device *dev, const char *vgid,
|
||||
int exported)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
|
||||
dl->pvd.vg_name, vgid,
|
||||
exported ? EXPORTED_VG : 0))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
|
||||
list_init(&info->mdas);
|
||||
info->status &= ~CACHE_INVALID;
|
||||
}
|
||||
|
||||
static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
struct device *dev, struct dm_pool *mem,
|
||||
const char *vg_name)
|
||||
{
|
||||
struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
|
||||
struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
|
||||
const char *name = dev_name(dev);
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!dl) {
|
||||
stack;
|
||||
@@ -342,41 +360,32 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
|
||||
dl->pvd.vg_name, NULL)))
|
||||
stack;
|
||||
else {
|
||||
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
|
||||
list_init(&info->mdas);
|
||||
info->status &= ~CACHE_INVALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* is it an orphan ?
|
||||
*/
|
||||
if (!*dl->pvd.vg_name) {
|
||||
log_very_verbose("%s is not a member of any format1 VG", name);
|
||||
|
||||
/* Update VG cache */
|
||||
/* vgcache_add(dl->pvd.vg_name, NULL, dev, fmt); */
|
||||
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
return (vg_name) ? NULL : dl;
|
||||
}
|
||||
|
||||
if (!_read_vgd(dl)) {
|
||||
if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
|
||||
log_error("Failed to read VG data from PV (%s)", name);
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Update VG cache with what we found */
|
||||
/* vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt); */
|
||||
|
||||
if (vg_name && strcmp(vg_name, dl->pvd.vg_name)) {
|
||||
log_very_verbose("%s is not a member of the VG %s",
|
||||
name, vg_name);
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
__update_lvmcache(fmt, dl, dev, dl->vgd.vg_uuid,
|
||||
dl->vgd.vg_status & VG_EXPORTED);
|
||||
|
||||
if (!_read_uuids(dl)) {
|
||||
log_error("Failed to read PV uuid list from %s", name);
|
||||
goto bad;
|
||||
@@ -461,7 +470,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* Fast path if we already saw this VG and cached the list of PVs */
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
|
||||
vginfo->infos.n) {
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
dev = info->dev;
|
||||
|
||||
@@ -204,7 +204,8 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
|
||||
*/
|
||||
int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
struct volume_group *vg,
|
||||
struct physical_volume *pv, struct pv_disk *pvd);
|
||||
struct physical_volume *pv, struct pv_disk *pvd,
|
||||
struct vg_disk *vgd);
|
||||
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
|
||||
struct volume_group *vg,
|
||||
struct pv_disk *pvd, struct physical_volume *pv);
|
||||
@@ -237,6 +238,7 @@ void export_numbers(struct list *pvds, struct volume_group *vg);
|
||||
|
||||
void export_pv_act(struct list *pvds);
|
||||
int munge_pvd(struct device *dev, struct pv_disk *pvd);
|
||||
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd);
|
||||
|
||||
/* blech */
|
||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
|
||||
@@ -312,7 +312,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd)) {
|
||||
if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
@@ -396,7 +396,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
|
||||
pv->vg_name, NULL))) {
|
||||
pv->vg_name, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -502,6 +502,7 @@ static struct metadata_area_ops _metadata_format1_ops = {
|
||||
|
||||
static struct format_instance *_create_instance(const struct format_type *fmt,
|
||||
const char *vgname,
|
||||
const char *vgid,
|
||||
void *private)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
|
||||
@@ -49,7 +49,8 @@ static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
|
||||
|
||||
int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
struct volume_group *vg,
|
||||
struct physical_volume *pv, struct pv_disk *pvd)
|
||||
struct physical_volume *pv, struct pv_disk *pvd,
|
||||
struct vg_disk *vgd)
|
||||
{
|
||||
memset(pv, 0, sizeof(*pv));
|
||||
memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
|
||||
@@ -60,6 +61,8 @@ int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
|
||||
|
||||
/* Store system_id from first PV if PV belongs to a VG */
|
||||
if (vg && !*vg->system_id)
|
||||
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
|
||||
@@ -426,7 +429,7 @@ int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd)) {
|
||||
if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -58,11 +58,20 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
struct vg_disk vgd;
|
||||
struct lvmcache_info *info;
|
||||
const char *vgid = NULL;
|
||||
int exported = 0;
|
||||
|
||||
munge_pvd(dev, pvd);
|
||||
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) {
|
||||
if (*pvd->vg_name && read_vgd(dev, &vgd, pvd)) {
|
||||
vgid = vgd.vg_uuid;
|
||||
exported = pvd->pv_status & VG_EXPORTED;
|
||||
}
|
||||
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, vgid,
|
||||
exported))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
|
||||
|
||||
if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
|
||||
(char *) &vgid))) {
|
||||
(char *) &vgid, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -314,7 +314,7 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
|
||||
/*
|
||||
* If the cache scanning doesn't work, this will never work
|
||||
*/
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
|
||||
vginfo->infos.n) {
|
||||
|
||||
if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
|
||||
|
||||
@@ -268,6 +268,7 @@ static struct metadata_area_ops _metadata_format_pool_ops = {
|
||||
|
||||
static struct format_instance *_create_instance(const struct format_type *fmt,
|
||||
const char *vgname,
|
||||
const char *vgid,
|
||||
void *private)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
|
||||
@@ -165,6 +165,7 @@ int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
log_error("Unable to duplicate vg_name string");
|
||||
return 0;
|
||||
}
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
pv->status = 0;
|
||||
pv->size = pd->pl_blocks;
|
||||
pv->pe_size = POOL_PE_SIZE;
|
||||
|
||||
@@ -207,8 +207,8 @@ static void _remove_expired(struct list *archives, uint32_t archives_size,
|
||||
/* Convert retain_days into the time after which we must retain */
|
||||
retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
|
||||
|
||||
/* Assume list is ordered oldest first (by index) */
|
||||
list_iterate_items(bf, archives) {
|
||||
/* Assume list is ordered newest first (by index) */
|
||||
list_iterate_back_items(bf, archives) {
|
||||
/* Get the mtime of the file and unlink if too old */
|
||||
if (stat(bf->path, &sb)) {
|
||||
log_sys_error("stat", bf->path);
|
||||
@@ -311,7 +311,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
|
||||
|
||||
if (!(context = create_text_context(cmd, af->path, NULL)) ||
|
||||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
||||
context))) {
|
||||
NULL, context))) {
|
||||
log_error("Couldn't create text instance object.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
|
||||
if (!(context = create_text_context(cmd, file,
|
||||
cmd->cmd_line)) ||
|
||||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
||||
context))) {
|
||||
NULL, context))) {
|
||||
log_error("Couldn't create text format object.");
|
||||
return NULL;
|
||||
}
|
||||
@@ -286,7 +286,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
|
||||
|
||||
/* Attempt to write out using currently active format */
|
||||
if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
|
||||
NULL))) {
|
||||
NULL, NULL))) {
|
||||
log_error("Failed to allocate format instance");
|
||||
return 0;
|
||||
}
|
||||
@@ -365,7 +365,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
|
||||
|
||||
if (!(context = create_text_context(cmd, file, desc)) ||
|
||||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
||||
context))) {
|
||||
NULL, context))) {
|
||||
log_error("Couldn't create backup object.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
static struct format_instance *_create_text_instance(const struct format_type
|
||||
*fmt, const char *vgname,
|
||||
const char *vgid,
|
||||
void *context);
|
||||
|
||||
struct text_fid_context {
|
||||
@@ -219,7 +220,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
|
||||
error:
|
||||
if ((info = info_from_pvid(dev_area->dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -858,9 +859,11 @@ static int _scan_file(const struct format_type *fmt)
|
||||
}
|
||||
|
||||
/* FIXME stat file to see if it's changed */
|
||||
fid = _create_text_instance(fmt, NULL, NULL);
|
||||
fid = _create_text_instance(fmt, NULL, NULL,
|
||||
NULL);
|
||||
if ((vg = _vg_read_file_name(fid, vgname,
|
||||
path)))
|
||||
/* FIXME Store creation host in vg */
|
||||
lvmcache_update_vg(vg);
|
||||
}
|
||||
|
||||
@@ -871,65 +874,92 @@ static int _scan_file(const struct format_type *fmt)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
|
||||
char *buf, uint32_t size)
|
||||
const char *vgname_from_mda(const struct format_type *fmt,
|
||||
struct device_area *dev_area, struct id *vgid,
|
||||
uint32_t *vgstatus, char **creation_host)
|
||||
{
|
||||
struct raw_locn *rlocn;
|
||||
struct mda_header *mdah;
|
||||
unsigned int len;
|
||||
int r = 0;
|
||||
uint32_t wrap = 0;
|
||||
const char *vgname = NULL;
|
||||
unsigned int len = 0;
|
||||
char buf[NAME_LEN + 1];
|
||||
|
||||
if (!dev_open(dev_area->dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(mdah = _raw_read_mda_header(fmt, dev_area))) {
|
||||
stack;
|
||||
if (!(mdah = _raw_read_mda_header(fmt, dev_area)))
|
||||
goto_out;
|
||||
|
||||
/* FIXME Cope with returning a list */
|
||||
rlocn = mdah->raw_locns;
|
||||
|
||||
/* Do quick check for a vgname */
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
NAME_LEN, buf))
|
||||
goto_out;
|
||||
|
||||
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
|
||||
len < (NAME_LEN - 1))
|
||||
len++;
|
||||
|
||||
buf[len] = '\0';
|
||||
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(buf))
|
||||
goto_out;
|
||||
|
||||
/* We found a VG - now check the metadata */
|
||||
if (rlocn->offset + rlocn->size > mdah->size)
|
||||
wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
|
||||
|
||||
if (wrap > rlocn->offset) {
|
||||
log_error("%s: metadata too large for circular buffer",
|
||||
dev_name(dev_area->dev));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rlocn = mdah->raw_locns;
|
||||
/* FIXME 64-bit */
|
||||
if (!(vgname = text_vgname_import(fmt, dev_area->dev,
|
||||
(off_t) (dev_area->start +
|
||||
rlocn->offset),
|
||||
(uint32_t) (rlocn->size - wrap),
|
||||
(off_t) (dev_area->start +
|
||||
MDA_HEADER_SIZE),
|
||||
wrap, calc_crc, rlocn->checksum,
|
||||
vgid, vgstatus, creation_host)))
|
||||
goto_out;
|
||||
|
||||
while (rlocn->offset) {
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
size, buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
len = 0;
|
||||
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
|
||||
len < (size - 1))
|
||||
len++;
|
||||
buf[len] = '\0';
|
||||
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
break;
|
||||
|
||||
/* FIXME Cope with returning a list */
|
||||
rlocn++;
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(vgname)) {
|
||||
stack;
|
||||
vgname = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64
|
||||
" for %s (%s)",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset,
|
||||
rlocn->size, vgname, vgid->uuid);
|
||||
|
||||
out:
|
||||
if (!dev_close(dev_area->dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
return vgname;
|
||||
}
|
||||
|
||||
static int _scan_raw(const struct format_type *fmt)
|
||||
{
|
||||
struct raw_list *rl;
|
||||
struct list *raw_list;
|
||||
char vgnamebuf[NAME_LEN + 2];
|
||||
const char *vgname;
|
||||
struct volume_group *vg;
|
||||
struct format_instance fid;
|
||||
struct id vgid;
|
||||
uint32_t vgstatus;
|
||||
|
||||
raw_list = &((struct mda_lists *) fmt->private)->raws;
|
||||
|
||||
@@ -938,9 +968,9 @@ static int _scan_raw(const struct format_type *fmt)
|
||||
|
||||
list_iterate_items(rl, raw_list) {
|
||||
/* FIXME We're reading mdah twice here... */
|
||||
if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf,
|
||||
sizeof(vgnamebuf))) {
|
||||
if ((vg = _vg_read_raw_area(&fid, vgnamebuf,
|
||||
if ((vgname = vgname_from_mda(fmt, &rl->dev_area, &vgid, &vgstatus,
|
||||
NULL))) {
|
||||
if ((vg = _vg_read_raw_area(&fid, vgname,
|
||||
&rl->dev_area, 0)))
|
||||
lvmcache_update_vg(vg);
|
||||
}
|
||||
@@ -1109,7 +1139,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
/* FIXME Test mode don't update cache? */
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
|
||||
ORPHAN, NULL))) {
|
||||
ORPHAN, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1245,7 +1275,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
/* Have we already cached vgname? */
|
||||
if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
|
||||
get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
|
||||
info->dev->pvid, pv)) {
|
||||
info->vginfo->vgid, info->dev->pvid, pv)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1256,6 +1286,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
if (info->vginfo && info->vginfo->vgname &&
|
||||
*info->vginfo->vgname &&
|
||||
get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
|
||||
info->vginfo->vgid,
|
||||
info->dev->pvid, pv)) {
|
||||
return 1;
|
||||
}
|
||||
@@ -1450,6 +1481,7 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
/* NULL vgname means use only the supplied context e.g. an archive file */
|
||||
static struct format_instance *_create_text_instance(const struct format_type
|
||||
*fmt, const char *vgname,
|
||||
const char *vgid,
|
||||
void *context)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
@@ -1535,7 +1567,7 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
|
||||
/* Scan PVs in VG for any further MDAs */
|
||||
lvmcache_label_scan(fmt->cmd, 0);
|
||||
if (!(vginfo = vginfo_from_vgname(vgname))) {
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
@@ -1569,7 +1601,6 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
|
||||
out:
|
||||
return fid;
|
||||
|
||||
}
|
||||
|
||||
void *create_text_context(struct cmd_context *cmd, const char *path,
|
||||
|
||||
@@ -54,7 +54,8 @@ int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct list *mda
|
||||
struct device *dev, uint64_t start, uint64_t size);
|
||||
void del_mdas(struct list *mdas);
|
||||
|
||||
int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
|
||||
char *buf, uint32_t size);
|
||||
const char *vgname_from_mda(const struct format_type *fmt,
|
||||
struct device_area *dev_area, struct id *vgid,
|
||||
uint32_t *vgstatus, char **creation_host);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,10 @@ struct text_vg_version_ops {
|
||||
struct config_tree * cf);
|
||||
void (*read_desc) (struct dm_pool * mem, struct config_tree * cf,
|
||||
time_t *when, char **desc);
|
||||
const char *(*read_vgname) (const struct format_type *fmt,
|
||||
struct config_tree *cft,
|
||||
struct id *vgid, uint32_t *vgstatus,
|
||||
char **creation_host);
|
||||
};
|
||||
|
||||
struct text_vg_version_ops *text_vg_vsn1_init(void);
|
||||
@@ -70,5 +74,12 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
checksum_fn_t checksum_fn,
|
||||
uint32_t checksum,
|
||||
time_t *when, char **desc);
|
||||
const char *text_vgname_import(const struct format_type *fmt,
|
||||
struct device *dev,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
struct id *vgid, uint32_t *vgstatus,
|
||||
char **creation_host);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,53 @@
|
||||
/* FIXME Use tidier inclusion method */
|
||||
static struct text_vg_version_ops *(_text_vsn_list[2]);
|
||||
|
||||
const char *text_vgname_import(const struct format_type *fmt,
|
||||
struct device *dev,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
struct id *vgid, uint32_t *vgstatus,
|
||||
char **creation_host)
|
||||
{
|
||||
struct config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
const char *vgname;
|
||||
|
||||
static int _initialised = 0;
|
||||
|
||||
if (!_initialised) {
|
||||
_text_vsn_list[0] = text_vg_vsn1_init();
|
||||
_text_vsn_list[1] = NULL;
|
||||
_initialised = 1;
|
||||
}
|
||||
|
||||
if (!(cft = create_config_tree(NULL)))
|
||||
goto_out;
|
||||
|
||||
if ((!dev && !read_config_file(cft)) ||
|
||||
(dev && !read_config_fd(cft, dev, offset, size,
|
||||
offset2, size2, checksum_fn, checksum)))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* Find a set of version functions that can read this file
|
||||
*/
|
||||
for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
|
||||
if (!(*vsn)->check_version(cft))
|
||||
continue;
|
||||
|
||||
if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid, vgstatus,
|
||||
creation_host)))
|
||||
goto_out;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
destroy_config_tree(cft);
|
||||
return vgname;
|
||||
}
|
||||
|
||||
struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
const char *file,
|
||||
struct device *dev,
|
||||
|
||||
@@ -167,6 +167,8 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
|
||||
if (!(cn = find_config_node(pvn, "status"))) {
|
||||
log_error("Couldn't find status flags for physical volume.");
|
||||
return 0;
|
||||
@@ -798,10 +800,59 @@ static void _read_desc(struct dm_pool *mem,
|
||||
*when = u;
|
||||
}
|
||||
|
||||
static const char *_read_vgname(const struct format_type *fmt,
|
||||
struct config_tree *cft, struct id *vgid,
|
||||
uint32_t *vgstatus, char **creation_host)
|
||||
{
|
||||
struct config_node *vgn, *cn;
|
||||
struct dm_pool *mem = fmt->cmd->mem;
|
||||
char *vgname;
|
||||
int old_suppress;
|
||||
|
||||
old_suppress = log_suppress(2);
|
||||
*creation_host = dm_pool_strdup(mem,
|
||||
find_config_str(cft->root,
|
||||
"creation_host", ""));
|
||||
log_suppress(old_suppress);
|
||||
|
||||
/* skip any top-level values */
|
||||
for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
|
||||
|
||||
if (!vgn) {
|
||||
log_error("Couldn't find volume group in file.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(vgname = dm_pool_strdup(mem, vgn->key)))
|
||||
return_0;
|
||||
|
||||
vgn = vgn->child;
|
||||
|
||||
if (!_read_id(vgid, vgn, "id")) {
|
||||
log_error("Couldn't read uuid for volume group %s.", vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(vgn, "status"))) {
|
||||
log_error("Couldn't find status flags for volume group %s.",
|
||||
vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(read_flags(vgstatus, VG_FLAGS, cn->v))) {
|
||||
log_error("Couldn't read status flags for volume group %s.",
|
||||
vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vgname;
|
||||
}
|
||||
|
||||
static struct text_vg_version_ops _vsn1_ops = {
|
||||
check_version:_check_version,
|
||||
read_vg:_read_vg,
|
||||
read_desc:_read_desc
|
||||
read_desc:_read_desc,
|
||||
read_vgname:_read_vgname
|
||||
};
|
||||
|
||||
struct text_vg_version_ops *text_vg_vsn1_init(void)
|
||||
|
||||
@@ -195,13 +195,16 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct disk_locn *dlocn_xl;
|
||||
uint64_t offset;
|
||||
struct metadata_area *mda;
|
||||
char vgnamebuf[NAME_LEN + 2];
|
||||
struct id vgid;
|
||||
struct mda_context *mdac;
|
||||
const char *vgname;
|
||||
uint32_t vgstatus;
|
||||
char *creation_host;
|
||||
|
||||
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
|
||||
|
||||
if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
|
||||
return 0;
|
||||
if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL, 0)))
|
||||
return_0;
|
||||
*label = info->label;
|
||||
|
||||
info->device_size = xlate64(pvhdr->device_size_xl);
|
||||
@@ -232,10 +235,12 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
|
||||
sizeof(vgnamebuf))) {
|
||||
lvmcache_update_vgname(info, vgnamebuf);
|
||||
}
|
||||
if ((vgname = vgname_from_mda(info->fmt, &mdac->area,
|
||||
&vgid, &vgstatus, &creation_host)) &&
|
||||
!lvmcache_update_vgname_and_id(info, vgname,
|
||||
(char *) &vgid, vgstatus,
|
||||
creation_host))
|
||||
return_0;
|
||||
}
|
||||
|
||||
info->status &= ~CACHE_INVALID;
|
||||
|
||||
@@ -117,15 +117,6 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
int found = 0;
|
||||
char readbuf[LABEL_SCAN_SIZE];
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
|
||||
log_debug("%s: Failed to read label area", dev_name(dev));
|
||||
goto out;
|
||||
@@ -184,13 +175,11 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
out:
|
||||
if (!found) {
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
0, NULL);
|
||||
log_very_verbose("%s: No label detected", dev_name(dev));
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -272,16 +261,29 @@ int label_read(struct device *dev, struct label **result)
|
||||
char buf[LABEL_SIZE];
|
||||
struct labeller *l;
|
||||
uint64_t sector;
|
||||
int r;
|
||||
struct lvmcache_info *info;
|
||||
int r = 0;
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or))) {
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
0, NULL);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or)))
|
||||
goto_out;
|
||||
|
||||
if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
|
||||
(*result)->sector = sector;
|
||||
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -335,18 +337,35 @@ int label_write(struct device *dev, struct label *label)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Unused */
|
||||
int label_verify(struct device *dev)
|
||||
{
|
||||
struct labeller *l;
|
||||
char buf[LABEL_SIZE];
|
||||
uint64_t sector;
|
||||
struct lvmcache_info *info;
|
||||
int r = 0;
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or))) {
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
0, NULL);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
return ((l->ops->verify) ? l->ops->verify(l, buf, sector) : 1);
|
||||
if (!(l = _find_labeller(dev, buf, §or)))
|
||||
goto_out;
|
||||
|
||||
r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;
|
||||
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void label_destroy(struct label *label)
|
||||
|
||||
@@ -330,6 +330,9 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
args[0] = flags & 0x7F; /* Maskoff lock flags */
|
||||
args[1] = flags & 0xC0; /* Bitmap flags */
|
||||
|
||||
if (partial_mode())
|
||||
args[1] |= LCK_PARTIAL_MODE;
|
||||
|
||||
/*
|
||||
* VG locks are just that: locks, and have no side effects
|
||||
* so we only need to do them on the local node because all
|
||||
|
||||
@@ -72,7 +72,7 @@ int init_external_locking(struct locking_type *locking, struct config_tree *cft)
|
||||
libname = find_config_str(cft->root, "global/locking_library",
|
||||
DEFAULT_LOCKING_LIB);
|
||||
|
||||
if (!(_locking_lib = load_shared_library(cft, libname, "locking"))) {
|
||||
if (!(_locking_lib = load_shared_library(cft, libname, "locking", 1))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,11 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_LOCAL 0x00000040 /* Don't propagate to other nodes */
|
||||
#define LCK_CLUSTER_VG 0x00000080 /* VG is clustered */
|
||||
|
||||
/*
|
||||
* Additional lock bits for cluster communication
|
||||
*/
|
||||
#define LCK_PARTIAL_MODE 0x00000001 /* Running in partial mode */
|
||||
|
||||
/*
|
||||
* Common combinations
|
||||
*/
|
||||
|
||||
@@ -90,9 +90,13 @@ void init_syslog(int facility)
|
||||
_syslog = 1;
|
||||
}
|
||||
|
||||
void log_suppress(int suppress)
|
||||
int log_suppress(int suppress)
|
||||
{
|
||||
int old_suppress = _log_suppress;
|
||||
|
||||
_log_suppress = suppress;
|
||||
|
||||
return old_suppress;
|
||||
}
|
||||
|
||||
void release_log_memory(void)
|
||||
@@ -253,6 +257,9 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
const char *message;
|
||||
const char *trformat; /* Translated format string */
|
||||
|
||||
if (_log_suppress == 2)
|
||||
return;
|
||||
|
||||
trformat = _(format);
|
||||
|
||||
if (_lvm2_log_fn) {
|
||||
|
||||
@@ -86,8 +86,9 @@ int ignorelockingfailure(void);
|
||||
int lockingfailed(void);
|
||||
int security_level(void);
|
||||
|
||||
/* Suppress messages to stdout/stderr */
|
||||
void log_suppress(int suppress);
|
||||
/* Suppress messages to stdout/stderr (1) or everywhere (2) */
|
||||
/* Returns previous setting */
|
||||
int log_suppress(int suppress);
|
||||
|
||||
/* Suppress messages to syslog */
|
||||
void syslog_suppress(int suppress);
|
||||
|
||||
@@ -71,6 +71,8 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
|
||||
/* Units of 512-byte sectors */
|
||||
pv->pe_size = vg->extent_size;
|
||||
|
||||
@@ -143,13 +145,14 @@ static int _copy_pv(struct physical_volume *pv_to,
|
||||
}
|
||||
|
||||
int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
|
||||
const char *id, struct physical_volume *pv)
|
||||
const char *vgid, const char *pvid,
|
||||
struct physical_volume *pv)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct pv_list *pvl;
|
||||
int consistent = 0;
|
||||
|
||||
if (!(vg = vg_read(fmt->cmd, vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(fmt->cmd, vg_name, vgid, &consistent))) {
|
||||
log_error("get_pv_from_vg_by_id: vg_read failed to read VG %s",
|
||||
vg_name);
|
||||
return 0;
|
||||
@@ -160,7 +163,7 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
|
||||
vg_name);
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (id_equal(&pvl->pv->id, (const struct id *) id)) {
|
||||
if (id_equal(&pvl->pv->id, (const struct id *) pvid)) {
|
||||
if (!_copy_pv(pv, pvl->pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
@@ -239,7 +242,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
|
||||
/* is this vg name already in use ? */
|
||||
old_partial = partial_mode();
|
||||
init_partial(1);
|
||||
if (vg_read(cmd, vg_name, &consistent)) {
|
||||
if (vg_read(cmd, vg_name, NULL, &consistent)) {
|
||||
log_err("A volume group called '%s' already exists.", vg_name);
|
||||
goto bad;
|
||||
}
|
||||
@@ -286,7 +289,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
|
||||
list_init(&vg->tags);
|
||||
|
||||
if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg_name,
|
||||
NULL))) {
|
||||
NULL, NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
goto bad;
|
||||
}
|
||||
@@ -496,7 +499,7 @@ struct physical_volume *pv_create(const struct format_type *fmt,
|
||||
uint64_t pvmetadatasize, struct list *mdas)
|
||||
{
|
||||
struct dm_pool *mem = fmt->cmd->mem;
|
||||
struct physical_volume *pv = dm_pool_alloc(mem, sizeof(*pv));
|
||||
struct physical_volume *pv = dm_pool_zalloc(mem, sizeof(*pv));
|
||||
|
||||
if (!pv) {
|
||||
stack;
|
||||
@@ -862,7 +865,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
struct volume_group *vg;
|
||||
struct physical_volume *pv;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(ORPHAN))) {
|
||||
if (!(vginfo = vginfo_from_vgname(ORPHAN, NULL))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -907,6 +910,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
*/
|
||||
static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
const char *vgname,
|
||||
const char *vgid,
|
||||
int *consistent, int precommitted)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
@@ -928,15 +932,15 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
|
||||
/* Find the vgname in the cache */
|
||||
/* If it's not there we must do full scan to be completely sure */
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
lvmcache_label_scan(cmd, 0);
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
if (memlock()) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -947,7 +951,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
use_precommitted = 0;
|
||||
|
||||
/* create format instance with appropriate metadata area */
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
return NULL;
|
||||
}
|
||||
@@ -978,7 +982,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
inconsistent = 0;
|
||||
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -987,7 +991,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
use_precommitted = 0;
|
||||
|
||||
/* create format instance with appropriate metadata area */
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1069,12 +1073,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
int *consistent)
|
||||
const char *vgid, int *consistent)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct lv_list *lvl;
|
||||
|
||||
if (!(vg = _vg_read(cmd, vgname, consistent, 0)))
|
||||
if (!(vg = _vg_read(cmd, vgname, vgid, consistent, 0)))
|
||||
return NULL;
|
||||
|
||||
if (!check_pv_segments(vg)) {
|
||||
@@ -1112,7 +1116,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
/* Is corresponding vgname already cached? */
|
||||
if ((vginfo = vginfo_from_vgid(vgid)) &&
|
||||
vginfo->vgname && *vginfo->vgname) {
|
||||
if ((vg = _vg_read(cmd, vginfo->vgname,
|
||||
if ((vg = _vg_read(cmd, vginfo->vgname, vgid,
|
||||
&consistent, precommitted)) &&
|
||||
!strncmp(vg->id.uuid, vgid, ID_LEN)) {
|
||||
if (!consistent) {
|
||||
@@ -1143,7 +1147,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
if (!vgname || !*vgname)
|
||||
continue; // FIXME Unnecessary?
|
||||
consistent = 0;
|
||||
if ((vg = _vg_read(cmd, vgname, &consistent,
|
||||
if ((vg = _vg_read(cmd, vgname, vgid, &consistent,
|
||||
precommitted)) &&
|
||||
!strncmp(vg->id.uuid, vgid, ID_LEN)) {
|
||||
if (!consistent) {
|
||||
@@ -1245,13 +1249,18 @@ struct list *get_vgs(struct cmd_context *cmd, int full_scan)
|
||||
return lvmcache_get_vgnames(cmd, full_scan);
|
||||
}
|
||||
|
||||
struct list *get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
return lvmcache_get_vgids(cmd, full_scan);
|
||||
}
|
||||
|
||||
struct list *get_pvs(struct cmd_context *cmd)
|
||||
{
|
||||
struct str_list *strl;
|
||||
struct list *results;
|
||||
const char *vgname;
|
||||
const char *vgname, *vgid;
|
||||
struct list *pvh, *tmp;
|
||||
struct list *vgnames;
|
||||
struct list *vgids;
|
||||
struct volume_group *vg;
|
||||
int consistent = 0;
|
||||
int old_partial;
|
||||
@@ -1267,7 +1276,7 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
list_init(results);
|
||||
|
||||
/* Get list of VGs */
|
||||
if (!(vgnames = get_vgs(cmd, 0))) {
|
||||
if (!(vgids = get_vgids(cmd, 0))) {
|
||||
log_error("get_pvs: get_vgs failed");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1278,12 +1287,16 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
old_pvmove = pvmove_mode();
|
||||
init_partial(1);
|
||||
init_pvmove(1);
|
||||
list_iterate_items(strl, vgnames) {
|
||||
vgname = strl->str;
|
||||
if (!vgname)
|
||||
list_iterate_items(strl, vgids) {
|
||||
vgid = strl->str;
|
||||
if (!vgid)
|
||||
continue; /* FIXME Unnecessary? */
|
||||
consistent = 0;
|
||||
if (!(vg = vg_read(cmd, vgname, &consistent))) {
|
||||
if (!(vgname = vgname_from_vgid(NULL, vgid))) {
|
||||
stack;
|
||||
continue;
|
||||
}
|
||||
if (!(vg = vg_read(cmd, vgname, vgid, &consistent))) {
|
||||
stack;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ struct physical_volume {
|
||||
struct device *dev;
|
||||
const struct format_type *fmt;
|
||||
const char *vg_name;
|
||||
struct id vgid;
|
||||
|
||||
uint32_t status;
|
||||
uint64_t size;
|
||||
@@ -382,6 +383,7 @@ struct format_handler {
|
||||
*/
|
||||
struct format_instance *(*create_instance) (const struct format_type *
|
||||
fmt, const char *vgname,
|
||||
const char *vgid,
|
||||
void *context);
|
||||
|
||||
/*
|
||||
@@ -403,7 +405,7 @@ int vg_write(struct volume_group *vg);
|
||||
int vg_commit(struct volume_group *vg);
|
||||
int vg_revert(struct volume_group *vg);
|
||||
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
|
||||
int *consistent);
|
||||
const char *vgid, int *consistent);
|
||||
struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
|
||||
struct list *mdas, uint64_t *label_sector,
|
||||
int warnings);
|
||||
@@ -411,6 +413,7 @@ struct list *get_pvs(struct cmd_context *cmd);
|
||||
|
||||
/* Set full_scan to 1 to re-read every (filtered) device label */
|
||||
struct list *get_vgs(struct cmd_context *cmd, int full_scan);
|
||||
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);
|
||||
@@ -478,7 +481,8 @@ struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name);
|
||||
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
|
||||
struct id *id);
|
||||
int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
|
||||
const char *id, struct physical_volume *pv);
|
||||
const char *vgid, const char *pvid,
|
||||
struct physical_volume *pv);
|
||||
|
||||
/* Find an LV within a given VG */
|
||||
struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name);
|
||||
@@ -535,11 +539,16 @@ int lv_split_segment(struct logical_volume *lv, uint32_t le);
|
||||
*/
|
||||
int lv_is_origin(const struct logical_volume *lv);
|
||||
int lv_is_cow(const struct logical_volume *lv);
|
||||
int lv_is_visible(const struct logical_volume *lv);
|
||||
|
||||
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
|
||||
|
||||
/* Given a cow LV, return return the snapshot lv_segment that uses it */
|
||||
struct lv_segment *find_cow(const struct logical_volume *lv);
|
||||
|
||||
/* Given a cow LV, return its origin */
|
||||
struct logical_volume *origin_from_cow(const struct logical_volume *lv);
|
||||
|
||||
int vg_add_snapshot(struct format_instance *fid, const char *name,
|
||||
struct logical_volume *origin, struct logical_volume *cow,
|
||||
union lvid *lvid, uint32_t extent_count,
|
||||
|
||||
@@ -28,12 +28,26 @@ int lv_is_cow(const struct logical_volume *lv)
|
||||
return lv->snapshot ? 1 : 0;
|
||||
}
|
||||
|
||||
int lv_is_visible(const struct logical_volume *lv)
|
||||
{
|
||||
if (lv_is_cow(lv))
|
||||
return lv_is_visible(find_cow(lv)->lv);
|
||||
|
||||
return lv->status & VISIBLE_LV ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Given a cow LV, return the snapshot lv_segment that uses it */
|
||||
struct lv_segment *find_cow(const struct logical_volume *lv)
|
||||
{
|
||||
return lv->snapshot;
|
||||
}
|
||||
|
||||
/* Given a cow LV, return its origin */
|
||||
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
||||
{
|
||||
return lv->snapshot->origin;
|
||||
}
|
||||
|
||||
int vg_add_snapshot(struct format_instance *fid, const char *name,
|
||||
struct logical_volume *origin,
|
||||
struct logical_volume *cow, union lvid *lvid,
|
||||
|
||||
@@ -38,7 +38,7 @@ void get_shared_library_path(struct config_tree *cft, const char *libname,
|
||||
}
|
||||
|
||||
void *load_shared_library(struct config_tree *cft, const char *libname,
|
||||
const char *desc)
|
||||
const char *desc, int silent)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
void *library;
|
||||
@@ -47,8 +47,14 @@ void *load_shared_library(struct config_tree *cft, const char *libname,
|
||||
|
||||
log_very_verbose("Opening shared %s library %s", desc, path);
|
||||
|
||||
if (!(library = dlopen(path, RTLD_LAZY)))
|
||||
log_error("Unable to open external %s library %s", desc, path);
|
||||
if (!(library = dlopen(path, RTLD_LAZY))) {
|
||||
if (silent && ignorelockingfailure())
|
||||
log_verbose("Unable to open external %s library %s",
|
||||
desc, path);
|
||||
else
|
||||
log_error("Unable to open external %s library %s",
|
||||
desc, path);
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
void get_shared_library_path(struct config_tree *cft, const char *libname,
|
||||
char *path, int path_len);
|
||||
void *load_shared_library(struct config_tree *cf, const char *libname,
|
||||
const char *what);
|
||||
const char *what, int silent);
|
||||
|
||||
@@ -324,7 +324,6 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
struct lvinfo info;
|
||||
char *repstr;
|
||||
struct lv_segment *snap_seg;
|
||||
float snap_percent;
|
||||
|
||||
if (!(repstr = dm_pool_zalloc(rh->mem, 7))) {
|
||||
@@ -344,7 +343,7 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
repstr[0] = 'v';
|
||||
else if (lv_is_origin(lv))
|
||||
repstr[0] = 'o';
|
||||
else if (find_cow(lv))
|
||||
else if (lv_is_cow(lv))
|
||||
repstr[0] = 's';
|
||||
else
|
||||
repstr[0] = '-';
|
||||
@@ -377,8 +376,8 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
repstr[4] = 'd'; /* Inactive without table */
|
||||
|
||||
/* Snapshot dropped? */
|
||||
if (info.live_table && (snap_seg = find_cow(lv)) &&
|
||||
(!lv_snapshot_percent(snap_seg->cow, &snap_percent) ||
|
||||
if (info.live_table && lv_is_cow(lv) &&
|
||||
(!lv_snapshot_percent(lv, &snap_percent) ||
|
||||
snap_percent < 0 || snap_percent >= 100)) {
|
||||
repstr[0] = toupper(repstr[0]);
|
||||
if (info.suspended)
|
||||
@@ -491,10 +490,9 @@ static int _origin_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
struct lv_segment *snap_seg;
|
||||
|
||||
if ((snap_seg = find_cow(lv)))
|
||||
return _string_disp(rh, field, &snap_seg->origin->name);
|
||||
if (lv_is_cow(lv))
|
||||
return _string_disp(rh, field, &origin_from_cow(lv)->name);
|
||||
|
||||
field->report_string = "";
|
||||
field->sort_value = (const void *) field->report_string;
|
||||
@@ -527,8 +525,7 @@ static int _lvname_disp(struct report_handle *rh, struct field *field,
|
||||
char *repstr;
|
||||
size_t len;
|
||||
|
||||
/* FIXME Remove need for snapshot special case */
|
||||
if (lv->status & VISIBLE_LV || lv_is_cow(lv)) {
|
||||
if (lv_is_visible(lv)) {
|
||||
repstr = lv->name;
|
||||
return _string_disp(rh, field, &repstr);
|
||||
}
|
||||
@@ -667,11 +664,10 @@ static int _chunksize_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
struct lv_segment *snap_seg;
|
||||
uint64_t size;
|
||||
|
||||
if ((snap_seg = find_cow(seg->lv)))
|
||||
size = (uint64_t) snap_seg->chunk_size;
|
||||
if (lv_is_cow(seg->lv))
|
||||
size = (uint64_t) find_cow(seg->lv)->chunk_size;
|
||||
else
|
||||
size = 0;
|
||||
|
||||
@@ -840,7 +836,6 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
struct lv_segment *snap_seg;
|
||||
struct lvinfo info;
|
||||
float snap_percent;
|
||||
uint64_t *sortval;
|
||||
@@ -851,16 +846,15 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(snap_seg = find_cow(lv)) ||
|
||||
(lv_info(lv->vg->cmd, snap_seg->cow, &info, 0) && !info.exists)) {
|
||||
if (!lv_is_cow(lv) ||
|
||||
(lv_info(lv->vg->cmd, lv, &info, 0) && !info.exists)) {
|
||||
field->report_string = "";
|
||||
*sortval = UINT64_C(0);
|
||||
field->sort_value = sortval;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_snapshot_percent(snap_seg->cow, &snap_percent)
|
||||
|| snap_percent < 0) {
|
||||
if (!lv_snapshot_percent(lv, &snap_percent) || snap_percent < 0) {
|
||||
field->report_string = "100.00";
|
||||
*sortval = UINT64_C(100);
|
||||
field->sort_value = sortval;
|
||||
|
||||
@@ -108,3 +108,4 @@ dm_hash_get_data
|
||||
dm_hash_get_first
|
||||
dm_hash_get_next
|
||||
dm_set_selinux_context
|
||||
dm_task_set_geometry
|
||||
|
||||
@@ -116,6 +116,7 @@ static struct cmd_data _cmd_data_v1[] = {
|
||||
{ "mknodes", 0, {4, 0, 0} },
|
||||
{ "versions", 0, {4, 1, 0} },
|
||||
{ "message", 0, {4, 2, 0} },
|
||||
{ "setgeometry",0, {4, 6, 0} },
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
@@ -59,7 +59,9 @@
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
/* dm major version no for running kernel */
|
||||
static int _dm_version = DM_VERSION_MAJOR;
|
||||
static unsigned _dm_version = DM_VERSION_MAJOR;
|
||||
static unsigned _dm_version_minor = 0;
|
||||
static unsigned _dm_version_patchlevel = 0;
|
||||
static int _log_suppress = 0;
|
||||
|
||||
static dm_bitset_t _dm_bitset = NULL;
|
||||
@@ -103,6 +105,9 @@ static struct cmd_data _cmd_data_v4[] = {
|
||||
#ifdef DM_TARGET_MSG
|
||||
{"message", DM_TARGET_MSG, {4, 2, 0}},
|
||||
#endif
|
||||
#ifdef DM_DEV_SET_GEOMETRY
|
||||
{"setgeometry", DM_DEV_SET_GEOMETRY, {4, 6, 0}},
|
||||
#endif
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
@@ -236,10 +241,10 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!dm_set_selinux_context(control, S_IFCHR)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dm_set_selinux_context(control, S_IFCHR)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
@@ -742,7 +747,7 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
||||
|
||||
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
|
||||
{
|
||||
unsigned int *v;
|
||||
unsigned *v;
|
||||
|
||||
#ifdef DM_COMPAT
|
||||
if (_dm_version == 1)
|
||||
@@ -756,6 +761,9 @@ int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
|
||||
|
||||
v = dmt->dmi.v4->version;
|
||||
snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
|
||||
_dm_version_minor = v[1];
|
||||
_dm_version_patchlevel = v[2];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -801,7 +809,7 @@ int dm_check_version(void)
|
||||
if (!_dm_compat)
|
||||
goto bad;
|
||||
|
||||
log_verbose("device-mapper ioctl protocol version %d failed. "
|
||||
log_verbose("device-mapper ioctl protocol version %u failed. "
|
||||
"Trying protocol version 1.", _dm_version);
|
||||
_dm_version = 1;
|
||||
if (_check_version(dmversion, sizeof(dmversion), 0)) {
|
||||
@@ -1001,6 +1009,23 @@ int dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start)
|
||||
{
|
||||
size_t len = strlen(cylinders) + 1 + strlen(heads) + 1 + strlen(sectors) + 1 + strlen(start) + 1;
|
||||
|
||||
if (!(dmt->geometry = dm_malloc(len))) {
|
||||
log_error("dm_task_set_geometry: dm_malloc failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sprintf(dmt->geometry, "%s %s %s %s", cylinders, heads, sectors, start) < 0) {
|
||||
log_error("dm_task_set_geometry: sprintf failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_no_open_count(struct dm_task *dmt)
|
||||
{
|
||||
dmt->no_open_count = 1;
|
||||
@@ -1095,6 +1120,40 @@ static void *_add_target(struct target *t, void *out, void *end)
|
||||
return out;
|
||||
}
|
||||
|
||||
static int _lookup_dev_name(uint64_t dev, char *buf, size_t len)
|
||||
{
|
||||
struct dm_names *names;
|
||||
unsigned next = 0;
|
||||
struct dm_task *dmt;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (!(names = dm_task_get_names(dmt)))
|
||||
goto out;
|
||||
|
||||
if (!names->dev)
|
||||
goto out;
|
||||
|
||||
do {
|
||||
names = (void *) names + next;
|
||||
if (names->dev == dev) {
|
||||
strncpy(buf, names->name, len);
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
next = names->next;
|
||||
} while (next);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
{
|
||||
const size_t min_size = 16 * 1024;
|
||||
@@ -1123,11 +1182,26 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (count && dmt->geometry) {
|
||||
log_error("targets and geometry are incompatible");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->newname && (dmt->sector || dmt->message)) {
|
||||
log_error("message and newname are incompatible");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->newname && dmt->geometry) {
|
||||
log_error("geometry and newname are incompatible");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->geometry && (dmt->sector || dmt->message)) {
|
||||
log_error("geometry and message are incompatible");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->sector && !dmt->message) {
|
||||
log_error("message is required with sector");
|
||||
return NULL;
|
||||
@@ -1139,6 +1213,9 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
if (dmt->message)
|
||||
len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
|
||||
|
||||
if (dmt->geometry)
|
||||
len += strlen(dmt->geometry) + 1;
|
||||
|
||||
/*
|
||||
* Give len a minimum size so that we have space to store
|
||||
* dependencies or status information.
|
||||
@@ -1164,16 +1241,6 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
dmi->data_size = len;
|
||||
dmi->data_start = sizeof(struct dm_ioctl);
|
||||
|
||||
if (dmt->dev_name)
|
||||
strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
|
||||
|
||||
if (dmt->type == DM_DEVICE_SUSPEND)
|
||||
dmi->flags |= DM_SUSPEND_FLAG;
|
||||
if (dmt->read_only)
|
||||
dmi->flags |= DM_READONLY_FLAG;
|
||||
if (dmt->skip_lockfs)
|
||||
dmi->flags |= DM_SKIP_LOCKFS_FLAG;
|
||||
|
||||
if (dmt->minor >= 0) {
|
||||
if (dmt->major <= 0) {
|
||||
log_error("Missing major number for persistent device.");
|
||||
@@ -1183,9 +1250,31 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
dmi->dev = MKDEV(dmt->major, dmt->minor);
|
||||
}
|
||||
|
||||
/* Does driver support device number referencing? */
|
||||
if (_dm_version_minor < 3 && !dmt->dev_name && !dmt->uuid && dmi->dev) {
|
||||
if (!_lookup_dev_name(dmi->dev, dmi->name, sizeof(dmi->name))) {
|
||||
log_error("Unable to find name for device (%" PRIu32
|
||||
":%" PRIu32 ")", dmt->major, dmt->minor);
|
||||
goto bad;
|
||||
}
|
||||
log_verbose("device (%" PRIu32 ":%" PRIu32 ") is %s "
|
||||
"for compatibility with old kernel",
|
||||
dmt->major, dmt->minor, dmi->name);
|
||||
}
|
||||
|
||||
if (dmt->dev_name)
|
||||
strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
|
||||
|
||||
if (dmt->uuid)
|
||||
strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
|
||||
|
||||
if (dmt->type == DM_DEVICE_SUSPEND)
|
||||
dmi->flags |= DM_SUSPEND_FLAG;
|
||||
if (dmt->read_only)
|
||||
dmi->flags |= DM_READONLY_FLAG;
|
||||
if (dmt->skip_lockfs)
|
||||
dmi->flags |= DM_SKIP_LOCKFS_FLAG;
|
||||
|
||||
dmi->target_count = count;
|
||||
dmi->event_nr = dmt->event_nr;
|
||||
|
||||
@@ -1205,6 +1294,9 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
strcpy(tmsg->message, dmt->message);
|
||||
}
|
||||
|
||||
if (dmt->geometry)
|
||||
strcpy(b, dmt->geometry);
|
||||
|
||||
return dmi;
|
||||
|
||||
bad:
|
||||
@@ -1342,7 +1434,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
task->tail = NULL;
|
||||
dm_task_destroy(task);
|
||||
if (!r)
|
||||
return r;
|
||||
goto revert;
|
||||
|
||||
/* Use the original structure last so the info will be correct */
|
||||
dmt->type = DM_DEVICE_RESUME;
|
||||
@@ -1351,6 +1443,17 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
|
||||
r = dm_task_run(dmt);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
revert:
|
||||
dmt->type = DM_DEVICE_REMOVE;
|
||||
dm_free(dmt->uuid);
|
||||
dmt->uuid = NULL;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
log_error("Failed to revert device creation.");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1571,6 +1674,9 @@ repeat_ioctl:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Was structure reused? */
|
||||
if (dmt->dmi.v4)
|
||||
dm_free(dmt->dmi.v4);
|
||||
dmt->dmi.v4 = dmi;
|
||||
return 1;
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ struct dm_task {
|
||||
} dmi;
|
||||
char *newname;
|
||||
char *message;
|
||||
char *geometry;
|
||||
uint64_t sector;
|
||||
int no_open_count;
|
||||
int skip_lockfs;
|
||||
|
||||
@@ -80,7 +80,9 @@ enum {
|
||||
|
||||
DM_DEVICE_LIST_VERSIONS,
|
||||
|
||||
DM_DEVICE_TARGET_MSG
|
||||
DM_DEVICE_TARGET_MSG,
|
||||
|
||||
DM_DEVICE_SET_GEOMETRY
|
||||
};
|
||||
|
||||
struct dm_task;
|
||||
@@ -145,6 +147,7 @@ int dm_task_set_uid(struct dm_task *dmt, uid_t uid);
|
||||
int dm_task_set_gid(struct dm_task *dmt, gid_t gid);
|
||||
int dm_task_set_mode(struct dm_task *dmt, mode_t mode);
|
||||
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
|
||||
int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start);
|
||||
int dm_task_set_message(struct dm_task *dmt, const char *message);
|
||||
int dm_task_set_sector(struct dm_task *dmt, uint64_t sector);
|
||||
int dm_task_no_open_count(struct dm_task *dmt);
|
||||
@@ -369,7 +372,7 @@ int dm_tree_node_add_target_area(struct dm_tree_node *node,
|
||||
|
||||
void *dm_malloc_aux(size_t s, const char *file, int line);
|
||||
void *dm_malloc_aux_debug(size_t s, const char *file, int line);
|
||||
char *dm_strdup_aux(const char *str);
|
||||
char *dm_strdup_aux(const char *str, const char *file, int line);
|
||||
void dm_free_aux(void *p);
|
||||
void *dm_realloc_aux(void *p, unsigned int s, const char *file, int line);
|
||||
int dm_dump_memory_debug(void);
|
||||
@@ -378,7 +381,7 @@ void dm_bounds_check_debug(void);
|
||||
#ifdef DEBUG_MEM
|
||||
|
||||
# define dm_malloc(s) dm_malloc_aux_debug((s), __FILE__, __LINE__)
|
||||
# define dm_strdup(s) dm_strdup_aux(s)
|
||||
# define dm_strdup(s) dm_strdup_aux((s), __FILE__, __LINE__)
|
||||
# define dm_free(p) dm_free_aux(p)
|
||||
# define dm_realloc(p, s) dm_realloc_aux(p, s, __FILE__, __LINE__)
|
||||
# define dm_dump_memory() dm_dump_memory_debug()
|
||||
|
||||
@@ -510,3 +510,4 @@ out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
char *dm_strdup_aux(const char *str)
|
||||
char *dm_strdup_aux(const char *str, const char *file, int line)
|
||||
{
|
||||
char *ret = dm_malloc(strlen(str) + 1);
|
||||
char *ret = dm_malloc_aux_debug(strlen(str) + 1, file, line);
|
||||
|
||||
if (ret)
|
||||
strcpy(ret, str);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH DMSETUP 8 "Sep 17 2003" "Linux" "MAINTENTANCE COMMANDS"
|
||||
.TH DMSETUP 8 "Apr 06 2006" "Linux" "MAINTENTANCE COMMANDS"
|
||||
.SH NAME
|
||||
dmsetup \- low level logical volume management
|
||||
.SH SYNOPSIS
|
||||
@@ -12,7 +12,7 @@ dmsetup \- low level logical volume management
|
||||
.B dmsetup remove_all
|
||||
.br
|
||||
.B dmsetup suspend
|
||||
.I device_name
|
||||
.I [--nolockfs] device_name
|
||||
.br
|
||||
.B dmsetup resume
|
||||
.I device_name
|
||||
@@ -29,7 +29,7 @@ dmsetup \- low level logical volume management
|
||||
.B dmsetup rename
|
||||
.I device_name new_name
|
||||
.br
|
||||
.B dmsetup ls [--target target_type] [--exec command]
|
||||
.B dmsetup ls [--target target_type] [--exec command] [--tree [-o options]]
|
||||
.br
|
||||
.B dmsetup info
|
||||
.I [device_name]
|
||||
@@ -147,10 +147,17 @@ Outputs some brief information about the device in the form:
|
||||
.IP \fBls
|
||||
.I [--target target_type]
|
||||
.I [--exec command]
|
||||
.I [--tree [-o options]]
|
||||
.br
|
||||
List device names. Optionally only list devices that have at least
|
||||
one target of the specified type. Optionally execute a command for
|
||||
each device. The device name is appended to the supplied command.
|
||||
--tree displays dependencies between devices as a tree.
|
||||
It accepts a comma-separate list of options.
|
||||
Some specify the information displayed against each node:
|
||||
device/nodevice; active, open, rw, uuid.
|
||||
Others specify how the tree is displayed:
|
||||
ascii, utf, vt100; compact, inverted, notrunc.
|
||||
.IP \fBload|reload
|
||||
.I device_name [table_file]
|
||||
.br
|
||||
@@ -183,11 +190,14 @@ Outputs status information for each of the device's targets.
|
||||
With --target, only information relating to the specified target type
|
||||
is displayed.
|
||||
.IP \fBsuspend
|
||||
.I [--nolockfs]
|
||||
.I device_name
|
||||
.br
|
||||
Suspends a device. Any I/O that has already been mapped by the device
|
||||
but has not yet completed will be flushed. Any further I/O to that
|
||||
device will be postponed for as long as the device is suspended.
|
||||
If there's a filesystem on the device which supports the operation,
|
||||
an attempt will be made to sync it first unless --nolockfs is specified.
|
||||
.IP \fBtable
|
||||
.I [--target target_type]
|
||||
.I [device_name]
|
||||
|
||||
@@ -17,6 +17,8 @@ vgchange \- change attributes of a volume group
|
||||
.RB [ \-l | \-\-logicalvolume
|
||||
.IR MaxLogicalVolumes ]
|
||||
.RB [ \-P | \-\-partial]
|
||||
.RB [ \-s | \-\-physicalextentsize
|
||||
.IR PhysicalExtentSize [ \fBkKmMgGtT\fR ]]
|
||||
.RB [ -t | \-\-test]
|
||||
.RB [ \-v | \-\-verbose]
|
||||
.RB [ \-\-version ]
|
||||
@@ -59,6 +61,27 @@ exclusively because they can only be used on one node at once.
|
||||
Changes the maximum logical volume number of an existing inactive
|
||||
volume group.
|
||||
.TP
|
||||
.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
|
||||
Changes the physical extent size on physical volumes of this volume group.
|
||||
A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
|
||||
is the default if no suffix is present.
|
||||
The default is 4 MB and it must be at least 1 KB and a power of 2.
|
||||
|
||||
Before increasing the physical extent size, you might need to use lvresize,
|
||||
pvresize and/or pvmove so that everything fits. For example, every
|
||||
contiguous range of extents used in a logical volume must start and
|
||||
end on an extent boundary.
|
||||
|
||||
If the volume group metadata uses lvm1 format, extents can vary in size from
|
||||
8KB to 16GB and there is a limit of 65534 extents in each logical volume. The
|
||||
default of 4 MB leads to a maximum logical volume size of around 256GB.
|
||||
|
||||
If the volume group metadata uses lvm2 format those restrictions do not apply,
|
||||
but having a large number of extents will slow down the tools but have no
|
||||
impact on I/O performance to the logical volume. The smallest PE is 1KB.
|
||||
|
||||
The 2.4 kernel has a limitation of 2TB per block device.
|
||||
.TP
|
||||
.BR \-x ", " \-\-resizeable { y | n }
|
||||
Enables or disables the extension/reduction of this volume group
|
||||
with/by physical volumes.
|
||||
|
||||
@@ -59,17 +59,22 @@ as described in \fBpvcreate(8)\fP.
|
||||
.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
|
||||
Sets the physical extent size on physical volumes of this volume group.
|
||||
A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
|
||||
is the default if no suffix is present. Values can be from 8 KB to 16 GB in
|
||||
powers of 2. The default is 4 MB.
|
||||
is the default if no suffix is present.
|
||||
The default is 4 MB and it must be at least 1 KB and a power of 2.
|
||||
|
||||
Once this value has been set, it is difficult to change it without recreating
|
||||
the volume group which would involve backing up and restoring data on any
|
||||
logical volumes.
|
||||
If the volume group metadata uses lvm1 format, there is a limit of 65534
|
||||
extents in each logical volume, so the default of 4 MB leads to a maximum
|
||||
logical volume size of around 256GB.
|
||||
If the volume group metadata uses lvm2 format there is no such restriction,
|
||||
although having a large number of extents will slow down
|
||||
the tools but have no impact on I/O performance to the logical volume.
|
||||
logical volumes. However, if no extents need moving for the new
|
||||
value to apply, it can be altered using vgchange \-s.
|
||||
|
||||
If the volume group metadata uses lvm1 format, extents can vary in size from
|
||||
8KB to 16GB and there is a limit of 65534 extents in each logical volume. The
|
||||
default of 4 MB leads to a maximum logical volume size of around 256GB.
|
||||
|
||||
If the volume group metadata uses lvm2 format those restrictions do not apply,
|
||||
but having a large number of extents will slow down the tools but have no
|
||||
impact on I/O performance to the logical volume. The smallest PE is 1KB.
|
||||
|
||||
The 2.4 kernel has a limitation of 2TB per block device.
|
||||
.SH EXAMPLES
|
||||
To create a volume group named
|
||||
|
||||
@@ -80,17 +80,26 @@ xx(lvchange,
|
||||
|
||||
xx(lvconvert,
|
||||
"Change logical volume layout",
|
||||
"lvconvert " "\n"
|
||||
"lvconvert "
|
||||
"[-m|--mirrors Mirrors]\n"
|
||||
"\t[--alloc AllocationPolicy]\n"
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|-?|--help]\n"
|
||||
"\t[-m|--mirrors Mirrors]\n"
|
||||
"\t[-R|--regionsize MirrorLogRegionSize]\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[--version]" "\n"
|
||||
"\tLogicalVolume[Path] [PhysicalVolume[Path]...]\n",
|
||||
"\tLogicalVolume[Path] [PhysicalVolume[Path]...]\n\n"
|
||||
|
||||
alloc_ARG, mirrors_ARG, regionsize_ARG, test_ARG)
|
||||
"lvconvert "
|
||||
"[-s|--snapshot]\n"
|
||||
"\t[-c|--chunksize]\n"
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|-?|--help]\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[-Z|--zero {y|n}]\n"
|
||||
"\t[--version]" "\n"
|
||||
"\tOriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]\n",
|
||||
|
||||
alloc_ARG, chunksize_ARG, mirrors_ARG, snapshot_ARG, test_ARG, zero_ARG)
|
||||
|
||||
xx(lvcreate,
|
||||
"Create a logical volume",
|
||||
@@ -527,6 +536,7 @@ xx(pvs,
|
||||
"\t[--nosuffix]\n"
|
||||
"\t[-o|--options [+]Field[,Field]]\n"
|
||||
"\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n"
|
||||
"\t[-P|--partial] " "\n"
|
||||
"\t[--segments]\n"
|
||||
"\t[--separator Separator]\n"
|
||||
"\t[--unbuffered]\n"
|
||||
@@ -536,8 +546,8 @@ xx(pvs,
|
||||
"\t[PhysicalVolume [PhysicalVolume...]]\n",
|
||||
|
||||
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
|
||||
nolocking_ARG, nosuffix_ARG, options_ARG, segments_ARG, separator_ARG,
|
||||
sort_ARG, unbuffered_ARG, units_ARG)
|
||||
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, segments_ARG,
|
||||
separator_ARG, sort_ARG, unbuffered_ARG, units_ARG)
|
||||
|
||||
xx(pvscan,
|
||||
"List all physical volumes",
|
||||
|
||||
@@ -508,6 +508,39 @@ static int _message(int argc, char **argv, void *data)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _setgeometry(int argc, char **argv, void *data)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_SET_GEOMETRY)))
|
||||
return 0;
|
||||
|
||||
if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {
|
||||
if (!_set_task_device(dmt, NULL, 0))
|
||||
goto out;
|
||||
} else {
|
||||
if (!_set_task_device(dmt, argv[1], 0))
|
||||
goto out;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (!dm_task_set_geometry(dmt, argv[1], argv[2], argv[3], argv[4]))
|
||||
goto out;
|
||||
|
||||
/* run the task */
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _version(int argc, char **argv, void *data)
|
||||
{
|
||||
char version[80];
|
||||
@@ -1317,7 +1350,7 @@ static struct command _commands[] = {
|
||||
{"reload", "<device> [<table_file>]", 0, 2, _load},
|
||||
{"rename", "<device> <new_name>", 1, 2, _rename},
|
||||
{"message", "<device> <sector> <message>", 2, -1, _message},
|
||||
{"ls", "[--target <target_type>] [--exec <command>] [--tree]", 0, 0, _ls},
|
||||
{"ls", "[--target <target_type>] [--exec <command>] [--tree [-o options]]", 0, 0, _ls},
|
||||
{"info", "[<device>]", 0, 1, _info},
|
||||
{"deps", "[<device>]", 0, 1, _deps},
|
||||
{"status", "[<device>] [--target <target_type>]", 0, 1, _status},
|
||||
@@ -1326,6 +1359,7 @@ static struct command _commands[] = {
|
||||
{"mknodes", "[<device>]", 0, 1, _mknodes},
|
||||
{"targets", "", 0, 0, _targets},
|
||||
{"version", "", 0, 0, _version},
|
||||
{"setgeometry", "<device> <cyl> <head> <sect> <start>", 5, 5, _setgeometry},
|
||||
{NULL, NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
@@ -1340,7 +1374,9 @@ static void _usage(FILE *out)
|
||||
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, "Table_file contents may be supplied on stdin.\n\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");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,20 @@
|
||||
#include "lv_alloc.h"
|
||||
|
||||
struct lvconvert_params {
|
||||
int snapshot;
|
||||
int zero;
|
||||
|
||||
const char *origin;
|
||||
const char *lv_name;
|
||||
const char *vg_name;
|
||||
|
||||
uint32_t chunk_size;
|
||||
uint32_t region_size;
|
||||
|
||||
uint32_t mirrors;
|
||||
sign_t mirrors_sign;
|
||||
uint32_t region_size;
|
||||
|
||||
struct segment_type *segtype;
|
||||
|
||||
alloc_policy_t alloc;
|
||||
|
||||
@@ -28,52 +38,164 @@ struct lvconvert_params {
|
||||
struct list *pvh;
|
||||
};
|
||||
|
||||
static int _read_name_params(struct lvconvert_params *lp,
|
||||
struct cmd_context *cmd, int *pargc, char ***pargv)
|
||||
{
|
||||
char *ptr;
|
||||
const char *vg_name = NULL;
|
||||
|
||||
if (lp->snapshot) {
|
||||
if (!*pargc) {
|
||||
log_error("Please specify a logical volume to act as "
|
||||
"the snapshot origin.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp->origin = *pargv[0];
|
||||
(*pargv)++, (*pargc)--;
|
||||
if (!(lp->vg_name = extract_vgname(cmd, lp->origin))) {
|
||||
log_error("The origin name should include the "
|
||||
"volume group.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Strip the volume group from the origin */
|
||||
if ((ptr = strrchr(lp->origin, (int) '/')))
|
||||
lp->origin = ptr + 1;
|
||||
}
|
||||
|
||||
if (!*pargc) {
|
||||
log_error("Please provide logical volume path");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp->lv_name = (*pargv)[0];
|
||||
(*pargv)++, (*pargc)--;
|
||||
|
||||
if (strchr(lp->lv_name, '/') &&
|
||||
(vg_name = extract_vgname(cmd, lp->lv_name)) &&
|
||||
lp->vg_name && strcmp(vg_name, lp->vg_name)) {
|
||||
log_error("Please use a single volume group name "
|
||||
"(\"%s\" or \"%s\")", vg_name, lp->vg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lp->vg_name)
|
||||
lp->vg_name = vg_name;
|
||||
|
||||
if (!validate_name(lp->vg_name)) {
|
||||
log_error("Please provide a valid volume group name");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ptr = strrchr(lp->lv_name, '/')))
|
||||
lp->lv_name = ptr + 1;
|
||||
|
||||
if (!apply_lvname_restrictions(lp->lv_name))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
|
||||
int argc, char **argv)
|
||||
{
|
||||
memset(lp, 0, sizeof(*lp));
|
||||
|
||||
if (arg_count(cmd, mirrors_ARG) + arg_count(cmd, snapshot_ARG) != 1) {
|
||||
log_error("Exactly one of --mirrors or --snapshot arguments "
|
||||
"required.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_count(cmd, snapshot_ARG))
|
||||
lp->snapshot = 1;
|
||||
|
||||
if (arg_count(cmd, mirrors_ARG)) {
|
||||
lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0);
|
||||
lp->mirrors_sign = arg_sign_value(cmd, mirrors_ARG, 0);
|
||||
}
|
||||
|
||||
lp->alloc = ALLOC_INHERIT;
|
||||
if (arg_count(cmd, alloc_ARG))
|
||||
lp->alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG,
|
||||
lp->alloc);
|
||||
|
||||
if (!arg_count(cmd, mirrors_ARG)) {
|
||||
log_error("--mirrors argument required");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0);
|
||||
lp->mirrors_sign = arg_sign_value(cmd, mirrors_ARG, 0);
|
||||
|
||||
/*
|
||||
* --regionsize is only valid when converting an LV into a mirror.
|
||||
* This is checked when we know the state of the LV being converted.
|
||||
*/
|
||||
if (arg_count(cmd, regionsize_ARG)) {
|
||||
if (arg_sign_value(cmd, regionsize_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Negative regionsize is invalid");
|
||||
if (lp->snapshot) {
|
||||
if (arg_count(cmd, regionsize_ARG)) {
|
||||
log_error("--regionsize is only available with mirrors");
|
||||
return 0;
|
||||
}
|
||||
lp->region_size = 2 * arg_uint_value(cmd, regionsize_ARG, 0);
|
||||
} else
|
||||
lp->region_size = 2 * find_config_int(cmd->cft->root,
|
||||
"activation/mirror_region_size",
|
||||
DEFAULT_MIRROR_REGION_SIZE);
|
||||
|
||||
if (lp->region_size & (lp->region_size - 1)) {
|
||||
log_error("Region size (%" PRIu32 ") must be a power of 2",
|
||||
lp->region_size);
|
||||
if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Negative chunk size is invalid");
|
||||
return 0;
|
||||
}
|
||||
lp->chunk_size = 2 * arg_uint_value(cmd, chunksize_ARG, 8);
|
||||
if (lp->chunk_size < 8 || lp->chunk_size > 1024 ||
|
||||
(lp->chunk_size & (lp->chunk_size - 1))) {
|
||||
log_error("Chunk size must be a power of 2 in the "
|
||||
"range 4K to 512K");
|
||||
return 0;
|
||||
}
|
||||
log_verbose("Setting chunksize to %d sectors.", lp->chunk_size);
|
||||
|
||||
if (!(lp->segtype = get_segtype_from_string(cmd, "snapshot")))
|
||||
return_0;
|
||||
|
||||
lp->zero = strcmp(arg_str_value(cmd, zero_ARG,
|
||||
(lp->segtype->flags &
|
||||
SEG_CANNOT_BE_ZEROED) ?
|
||||
"n" : "y"), "n");
|
||||
|
||||
} else { /* Mirrors */
|
||||
if (arg_count(cmd, chunksize_ARG)) {
|
||||
log_error("--chunksize is only available with "
|
||||
"snapshots");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_count(cmd, zero_ARG)) {
|
||||
log_error("--zero is only available with snapshots");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* --regionsize is only valid if converting an LV into a mirror.
|
||||
* Checked when we know the state of the LV being converted.
|
||||
*/
|
||||
if (arg_count(cmd, regionsize_ARG)) {
|
||||
if (arg_sign_value(cmd, regionsize_ARG, 0) ==
|
||||
SIGN_MINUS) {
|
||||
log_error("Negative regionsize is invalid");
|
||||
return 0;
|
||||
}
|
||||
lp->region_size = 2 * arg_uint_value(cmd,
|
||||
regionsize_ARG, 0);
|
||||
} else
|
||||
lp->region_size = 2 * find_config_int(cmd->cft->root,
|
||||
"activation/mirror_region_size",
|
||||
DEFAULT_MIRROR_REGION_SIZE);
|
||||
|
||||
if (lp->region_size & (lp->region_size - 1)) {
|
||||
log_error("Region size (%" PRIu32
|
||||
") must be a power of 2", lp->region_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(lp->segtype = get_segtype_from_string(cmd, "striped")))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (activation() && lp->segtype->ops->target_present &&
|
||||
!lp->segtype->ops->target_present()) {
|
||||
log_error("%s: Required device-mapper target(s) not "
|
||||
"detected in your kernel", lp->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!argc) {
|
||||
log_error("Please give logical volume path");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp->lv_name = argv[0];
|
||||
argv++, argc--;
|
||||
if (!_read_name_params(lp, cmd, &argc, &argv))
|
||||
return_0;
|
||||
|
||||
lp->pv_count = argc;
|
||||
lp->pvs = argv;
|
||||
@@ -89,7 +211,6 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
struct alloc_handle *ah = NULL;
|
||||
struct logical_volume *log_lv;
|
||||
struct list *parallel_areas;
|
||||
struct segment_type *segtype;
|
||||
|
||||
seg = first_seg(lv);
|
||||
existing_mirrors = seg->area_count;
|
||||
@@ -121,10 +242,9 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!remove_mirror_images(seg, 1, lp->pv_count ? lp->pvh : NULL, 1)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!remove_mirror_images(seg, 1,
|
||||
lp->pv_count ? lp->pvh : NULL, 1))
|
||||
return_0;
|
||||
} else { /* mirrors > 1 */
|
||||
if ((lv->status & MIRRORED)) {
|
||||
if (list_size(&lv->segments) != 1) {
|
||||
@@ -149,10 +269,10 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
return 0;
|
||||
} else {
|
||||
/* Reduce number of mirrors */
|
||||
if (!remove_mirror_images(seg, lp->mirrors, lp->pv_count ? lp->pvh : NULL, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!remove_mirror_images(seg, lp->mirrors,
|
||||
lp->pv_count ?
|
||||
lp->pvh : NULL, 0))
|
||||
return_0;
|
||||
}
|
||||
} else {
|
||||
/* Make existing LV into mirror set */
|
||||
@@ -166,22 +286,16 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
}
|
||||
}
|
||||
|
||||
if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv)))
|
||||
return_0;
|
||||
|
||||
segtype = get_segtype_from_string(cmd, "striped");
|
||||
|
||||
if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1,
|
||||
lp->mirrors - 1, 1,
|
||||
if (!(ah = allocate_extents(lv->vg, NULL, lp->segtype,
|
||||
1, lp->mirrors - 1, 1,
|
||||
lv->le_count * (lp->mirrors - 1),
|
||||
NULL, 0, 0, lp->pvh,
|
||||
lp->alloc,
|
||||
parallel_areas))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
parallel_areas)))
|
||||
return_0;
|
||||
|
||||
lp->region_size = adjusted_mirror_region_size(lv->vg->extent_size,
|
||||
lv->le_count,
|
||||
@@ -195,20 +309,17 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
}
|
||||
|
||||
if (!create_mirror_layers(ah, 1, lp->mirrors, lv,
|
||||
segtype, 0, lp->region_size,
|
||||
log_lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
lp->segtype, 0,
|
||||
lp->region_size,
|
||||
log_lv))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
|
||||
|
||||
if (!vg_write(lv->vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!vg_write(lv->vg))
|
||||
return_0;
|
||||
|
||||
backup(lv->vg);
|
||||
|
||||
@@ -235,6 +346,68 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvconvert_snapshot(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct lvconvert_params *lp)
|
||||
{
|
||||
struct logical_volume *org;
|
||||
|
||||
if (!(org = find_lv(lv->vg, lp->origin))) {
|
||||
log_error("Couldn't find origin volume '%s'.", lp->origin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (org->status & (LOCKED|PVMOVE) || lv_is_cow(org)) {
|
||||
log_error("Unable to create a snapshot of a %s LV.",
|
||||
org->status & LOCKED ? "locked" :
|
||||
org->status & PVMOVE ? "pvmove" : "snapshot");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lp->zero)
|
||||
log_error("WARNING: \"%s\" not zeroed", lv->name);
|
||||
else if (!zero_lv(cmd, lv)) {
|
||||
log_error("Aborting. Failed to wipe snapshot "
|
||||
"exception store.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Couldn't deactivate LV %s.", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_add_snapshot(lv->vg->fid, NULL, org, lv, NULL, org->le_count,
|
||||
lp->chunk_size)) {
|
||||
log_error("Couldn't create snapshot.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* store vg on disk(s) */
|
||||
if (!vg_write(lv->vg))
|
||||
return_0;
|
||||
|
||||
backup(lv->vg);
|
||||
|
||||
if (!suspend_lv(cmd, org)) {
|
||||
log_error("Failed to suspend origin %s", org->name);
|
||||
vg_revert(lv->vg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_commit(lv->vg))
|
||||
return_0;
|
||||
|
||||
if (!resume_lv(cmd, org)) {
|
||||
log_error("Problem reactivating origin %s", org->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print("Logical volume %s converted to snapshot.", lv->name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
@@ -267,6 +440,11 @@ static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
return ECMD_FAILED;
|
||||
if (!lvconvert_mirrors(cmd, lv, lp))
|
||||
return ECMD_FAILED;
|
||||
} else if (lp->snapshot) {
|
||||
if (!archive(lv->vg))
|
||||
return ECMD_FAILED;
|
||||
if (!lvconvert_snapshot(cmd, lv, lp))
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
@@ -274,8 +452,6 @@ static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
int lvconvert(struct cmd_context * cmd, int argc, char **argv)
|
||||
{
|
||||
const char *vg_name;
|
||||
char *st;
|
||||
int consistent = 1;
|
||||
struct volume_group *vg;
|
||||
struct lv_list *lvl;
|
||||
@@ -287,41 +463,31 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
vg_name = extract_vgname(cmd, lp.lv_name);
|
||||
log_verbose("Checking for existing volume group \"%s\"", lp.vg_name);
|
||||
|
||||
if (!validate_name(vg_name)) {
|
||||
log_error("Please provide a valid volume group name");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if ((st = strrchr(lp.lv_name, '/')))
|
||||
lp.lv_name = st + 1;
|
||||
|
||||
log_verbose("Checking for existing volume group \"%s\"", vg_name);
|
||||
|
||||
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
|
||||
log_error("Can't get lock for %s", vg_name);
|
||||
if (!lock_vol(cmd, lp.vg_name, LCK_VG_WRITE)) {
|
||||
log_error("Can't get lock for %s", lp.vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, vg_name, &consistent))) {
|
||||
log_error("Volume group \"%s\" doesn't exist", vg_name);
|
||||
if (!(vg = vg_read(cmd, lp.vg_name, NULL, &consistent))) {
|
||||
log_error("Volume group \"%s\" doesn't exist", lp.vg_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (vg->status & EXPORTED_VG) {
|
||||
log_error("Volume group \"%s\" is exported", vg_name);
|
||||
log_error("Volume group \"%s\" is exported", lp.vg_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(vg->status & LVM_WRITE)) {
|
||||
log_error("Volume group \"%s\" is read-only", vg_name);
|
||||
log_error("Volume group \"%s\" is read-only", lp.vg_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(lvl = find_lv_in_vg(vg, lp.lv_name))) {
|
||||
log_error("Logical volume \"%s\" not found in "
|
||||
"volume group \"%s\"", lp.lv_name, vg_name);
|
||||
"volume group \"%s\"", lp.lv_name, lp.vg_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -337,6 +503,6 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
|
||||
ret = lvconvert_single(cmd, lvl->lv, &lp);
|
||||
|
||||
error:
|
||||
unlock_vg(cmd, vg_name);
|
||||
unlock_vg(cmd, lp.vg_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
/* does VG exist? */
|
||||
log_verbose("Finding volume group \"%s\"", lp->vg_name);
|
||||
|
||||
if (!(vg = vg_read(cmd, lp->vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(cmd, lp->vg_name, NULL, &consistent))) {
|
||||
log_error("Volume group \"%s\" doesn't exist", lp->vg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
static int _lvdisplay_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV) &&
|
||||
!(lv_is_cow(lv)))
|
||||
if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
if (arg_count(cmd, colon_ARG))
|
||||
|
||||
@@ -83,7 +83,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
}
|
||||
|
||||
if (lv_is_cow(lv)) {
|
||||
origin = find_cow(lv)->origin;
|
||||
origin = origin_from_cow(lv);
|
||||
log_verbose("Removing snapshot %s", lv->name);
|
||||
if (!vg_remove_snapshot(lv)) {
|
||||
stack;
|
||||
|
||||
@@ -106,7 +106,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) {
|
||||
log_error("Volume group \"%s\" doesn't exist", vg_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -116,7 +116,6 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *snap_seg;
|
||||
struct lvinfo info;
|
||||
uint32_t stripesize_extents = 0;
|
||||
uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
|
||||
@@ -134,7 +133,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
|
||||
char size_buf[SIZE_BUF];
|
||||
char lv_path[PATH_MAX];
|
||||
|
||||
if (!(vg = vg_read(cmd, lp->vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(cmd, lp->vg_name, NULL, &consistent))) {
|
||||
log_error("Volume group %s doesn't exist", lp->vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
@@ -521,8 +520,8 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
|
||||
backup(vg);
|
||||
|
||||
/* If snapshot, must suspend all associated devices */
|
||||
if ((snap_seg = find_cow(lv)))
|
||||
lock_lv = snap_seg->origin;
|
||||
if (lv_is_cow(lv))
|
||||
lock_lv = origin_from_cow(lv);
|
||||
else
|
||||
lock_lv = lv;
|
||||
|
||||
|
||||
@@ -27,9 +27,7 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
const char *active_str, *snapshot_str;
|
||||
|
||||
/* FIXME Avoid snapshot special-case */
|
||||
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV) &&
|
||||
!(lv_is_cow(lv)))
|
||||
if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
inkernel = lv_info(cmd, lv, &info, 1) && info.exists;
|
||||
@@ -43,10 +41,9 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
snap_active = 0;
|
||||
}
|
||||
snap_seg = NULL;
|
||||
} else if ((snap_seg = find_cow(lv))) {
|
||||
} else if (lv_is_cow(lv)) {
|
||||
if (inkernel &&
|
||||
(snap_active = lv_snapshot_percent(snap_seg->cow,
|
||||
&snap_percent)))
|
||||
(snap_active = lv_snapshot_percent(lv, &snap_percent)))
|
||||
if (snap_percent < 0 || snap_percent >= 100)
|
||||
snap_active = 0;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(cmd, pv->vg_name, NULL, &consistent))) {
|
||||
unlock_vg(cmd, pv->vg_name);
|
||||
log_error("Unable to find volume group of \"%s\"",
|
||||
pv_name);
|
||||
|
||||
@@ -62,7 +62,7 @@ static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, vgname, &consistent)) || !consistent) {
|
||||
if (!(vg = vg_read(cmd, vgname, NULL, &consistent)) || !consistent) {
|
||||
log_error("Volume group \"%s\" doesn't exist", vgname);
|
||||
unlock_vg(cmd, vgname);
|
||||
return NULL;
|
||||
|
||||
@@ -33,9 +33,14 @@ static int pvremove_check(struct cmd_context *cmd, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* is there a pv here already */
|
||||
if (!(pv = pv_read(cmd, name, NULL, NULL, 1)))
|
||||
return 1;
|
||||
/* Is there a pv here already? */
|
||||
/* If not, this is an error unless you used -f. */
|
||||
if (!(pv = pv_read(cmd, name, NULL, NULL, 1))) {
|
||||
if (arg_count(cmd, force_ARG))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* orphan ? */
|
||||
if (!pv->vg_name[0])
|
||||
|
||||
@@ -70,7 +70,7 @@ static int _pvresize_single(struct cmd_context *cmd,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) {
|
||||
unlock_vg(cmd, vg_name);
|
||||
log_error("Unable to find volume group of \"%s\"",
|
||||
pv_name);
|
||||
|
||||
@@ -35,9 +35,7 @@ static int _vgs_single(struct cmd_context *cmd, const char *vg_name,
|
||||
static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
/* FIXME Avoid snapshot special-case */
|
||||
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV) &&
|
||||
!(lv_is_cow(lv)))
|
||||
if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL))
|
||||
@@ -67,7 +65,7 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(cmd, pv->vg_name, NULL, &consistent))) {
|
||||
log_error("Can't read %s: skipping", pv->vg_name);
|
||||
unlock_vg(cmd, pv->vg_name);
|
||||
return ECMD_FAILED;
|
||||
@@ -83,9 +81,7 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
/* FIXME Avoid snapshot special-case */
|
||||
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV) &&
|
||||
!(lv_is_cow(lv)))
|
||||
if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
return process_each_segment_in_lv(cmd, lv, handle, _segs_single);
|
||||
@@ -110,7 +106,7 @@ static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(cmd, pv->vg_name, (char *)&pv->vgid, &consistent))) {
|
||||
log_error("Can't read %s: skipping", pv->vg_name);
|
||||
unlock_vg(cmd, pv->vg_name);
|
||||
return ECMD_FAILED;
|
||||
|
||||
@@ -241,7 +241,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
|
||||
consistent = 1;
|
||||
else
|
||||
consistent = 0;
|
||||
if (!(vg = vg_read(cmd, vgname, &consistent)) || !consistent) {
|
||||
if (!(vg = vg_read(cmd, vgname, NULL, &consistent)) || !consistent) {
|
||||
unlock_vg(cmd, vgname);
|
||||
if (!vg)
|
||||
log_error("Volume group \"%s\" "
|
||||
@@ -250,7 +250,6 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
|
||||
log_error("Volume group \"%s\" "
|
||||
"inconsistent", vgname);
|
||||
if (!vg || !(vg = recover_vg(cmd, vgname, lock_type))) {
|
||||
unlock_vg(cmd, vgname);
|
||||
if (ret_max < ECMD_FAILED)
|
||||
ret_max = ECMD_FAILED;
|
||||
continue;
|
||||
@@ -332,6 +331,7 @@ int process_each_segment_in_lv(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
|
||||
const char *vgid,
|
||||
struct list *tags, struct list *arg_vgnames,
|
||||
int lock_type, int consistent, void *handle,
|
||||
int ret_max,
|
||||
@@ -349,7 +349,7 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
|
||||
}
|
||||
|
||||
log_verbose("Finding volume group \"%s\"", vg_name);
|
||||
vg = vg_read(cmd, vg_name, &consistent);
|
||||
vg = vg_read(cmd, vg_name, vgid, &consistent);
|
||||
|
||||
if (!list_empty(tags)) {
|
||||
/* Only process if a tag matches or it's on arg_vgnames */
|
||||
@@ -381,10 +381,10 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
|
||||
int ret_max = 0;
|
||||
|
||||
struct str_list *sl;
|
||||
struct list *vgnames;
|
||||
struct list *vgnames, *vgids;
|
||||
struct list arg_vgnames, tags;
|
||||
|
||||
const char *vg_name;
|
||||
const char *vg_name, *vgid;
|
||||
char *dev_dir = cmd->dev_dir;
|
||||
|
||||
list_init(&tags);
|
||||
@@ -434,19 +434,30 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
|
||||
|
||||
if (!argc || !list_empty(&tags)) {
|
||||
log_verbose("Finding all volume groups");
|
||||
if (!(vgnames = get_vgs(cmd, 0)) || list_empty(vgnames)) {
|
||||
if (!(vgids = get_vgids(cmd, 0)) || list_empty(vgids)) {
|
||||
log_error("No volume groups found");
|
||||
return ret_max;
|
||||
}
|
||||
}
|
||||
|
||||
list_iterate_items(sl, vgnames) {
|
||||
vg_name = sl->str;
|
||||
if (!vg_name || !*vg_name)
|
||||
continue; /* FIXME Unnecessary? */
|
||||
ret_max = _process_one_vg(cmd, vg_name, &tags, &arg_vgnames,
|
||||
lock_type, consistent, handle,
|
||||
ret_max, process_single);
|
||||
list_iterate_items(sl, vgids) {
|
||||
vgid = sl->str;
|
||||
if (!vgid || !(vg_name = vgname_from_vgid(cmd->mem, vgid)) ||
|
||||
!*vg_name)
|
||||
continue;
|
||||
ret_max = _process_one_vg(cmd, vg_name, vgid, &tags,
|
||||
&arg_vgnames,
|
||||
lock_type, consistent, handle,
|
||||
ret_max, process_single);
|
||||
}
|
||||
} else {
|
||||
list_iterate_items(sl, vgnames) {
|
||||
vg_name = sl->str;
|
||||
if (!vg_name || !*vg_name)
|
||||
continue; /* FIXME Unnecessary? */
|
||||
ret_max = _process_one_vg(cmd, vg_name, NULL, &tags,
|
||||
&arg_vgnames,
|
||||
lock_type, consistent, handle,
|
||||
ret_max, process_single);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_max;
|
||||
@@ -582,7 +593,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
|
||||
if (!list_empty(&tags) && (vgnames = get_vgs(cmd, 0)) &&
|
||||
!list_empty(vgnames)) {
|
||||
list_iterate_items(sll, vgnames) {
|
||||
vg = vg_read(cmd, sll->str, &consistent);
|
||||
vg = vg_read(cmd, sll->str, NULL, &consistent);
|
||||
if (!consistent)
|
||||
continue;
|
||||
ret = process_each_pv_in_vg(cmd, vg, &tags,
|
||||
@@ -967,7 +978,7 @@ struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vg_read(cmd, vgname, &consistent);
|
||||
return vg_read(cmd, vgname, NULL, &consistent);
|
||||
}
|
||||
|
||||
int apply_lvname_restrictions(const char *name)
|
||||
@@ -1046,7 +1057,7 @@ int zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
* <clausen> also, more than 4k
|
||||
* <clausen> say, reiserfs puts it's superblock 32k in, IIRC
|
||||
* <ejt_> k, I'll drop a fixme to that effect
|
||||
* (I know the device is at least 4k, but not 32k)
|
||||
* (I know the device is at least 4k, but not 32k)
|
||||
*/
|
||||
if (!(name = dm_pool_alloc(cmd->mem, PATH_MAX))) {
|
||||
log_error("Name allocation failed - device not zeroed");
|
||||
|
||||
@@ -198,7 +198,7 @@ static int _vgchange_clustered(struct cmd_context *cmd,
|
||||
|
||||
if (clustered) {
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lvl->lv->origin_count || lvl->lv->snapshot) {
|
||||
if (lv_is_origin(lvl->lv) || lv_is_cow(lvl->lv)) {
|
||||
log_error("Volume group %s contains snapshots "
|
||||
"that are not yet supported.",
|
||||
vg->name);
|
||||
|
||||
@@ -19,6 +19,9 @@ static int vgexport_single(struct cmd_context *cmd, const char *vg_name,
|
||||
struct volume_group *vg, int consistent,
|
||||
void *handle)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
struct physical_volume *pv;
|
||||
|
||||
if (!vg) {
|
||||
log_error("Unable to find volume group \"%s\"", vg_name);
|
||||
goto error;
|
||||
@@ -50,6 +53,11 @@ static int vgexport_single(struct cmd_context *cmd, const char *vg_name,
|
||||
|
||||
vg->status |= EXPORTED_VG;
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
pv = pvl->pv;
|
||||
pv->status |= EXPORTED_VG;
|
||||
}
|
||||
|
||||
if (!vg_write(vg) || !vg_commit(vg))
|
||||
goto error;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, vg_name, &consistent)) || !consistent) {
|
||||
if (!(vg = vg_read(cmd, vg_name, NULL, &consistent)) || !consistent) {
|
||||
log_error("Volume group \"%s\" not found.", vg_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ static int vgimport_single(struct cmd_context *cmd, const char *vg_name,
|
||||
struct volume_group *vg, int consistent,
|
||||
void *handle)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
struct physical_volume *pv;
|
||||
|
||||
if (!vg || !consistent) {
|
||||
log_error("Unable to find exported volume group \"%s\"",
|
||||
vg_name);
|
||||
@@ -40,6 +43,11 @@ static int vgimport_single(struct cmd_context *cmd, const char *vg_name,
|
||||
|
||||
vg->status &= ~EXPORTED_VG;
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
pv = pvl->pv;
|
||||
pv->status &= ~EXPORTED_VG;
|
||||
}
|
||||
|
||||
if (!vg_write(vg) || !vg_commit(vg))
|
||||
goto error;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg_to = vg_read(cmd, vg_name_to, &consistent)) || !consistent) {
|
||||
if (!(vg_to = vg_read(cmd, vg_name_to, NULL, &consistent)) || !consistent) {
|
||||
log_error("Volume group \"%s\" doesn't exist", vg_name_to);
|
||||
unlock_vg(cmd, vg_name_to);
|
||||
return ECMD_FAILED;
|
||||
@@ -61,7 +61,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
|
||||
}
|
||||
|
||||
consistent = 1;
|
||||
if (!(vg_from = vg_read(cmd, vg_name_from, &consistent)) || !consistent) {
|
||||
if (!(vg_from = vg_read(cmd, vg_name_from, NULL, &consistent)) || !consistent) {
|
||||
log_error("Volume group \"%s\" doesn't exist", vg_name_from);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -432,7 +432,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if ((!(vg = vg_read(cmd, vg_name, &consistent)) || !consistent) &&
|
||||
if ((!(vg = vg_read(cmd, vg_name, NULL, &consistent)) || !consistent) &&
|
||||
!arg_count(cmd, removemissing_ARG)) {
|
||||
log_error("Volume group \"%s\" doesn't exist", vg_name);
|
||||
unlock_vg(cmd, vg_name);
|
||||
@@ -449,7 +449,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
init_partial(1);
|
||||
consistent = 0;
|
||||
if (!(vg = vg_read(cmd, vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) {
|
||||
log_error("Volume group \"%s\" not found", vg_name);
|
||||
unlock_vg(cmd, vg_name);
|
||||
return ECMD_FAILED;
|
||||
|
||||
@@ -19,12 +19,15 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
char *dev_dir;
|
||||
unsigned int length;
|
||||
struct id id;
|
||||
int consistent = 1;
|
||||
|
||||
char *vg_name_old, *vg_name_new;
|
||||
|
||||
int match = 0;
|
||||
int found_id = 0;
|
||||
struct list *vgids;
|
||||
struct str_list *sl;
|
||||
char *vg_name_new;
|
||||
const char *vgid = NULL, *vg_name, *vg_name_old;
|
||||
char old_path[NAME_LEN], new_path[NAME_LEN];
|
||||
|
||||
struct volume_group *vg_old, *vg_new;
|
||||
|
||||
if (argc != 2) {
|
||||
@@ -64,22 +67,49 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
log_verbose("Checking for existing volume group \"%s\"", vg_name_old);
|
||||
|
||||
/* Avoid duplicates */
|
||||
if (!(vgids = get_vgids(cmd, 0)) || list_empty(vgids)) {
|
||||
log_error("No complete volume groups found");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
list_iterate_items(sl, vgids) {
|
||||
vgid = sl->str;
|
||||
if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid)) || !*vg_name)
|
||||
continue;
|
||||
if (!strcmp(vg_name, vg_name_old)) {
|
||||
if (match) {
|
||||
log_error("Found more than one VG called %s. "
|
||||
"Please supply VG uuid.", vg_name_old);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
match = 1;
|
||||
}
|
||||
}
|
||||
|
||||
log_suppress(2);
|
||||
found_id = id_read_format(&id, vg_name_old);
|
||||
log_suppress(0);
|
||||
if (found_id && (vg_name = vgname_from_vgid(cmd->mem, id.uuid))) {
|
||||
vg_name_old = vg_name;
|
||||
vgid = id.uuid;
|
||||
} else
|
||||
vgid = NULL;
|
||||
|
||||
if (!lock_vol(cmd, vg_name_old, LCK_VG_WRITE)) {
|
||||
log_error("Can't get lock for %s", vg_name_old);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg_old = vg_read(cmd, vg_name_old, &consistent)) || !consistent) {
|
||||
log_error("Volume group \"%s\" doesn't exist", vg_name_old);
|
||||
if (!(vg_old = vg_read(cmd, vg_name_old, vgid, &consistent)) || !consistent) {
|
||||
log_error("Volume group %s %s%s%snot found.", vg_name_old,
|
||||
vgid ? "(" : "", vgid ? vgid : "", vgid ? ") " : "");
|
||||
unlock_vg(cmd, vg_name_old);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (vg_old->status & EXPORTED_VG) {
|
||||
unlock_vg(cmd, vg_name_old);
|
||||
log_error("Volume group \"%s\" is exported", vg_old->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
if (vg_old->status & EXPORTED_VG)
|
||||
log_info("Volume group \"%s\" is exported", vg_old->name);
|
||||
|
||||
if (!(vg_old->status & LVM_WRITE)) {
|
||||
unlock_vg(cmd, vg_name_old);
|
||||
@@ -104,7 +134,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
consistent = 0;
|
||||
if ((vg_new = vg_read(cmd, vg_name_new, &consistent))) {
|
||||
if ((vg_new = vg_read(cmd, vg_name_new, NULL, &consistent))) {
|
||||
log_error("New volume group \"%s\" already exists",
|
||||
vg_name_new);
|
||||
goto error;
|
||||
@@ -146,6 +176,10 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
|
||||
log_print("Volume group \"%s\" successfully renamed to \"%s\"",
|
||||
vg_name_old, vg_name_new);
|
||||
|
||||
/* FIXME lvmcache corruption - vginfo duplicated instead of renamed */
|
||||
persistent_filter_wipe(cmd->filter);
|
||||
lvmcache_destroy();
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
error:
|
||||
|
||||
@@ -190,7 +190,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg_from = vg_read(cmd, vg_name_from, &consistent)) || !consistent) {
|
||||
if (!(vg_from = vg_read(cmd, vg_name_from, NULL, &consistent)) || !consistent) {
|
||||
log_error("Volume group \"%s\" doesn't exist", vg_name_from);
|
||||
unlock_vg(cmd, vg_name_from);
|
||||
return ECMD_FAILED;
|
||||
@@ -216,7 +216,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
consistent = 0;
|
||||
if ((vg_to = vg_read(cmd, vg_name_to, &consistent))) {
|
||||
if ((vg_to = vg_read(cmd, vg_name_to, NULL, &consistent))) {
|
||||
/* FIXME Remove this restriction */
|
||||
log_error("Volume group \"%s\" already exists", vg_name_to);
|
||||
goto error;
|
||||
@@ -287,7 +287,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
/* Remove EXPORTED flag from new VG */
|
||||
consistent = 1;
|
||||
if (!(vg_to = vg_read(cmd, vg_name_to, &consistent)) || !consistent) {
|
||||
if (!(vg_to = vg_read(cmd, vg_name_to, NULL, &consistent)) || !consistent) {
|
||||
log_error("Volume group \"%s\" became inconsistent: please "
|
||||
"fix manually", vg_name_to);
|
||||
goto error;
|
||||
|
||||
Reference in New Issue
Block a user