1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-12-29 06:57:46 +03:00

Compare commits

...

45 Commits

Author SHA1 Message Date
Alasdair Kergon
dd2a3f40e1 pre-release 2007-06-15 19:05:02 +00:00
Alasdair Kergon
78f76c1690 Fix default dmsetup report buffering and add --unbuffered.
Add tree-based and dependency fields to dmsetup reports.
2007-06-15 18:20:28 +00:00
Dave Wysochanski
4788066a5f Update vgcfgrestore man pg 2007-06-15 16:05:57 +00:00
Petr Rockai
10e4254e7d Allow keyboard interrupts in yes_no_prompt(). Add code to toollib.c
loops and to pvcreate.c, lvchange.c and lvresize.c to handle
interrupted prompts.
2007-06-15 10:11:14 +00:00
Dave Wysochanski
0106e4df9d Fix inverted logic on last checkin for pvremove 2007-06-14 15:51:36 +00:00
Dave Wysochanski
8ac718a3a2 convert pv->vg_name[0] to \!is_orphan(pv) 2007-06-14 15:48:05 +00:00
Dave Wysochanski
46d45273a1 Convert pv->vg_name to get_pv_vg_name 2007-06-14 15:25:36 +00:00
Patrick Caulfield
8da9ec3599 Remove system-lv.[ch] 2007-06-14 10:17:12 +00:00
Patrick Caulfield
01fdf84d69 Remove system LV code from clvmd. It's never been used and never should be
used! It's removal tidies a number of code paths inside clvmd.
2007-06-14 10:16:35 +00:00
Dave Wysochanski
cc78386e75 Update WHATS_NEW for get_pv* conversions 2007-06-13 23:57:15 +00:00
Dave Wysochanski
3755157c61 Convert pv->vg_name to get_pv_vg_name 2007-06-13 23:53:38 +00:00
Dave Wysochanski
80f8436f0a Convert pv->status to get_pv_status 2007-06-13 23:33:45 +00:00
Dave Wysochanski
f88a4b7760 Convert pv->dev to get_pv_dev 2007-06-13 23:29:33 +00:00
Dave Wysochanski
de229b8ab0 Convert pv->size to get_pv_size 2007-06-13 23:02:51 +00:00
Dave Wysochanski
a3ba37e45e Convert existing_pv dereferences to get_pv_* 2007-06-13 22:58:32 +00:00
Dave Wysochanski
50c779b3c6 Convert pv->pe_size to get_pv_pe_size 2007-06-13 22:30:26 +00:00
Dave Wysochanski
192372e1c3 Convert pv->pe_start to get_pv_pe_start 2007-06-13 22:16:27 +00:00
Dave Wysochanski
f88fd88c38 Convert pv->pe_count to get_pv_pe_count 2007-06-13 22:11:29 +00:00
Dave Wysochanski
6e15145af1 Convert pv->pe_alloc_count to get_pv_pe_alloc_count 2007-06-13 22:04:45 +00:00
Dave Wysochanski
4b5fad4e48 Remove casts in pv_create and find_pv_in_vg_by_uuid 2007-06-13 21:14:07 +00:00
Dave Wysochanski
7a13e71c80 Convert pv_handle_t to pv_t * and tidy up whitespace 2007-06-13 20:55:56 +00:00
Dave Wysochanski
3c10943900 Add typedef pv_handle_t 2007-06-13 19:52:48 +00:00
Dave Wysochanski
696b8811c2 Fix a couple benign warnings by adding variable initializations. 2007-06-13 15:11:19 +00:00
Dave Wysochanski
9fd2c8602a Convert find_pv_in_vg_by_uuid and pv_create to use PV handles 2007-06-12 22:41:27 +00:00
Dave Wysochanski
a3636a5af4 Change PV_HANDLE_DEREF to pv_field and add paren's 2007-06-12 21:39:49 +00:00
Dave Wysochanski
f2e5f07718 Add get_pv_* functions to return PV fields in prep for external LVM library 2007-06-12 21:20:20 +00:00
Dave Wysochanski
16c6fdde60 Add wrappers to functions related to pv commands in preparation for exported LVM lib 2007-06-11 18:29:30 +00:00
Alasdair Kergon
2155c93426 Add capability for tree-based fields to dmsetup reports. 2007-06-11 13:20:29 +00:00
Bryn M. Reeves
c394631e4c Allow vgcfgrestore to list metadata backup files using -f 2007-06-08 22:38:48 +00:00
Dave Wysochanski
8b370b7cc1 Add vg_check_status to consolidate vg status flags checks and error messages. 2007-06-06 19:40:28 +00:00
Dave Wysochanski
607db9971c make code consistent with pvresize code - good candidate for common code cleanup 2007-06-05 18:23:17 +00:00
Dave Wysochanski
6768f64e2f Fix pvdisplay --maps to not display segment header for orphan PVs. 2007-05-31 20:26:11 +00:00
Dave Wysochanski
f1813b1cc6 Fix redundant segment display when PV is given to 'pvdisplay --maps' cmdline. 2007-05-31 20:10:25 +00:00
Dave Wysochanski
fb665bd0dd Remove 'Type' from pvdisplay --maps as there is no 'Type' of a physical segment, only logical segments 2007-05-31 15:18:44 +00:00
Dave Wysochanski
65dda2ef3d Small fixes to pvdisplay --maps: 1) rename struct pv_segment vars from 'seg' to 'pvseg', 2) Change heading 2007-05-31 14:19:57 +00:00
Dave Wysochanski
b162b992af Add --maps to pvdisplay.
Modified original patch from David Robinson <zxvdr.au@gmail.com>.
2007-05-30 20:43:09 +00:00
Dave Wysochanski
67a3a3d130 Fix vgcfgrestore man pg to show mandatory VG name and remove LVM1 options. 2007-05-22 02:52:57 +00:00
Dave Wysochanski
92cd9bf7d2 Fix vgrename man page to include UUID and be more consistent with lvrename. 2007-05-22 02:51:33 +00:00
Patrick Caulfield
bf97034485 Add *Experimental* OpenAIS support to clvmd. 2007-05-21 10:52:01 +00:00
Milan Broz
1ded1fc509 Remove symlinks if parent volume is deactivated. 2007-05-15 14:42:01 +00:00
Milan Broz
e0592c58b3 Fix and clarify vgsplit error messages. 2007-05-15 13:01:41 +00:00
Milan Broz
5ead2706b4 Fix a segfault if a device has no target (no table) 2007-05-14 11:27:34 +00:00
Patrick Caulfield
52ada4853c Misc clvmd cleanups from Jim Meyering 2007-05-02 12:22:40 +00:00
Patrick Caulfield
c2b27a8298 Add some more debuglogs to clvmd startup. 2007-05-02 08:23:36 +00:00
Alasdair Kergon
3934c1d437 post-release 2007-04-27 20:58:45 +00:00
54 changed files with 2034 additions and 1049 deletions

View File

@@ -1 +1 @@
2.02.25-cvs (2007-04 27)
2.02.26-cvs (2007-06-15)

View File

@@ -1,3 +1,25 @@
Version 2.02.26 - 15th June 2007
================================
Update vgcfgrestore man page.
Allow keyboard interrupt during user prompts when appropriate.
Remove unused clvmd system-lv code.
Replace many physical_volume struct dereferences with new get_pv_* functions.
Suppress a benign compile-time warning.
Convert find_pv_in_vg_by_uuid and pv_create to use PV handles.
Add wrappers to some functions in preparation for external LVM library.
Add -f to vgcfgrestore to list metadata backup files.
Add vg_check_status to consolidate vg status checks and error messages.
Add pvdisplay --maps implementation.
Remove unsupported LVM1 options from vgcfgrestore man page.
Update vgcfgrestore man page to show mandatory VG name.
Update vgrename man page to include UUID and be consistent with lvrename.
Add (experimental) OpenAIS support to clvmd.
Fix deactivation code to follow dependencies and remove symlinks.
Fix and clarify vgsplit error messages.
Fix a segfault in device_is_usable() if a device has no table.
Add some more debug messages to clvmd startup.
Misc clvmd cleanups.
Version 2.02.25 - 27th April 2007
=================================
Fix get_config_uint64() to read a 64-bit value not a 32-bit one.

View File

@@ -1,3 +1,8 @@
Version 1.02.20 - 15th June 2007
================================
Fix default dmsetup report buffering and add --unbuffered.
Add tree-based and dependency fields to dmsetup reports.
Version 1.02.19 - 27th April 2007
=================================
Standardise protective include file #defines.

View File

@@ -19,8 +19,7 @@ SOURCES = \
clvmd-command.c \
clvmd.c \
lvm-functions.c \
refresh_clvmd.c \
system-lv.c
refresh_clvmd.c
ifeq ("@CLVMD@", "gulm")
GULM = yes
@@ -30,9 +29,16 @@ ifeq ("@CLVMD@", "cman")
CMAN = yes
endif
ifeq ("@CLVMD@", "openais")
OPENAIS = yes
GULM = no
CMAN = no
endif
ifeq ("@CLVMD@", "all")
GULM = yes
CMAN = yes
OPENAIS = no
endif
ifeq ("@DEBUG@", "yes")
@@ -51,6 +57,12 @@ ifeq ("$(CMAN)", "yes")
DEFS += -DUSE_CMAN
endif
ifeq ("$(OPENAIS)", "yes")
SOURCES += clvmd-openais.c
LMLIBS += -lSaLck -lSaClm -lcpg
DEFS += -DUSE_OPENAIS
endif
TARGETS = \
clvmd

View File

@@ -58,7 +58,7 @@ 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 nodeid_from_csid(const 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,
@@ -78,6 +78,7 @@ static int _init_cluster(void)
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
return -1;
}
DEBUGLOG("Connected to CMAN\n");
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
syslog(LOG_ERR, "Can't bind cluster socket: %m");
@@ -93,6 +94,8 @@ static int _init_cluster(void)
get_members();
count_clvmds_running();
DEBUGLOG("CMAN initialisation complete\n");
/* Create a lockspace for LV & VG locks to live in */
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
if (!lockspace) {
@@ -100,7 +103,7 @@ static int _init_cluster(void)
return -1;
}
dlm_ls_pthread_init(lockspace);
DEBUGLOG("DLM initialisation complete\n");
return 0;
}
@@ -128,7 +131,8 @@ static int _get_num_nodes()
}
/* send_message with the fd check removed */
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
const char *errtext)
{
int nodeid = 0;
@@ -137,7 +141,7 @@ static int _cluster_send_message(void *buf, int msglen, char *csid, const char *
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
{
log_error(errtext);
log_error("%s", errtext);
}
return msglen;
}
@@ -152,7 +156,8 @@ static void _get_our_csid(char *csid)
/* 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 *,
void (*callback) (struct local_client *,
const char *,
int))
{
int i;
@@ -205,7 +210,8 @@ static void event_callback(cman_handle_t handle, void *private, int reason, int
}
static struct local_client *cman_client;
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client)
{
@@ -228,7 +234,7 @@ static void data_callback(cman_handle_t handle, void *private,
process_message(cman_client, buf, len, (char *)&nodeid);
}
static void _add_up_node(char *csid)
static void _add_up_node(const char *csid)
{
/* It's up ! */
int nodeid = nodeid_from_csid(csid);
@@ -320,17 +326,16 @@ static void get_members()
}
if (node_updown == NULL) {
node_updown =
(int *) malloc(sizeof(int) *
max(num_nodes, max_updown_nodes));
memset(node_updown, 0,
sizeof(int) * max(num_nodes, max_updown_nodes));
size_t buf_len = sizeof(int) * max(num_nodes, max_updown_nodes);
node_updown = malloc(buf_len);
if (node_updown)
memset(node_updown, 0, buf_len);
}
}
/* Convert a node name to a CSID */
static int _csid_from_name(char *csid, char *name)
static int _csid_from_name(char *csid, const char *name)
{
int i;
@@ -344,7 +349,7 @@ static int _csid_from_name(char *csid, char *name)
}
/* Convert a CSID to a node name */
static int _name_from_csid(char *csid, char *name)
static int _name_from_csid(const char *csid, char *name)
{
int i;
@@ -376,7 +381,7 @@ static int name_from_nodeid(int nodeid, char *name)
}
/* Convert a CSID to a node ID */
static int nodeid_from_csid(char *csid)
static int nodeid_from_csid(const char *csid)
{
int nodeid;

View File

@@ -95,13 +95,22 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
/* Just a test message */
case CLVMD_CMD_TEST:
if (arglen > buflen) {
char *new_buf;
buflen = arglen + 200;
*buf = realloc(*buf, buflen);
new_buf = realloc(*buf, buflen);
if (new_buf == NULL) {
status = errno;
free (*buf);
}
*buf = new_buf;
}
if (*buf) {
uname(&nodeinfo);
*retlen = 1 + snprintf(*buf, buflen,
"TEST from %s: %s v%s",
nodeinfo.nodename, args,
nodeinfo.release);
}
uname(&nodeinfo);
*retlen = 1 + snprintf(*buf, buflen, "TEST from %s: %s v%s",
nodeinfo.nodename, args,
nodeinfo.release);
break;
case CLVMD_CMD_LOCK_VG:
@@ -118,7 +127,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
/* Replace EIO with something less scary */
if (status == EIO) {
*retlen =
1 + snprintf(*buf, buflen,
1 + snprintf(*buf, buflen, "%s",
get_last_lvm_error());
return EIO;
}
@@ -131,7 +140,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
case CLVMD_CMD_GET_CLUSTERNAME:
status = clops->get_cluster_name(*buf, buflen);
if (!status)
*retlen = strlen(*buf);
*retlen = strlen(*buf)+1;
break;
default:
@@ -141,7 +150,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
/* Check the status of the command and return the error text */
if (status) {
*retlen = 1 + snprintf(*buf, buflen, strerror(status));
*retlen = 1 + snprintf(*buf, buflen, "%s", strerror(status));
}
return status;

View File

@@ -25,27 +25,31 @@ struct local_client;
struct cluster_ops {
void (*cluster_init_completed) (void);
int (*cluster_send_message) (void *buf, int msglen, char *csid,
const char *errtext);
int (*name_from_csid) (char *csid, char *name);
int (*csid_from_name) (char *csid, char *name);
int (*cluster_send_message) (const void *buf, int msglen,
const char *csid,
const char *errtext);
int (*name_from_csid) (const char *csid, char *name);
int (*csid_from_name) (char *csid, const char *name);
int (*get_num_nodes) (void);
int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
char *csid, struct local_client **new_client);
const char *csid,
struct local_client **new_client);
int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */
int (*cluster_do_node_callback) (struct local_client *client,
void (*callback) (struct local_client *,
char *csid, int node_up));
void (*callback) (struct local_client *,
const char *csid,
int node_up));
int (*is_quorate) (void);
void (*get_our_csid) (char *csid);
void (*add_up_node) (char *csid);
void (*add_up_node) (const char *csid);
void (*reread_config) (void);
void (*cluster_closedown) (void);
int (*get_cluster_name)(char *buf, int buflen);
int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
int (*sync_lock) (const char *resource, int mode,
int flags, int *lockid);
int (*sync_unlock) (const char *resource, int lockid);
};
@@ -71,6 +75,23 @@ struct cluster_ops *init_gulm_cluster(void);
struct cluster_ops *init_cman_cluster(void);
#endif
#ifdef USE_OPENAIS
# include <openais/saAis.h>
# include <openais/totem/totem.h>
# define OPENAIS_CSID_LEN (sizeof(int))
# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
# define MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
# endif
# ifndef CMAN_MAX_CLUSTER_MESSAGE
# define CMAN_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
# endif
# ifndef MAX_CSID_LEN
# define MAX_CSID_LEN sizeof(int)
# endif
struct cluster_ops *init_openais_cluster(void);
#endif
#endif

View File

@@ -0,0 +1,756 @@
/******************************************************************************
*******************************************************************************
**
** Copyright (C) 2007 Red Hat, Inc. All rights reserved.
**
*******************************************************************************
******************************************************************************/
/* This provides the interface between clvmd and OpenAIS as the cluster
* and lock manager.
*
*/
#include <pthread.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <utmpx.h>
#include <syslog.h>
#include <assert.h>
#include <libdevmapper.h>
#include <openais/saAis.h>
#include <openais/saLck.h>
#include <openais/saClm.h>
#include <openais/cpg.h>
#include "list.h"
#include "locking.h"
#include "log.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "lvm-functions.h"
#include "clvmd.h"
/* Timeout value for several openais calls */
#define TIMEOUT 10
static void lck_lock_callback(SaInvocationT invocation,
SaLckLockStatusT lockStatus,
SaAisErrorT error);
static void lck_unlock_callback(SaInvocationT invocation,
SaAisErrorT error);
static void cpg_deliver_callback (cpg_handle_t handle,
struct cpg_name *groupName,
uint32_t nodeid,
uint32_t pid,
void *msg,
int msg_len);
static void cpg_confchg_callback(cpg_handle_t handle,
struct cpg_name *groupName,
struct cpg_address *member_list, int member_list_entries,
struct cpg_address *left_list, int left_list_entries,
struct cpg_address *joined_list, int joined_list_entries);
static void _cluster_closedown(void);
/* Hash list of nodes in the cluster */
static struct dm_hash_table *node_hash;
/* For associating lock IDs & resource handles */
static struct dm_hash_table *lock_hash;
/* Number of active nodes */
static int num_nodes;
static unsigned int our_nodeid;
static struct local_client *cluster_client;
/* OpenAIS handles */
static cpg_handle_t cpg_handle;
static SaLckHandleT lck_handle;
static struct cpg_name cpg_group_name;
/* Openais callback structs */
cpg_callbacks_t cpg_callbacks = {
.cpg_deliver_fn = cpg_deliver_callback,
.cpg_confchg_fn = cpg_confchg_callback,
};
SaLckCallbacksT lck_callbacks = {
.saLckLockGrantCallback = lck_lock_callback,
.saLckResourceUnlockCallback = lck_unlock_callback
};
/* We only call Clm to get our node id */
SaClmCallbacksT clm_callbacks;
struct node_info
{
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
int nodeid;
};
struct lock_info
{
SaLckResourceHandleT res_handle;
SaLckLockIdT lock_id;
SaNameT lock_name;
};
struct lock_wait
{
pthread_cond_t cond;
pthread_mutex_t mutex;
int status;
};
/* Set errno to something approximating the right value and return 0 or -1 */
static int ais_to_errno(SaAisErrorT err)
{
switch(err)
{
case SA_AIS_OK:
return 0;
case SA_AIS_ERR_LIBRARY:
errno = EINVAL;
break;
case SA_AIS_ERR_VERSION:
errno = EINVAL;
break;
case SA_AIS_ERR_INIT:
errno = EINVAL;
break;
case SA_AIS_ERR_TIMEOUT:
errno = ETIME;
break;
case SA_AIS_ERR_TRY_AGAIN:
errno = EAGAIN;
break;
case SA_AIS_ERR_INVALID_PARAM:
errno = EINVAL;
break;
case SA_AIS_ERR_NO_MEMORY:
errno = ENOMEM;
break;
case SA_AIS_ERR_BAD_HANDLE:
errno = EINVAL;
break;
case SA_AIS_ERR_BUSY:
errno = EBUSY;
break;
case SA_AIS_ERR_ACCESS:
errno = EPERM;
break;
case SA_AIS_ERR_NOT_EXIST:
errno = ENOENT;
break;
case SA_AIS_ERR_NAME_TOO_LONG:
errno = ENAMETOOLONG;
break;
case SA_AIS_ERR_EXIST:
errno = EEXIST;
break;
case SA_AIS_ERR_NO_SPACE:
errno = ENOSPC;
break;
case SA_AIS_ERR_INTERRUPT:
errno = EINTR;
break;
case SA_AIS_ERR_NAME_NOT_FOUND:
errno = ENOENT;
break;
case SA_AIS_ERR_NO_RESOURCES:
errno = ENOMEM;
break;
case SA_AIS_ERR_NOT_SUPPORTED:
errno = EOPNOTSUPP;
break;
case SA_AIS_ERR_BAD_OPERATION:
errno = EINVAL;
break;
case SA_AIS_ERR_FAILED_OPERATION:
errno = EIO;
break;
case SA_AIS_ERR_MESSAGE_ERROR:
errno = EIO;
break;
case SA_AIS_ERR_QUEUE_FULL:
errno = EXFULL;
break;
case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
errno = EINVAL;
break;
case SA_AIS_ERR_BAD_FLAGS:
errno = EINVAL;
break;
case SA_AIS_ERR_TOO_BIG:
errno = E2BIG;
break;
case SA_AIS_ERR_NO_SECTIONS:
errno = ENOMEM;
break;
default:
errno = EINVAL;
break;
}
return -1;
}
static char *print_csid(const char *csid)
{
static char buf[128];
int id;
memcpy(&id, csid, sizeof(int));
sprintf(buf, "%d", id);
return buf;
}
static int add_internal_client(int fd, fd_callback_t callback)
{
struct local_client *client;
DEBUGLOG("Add_internal_client, fd = %d\n", fd);
client = malloc(sizeof(struct local_client));
if (!client)
{
DEBUGLOG("malloc failed\n");
return -1;
}
memset(client, 0, sizeof(struct local_client));
client->fd = fd;
client->type = CLUSTER_INTERNAL;
client->callback = callback;
add_client(client);
/* Set Close-on-exec */
fcntl(fd, F_SETFD, 1);
return 0;
}
static void cpg_deliver_callback (cpg_handle_t handle,
struct cpg_name *groupName,
uint32_t nodeid,
uint32_t pid,
void *msg,
int msg_len)
{
int target_nodeid;
memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
DEBUGLOG("Got message from nodeid %d for %d. len %d\n",
nodeid, target_nodeid, msg_len-4);
if (target_nodeid == our_nodeid)
process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
}
static void cpg_confchg_callback(cpg_handle_t handle,
struct cpg_name *groupName,
struct cpg_address *member_list, int member_list_entries,
struct cpg_address *left_list, int left_list_entries,
struct cpg_address *joined_list, int joined_list_entries)
{
int i;
struct node_info *ninfo;
DEBUGLOG("confchg callback. %d joined, %d left, %d members\n",
joined_list_entries, left_list_entries, member_list_entries);
for (i=0; i<joined_list_entries; i++) {
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&joined_list[i].nodeid,
OPENAIS_CSID_LEN);
if (!ninfo) {
ninfo = malloc(sizeof(struct node_info));
if (!ninfo) {
break;
}
else {
ninfo->nodeid = joined_list[i].nodeid;
dm_hash_insert_binary(node_hash,
(char *)&ninfo->nodeid,
OPENAIS_CSID_LEN, ninfo);
}
}
ninfo->state = NODE_CLVMD;
}
for (i=0; i<left_list_entries; i++) {
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&left_list[i].nodeid,
OPENAIS_CSID_LEN);
if (ninfo)
ninfo->state = NODE_DOWN;
}
num_nodes = joined_list_entries;
}
static void lck_lock_callback(SaInvocationT invocation,
SaLckLockStatusT lockStatus,
SaAisErrorT error)
{
struct lock_wait *lwait = (struct lock_wait *)(long)invocation;
DEBUGLOG("lck_lock_callback, error = %d\n", error);
lwait->status = error;
pthread_mutex_lock(&lwait->mutex);
pthread_cond_signal(&lwait->cond);
pthread_mutex_unlock(&lwait->mutex);
}
static void lck_unlock_callback(SaInvocationT invocation,
SaAisErrorT error)
{
struct lock_wait *lwait = (struct lock_wait *)(long)invocation;
DEBUGLOG("lck_unlock_callback\n");
lwait->status = SA_AIS_OK;
pthread_mutex_lock(&lwait->mutex);
pthread_cond_signal(&lwait->cond);
pthread_mutex_unlock(&lwait->mutex);
}
static int lck_dispatch(struct local_client *client, char *buf, int len,
const char *csid, struct local_client **new_client)
{
*new_client = NULL;
saLckDispatch(lck_handle, SA_DISPATCH_ONE);
return 1;
}
static int _init_cluster(void)
{
SaAisErrorT err;
SaVersionT ver = { 'B', 1, 1 };
SaClmHandleT clm_handle;
int select_fd;
SaClmClusterNodeT cluster_node;
node_hash = dm_hash_create(100);
lock_hash = dm_hash_create(10);
err = cpg_initialize(&cpg_handle,
&cpg_callbacks);
if (err != SA_AIS_OK) {
syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
err);
DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
return ais_to_errno(err);
}
err = saLckInitialize(&lck_handle,
&lck_callbacks,
&ver);
if (err != SA_AIS_OK) {
cpg_initialize(&cpg_handle, &cpg_callbacks);
syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
err);
DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
return ais_to_errno(err);
}
/* Connect to the clvmd group */
strcpy((char *)cpg_group_name.value, "clvmd");
cpg_group_name.length = strlen((char *)cpg_group_name.value);
err = cpg_join(cpg_handle, &cpg_group_name);
if (err != SA_AIS_OK) {
cpg_finalize(cpg_handle);
saLckFinalize(lck_handle);
syslog(LOG_ERR, "Cannot join clvmd process group");
DEBUGLOG("Cannot join clvmd process group\n");
return ais_to_errno(err);
}
/* A brief foray into Clm to get our node id */
err = saClmInitialize(&clm_handle, &clm_callbacks, &ver);
if (err != SA_AIS_OK) {
syslog(LOG_ERR, "Could not initialize OpenAIS membership service %d\n", err);
DEBUGLOG("Could not initialize OpenAIS Membership service %d\n", err);
return ais_to_errno(err);
}
err = saClmClusterNodeGet(clm_handle,
SA_CLM_LOCAL_NODE_ID,
TIMEOUT,
&cluster_node);
if (err != SA_AIS_OK) {
cpg_finalize(cpg_handle);
saLckFinalize(lck_handle);
saClmFinalize(clm_handle);
syslog(LOG_ERR, "Cannot get local node id\n");
return ais_to_errno(err);
}
saClmFinalize(clm_handle);
our_nodeid = cluster_node.nodeId;
DEBUGLOG("Our local node id is %d\n", our_nodeid);
saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
add_internal_client(select_fd, lck_dispatch);
DEBUGLOG("Connected to OpenAIS\n");
return 0;
}
static void _cluster_closedown(void)
{
DEBUGLOG("cluster_closedown\n");
unlock_all();
saLckFinalize(lck_handle);
cpg_inalize(cpg_handle);
}
static void _get_our_csid(char *csid)
{
memcpy(csid, &our_nodeid, sizeof(int));
}
/* OpenAIS doesn't really have nmode names so we
just use the node ID in hex instead */
static int _csid_from_name(char *csid, const char *name)
{
int nodeid;
struct node_info *ninfo;
if (sscanf(name, "%x", &nodeid) == 1) {
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (ninfo)
return nodeid;
}
return -1;
}
static int _name_from_csid(const char *csid, char *name)
{
struct node_info *ninfo;
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (!ninfo)
{
sprintf(name, "UNKNOWN %s", print_csid(csid));
return -1;
}
sprintf(name, "%x", ninfo->nodeid);
return 0;
}
static int _get_num_nodes()
{
DEBUGLOG("num_nodes = %d\n", num_nodes);
return num_nodes;
}
/* Node is now known to be running a clvmd */
static void _add_up_node(const char *csid)
{
struct node_info *ninfo;
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (!ninfo) {
DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
print_csid(csid));
return;
}
DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
ninfo->state = NODE_CLVMD;
return;
}
/* Call a callback for each node, so the caller knows whether it's up or down */
static int _cluster_do_node_callback(struct local_client *master_client,
void (*callback)(struct local_client *,
const char *csid, int node_up))
{
struct dm_hash_node *hn;
struct node_info *ninfo;
dm_hash_iterate(hn, node_hash)
{
char csid[OPENAIS_CSID_LEN];
ninfo = dm_hash_get_data(node_hash, hn);
memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
ninfo->state);
if (ninfo->state != NODE_DOWN)
callback(master_client, csid, ninfo->state == NODE_CLVMD);
}
return 0;
}
/* Real locking */
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
{
struct lock_wait lwait;
struct lock_info *linfo;
SaLckResourceHandleT res_handle;
SaAisErrorT err;
SaLckLockIdT lock_id;
pthread_cond_init(&lwait.cond, NULL);
pthread_mutex_init(&lwait.mutex, NULL);
pthread_mutex_lock(&lwait.mutex);
/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
linfo = malloc(sizeof(struct lock_info));
if (!linfo)
return -1;
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
linfo->lock_name.length = strlen(resource)+1;
strcpy((char *)linfo->lock_name.value, resource);
err = saLckResourceOpen(lck_handle, &linfo->lock_name,
SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
if (err != SA_AIS_OK)
{
DEBUGLOG("ResourceOpen returned %d\n", err);
free(linfo);
return ais_to_errno(err);
}
err = saLckResourceLockAsync(res_handle,
(SaInvocationT)(long)&lwait,
&lock_id,
mode,
flags,
0);
if (err != SA_AIS_OK)
{
free(linfo);
saLckResourceClose(res_handle);
return ais_to_errno(err);
}
/* Wait for it to complete */
pthread_cond_wait(&lwait.cond, &lwait.mutex);
pthread_mutex_unlock(&lwait.mutex);
DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", lwait.status,
lock_id);
linfo->lock_id = lock_id;
linfo->res_handle = res_handle;
dm_hash_insert(lock_hash, resource, linfo);
return ais_to_errno(lwait.status);
}
static int _unlock_resource(char *resource, int lockid)
{
struct lock_wait lwait;
SaAisErrorT err;
struct lock_info *linfo;
pthread_cond_init(&lwait.cond, NULL);
pthread_mutex_init(&lwait.mutex, NULL);
pthread_mutex_lock(&lwait.mutex);
DEBUGLOG("unlock_resource %s\n", resource);
linfo = dm_hash_lookup(lock_hash, resource);
if (!linfo)
return 0;
DEBUGLOG("unlock_resource: lockid: %llx\n", linfo->lock_id);
err = saLckResourceUnlockAsync((SaInvocationT)(long)&lwait, linfo->lock_id);
if (err != SA_AIS_OK)
{
DEBUGLOG("Unlock returned %d\n", err);
return ais_to_errno(err);
}
/* Wait for it to complete */
pthread_cond_wait(&lwait.cond, &lwait.mutex);
pthread_mutex_unlock(&lwait.mutex);
/* Release the resource */
dm_hash_remove(lock_hash, resource);
saLckResourceClose(linfo->res_handle);
free(linfo);
return ais_to_errno(lwait.status);
}
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
{
int status;
char lock1[strlen(resource)+3];
char lock2[strlen(resource)+3];
snprintf(lock1, sizeof(lock1), "%s-1", resource);
snprintf(lock2, sizeof(lock2), "%s-2", resource);
switch (mode)
{
case LCK_EXCL:
status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
if (status)
goto out;
/* If we can't get this lock too then bail out */
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
lockid);
if (status == SA_LCK_LOCK_NOT_QUEUED)
{
_unlock_resource(lock1, *lockid);
status = -1;
errno = EAGAIN;
}
break;
case LCK_PREAD:
case LCK_READ:
status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
if (status)
goto out;
_unlock_resource(lock2, *lockid);
break;
case LCK_WRITE:
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
if (status)
goto out;
_unlock_resource(lock1, *lockid);
break;
default:
status = -1;
errno = EINVAL;
break;
}
out:
*lockid = mode;
return status;
}
static int _sync_unlock(const char *resource, int lockid)
{
int status = 0;
char lock1[strlen(resource)+3];
char lock2[strlen(resource)+3];
snprintf(lock1, sizeof(lock1), "%s-1", resource);
snprintf(lock2, sizeof(lock2), "%s-2", resource);
_unlock_resource(lock1, lockid);
_unlock_resource(lock2, lockid);
return status;
}
/* We are always quorate ! */
static int _is_quorate()
{
return 1;
}
static int _get_main_cluster_fd(void)
{
int select_fd;
cpg_fd_get(cpg_handle, &select_fd);
return select_fd;
}
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client)
{
cluster_client = fd;
*new_client = NULL;
cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
return 1;
}
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
const char *errtext)
{
struct iovec iov[2];
SaAisErrorT err;
int target_node;
if (csid)
memcpy(&target_node, csid, OPENAIS_CSID_LEN);
else
target_node = 0;
iov[0].iov_base = &target_node;
iov[0].iov_len = sizeof(int);
iov[1].iov_base = (char *)buf;
iov[1].iov_len = msglen;
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
return ais_to_errno(err);
}
/* We don't have a cluster name to report here */
static int _get_cluster_name(char *buf, int buflen)
{
strncpy(buf, "OpenAIS", buflen);
return 0;
}
static struct cluster_ops _cluster_openais_ops = {
.cluster_init_completed = NULL,
.cluster_send_message = _cluster_send_message,
.name_from_csid = _name_from_csid,
.csid_from_name = _csid_from_name,
.get_num_nodes = _get_num_nodes,
.cluster_fd_callback = _cluster_fd_callback,
.get_main_cluster_fd = _get_main_cluster_fd,
.cluster_do_node_callback = _cluster_do_node_callback,
.is_quorate = _is_quorate,
.get_our_csid = _get_our_csid,
.add_up_node = _add_up_node,
.reread_config = NULL,
.cluster_closedown = _cluster_closedown,
.get_cluster_name = _get_cluster_name,
.sync_lock = _sync_lock,
.sync_unlock = _sync_unlock,
};
struct cluster_ops *init_openais_cluster(void)
{
if (!_init_cluster())
return &_cluster_openais_ops;
else
return NULL;
}

View File

@@ -45,7 +45,6 @@
#include "version.h"
#include "clvmd.h"
#include "refresh_clvmd.h"
#include "system-lv.h"
#include "list.h"
#include "log.h"
@@ -58,10 +57,6 @@
#define MAX_RETRIES 4
/* The maximum size of a message that will fit into a packet. Anything bigger
than this is sent via the system LV */
#define MAX_INLINE_MESSAGE (max_cluster_message-sizeof(struct clvm_header))
#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0)
/* Head of the fd list. Also contains
@@ -115,31 +110,32 @@ static void send_local_reply(struct local_client *client, int status,
static void free_reply(struct local_client *client);
static void send_version_message(void);
static void *pre_and_post_thread(void *arg);
static int send_message(void *buf, int msglen, char *csid, int fd,
static int send_message(void *buf, int msglen, const char *csid, int fd,
const char *errtext);
static int read_from_local_sock(struct local_client *thisfd);
static int process_local_command(struct clvm_header *msg, int msglen,
struct local_client *client,
unsigned short xid);
static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
char *csid);
static int process_reply(struct clvm_header *msg, int msglen, char *csid);
const char *csid);
static int process_reply(const struct clvm_header *msg, int msglen,
const char *csid);
static int open_local_sock(void);
static struct local_client *find_client(int clientid);
static void main_loop(int local_sock, int cmd_timeout);
static void be_daemon(int start_timeout);
static int check_all_clvmds_running(struct local_client *client);
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
int len, char *csid,
int len, const char *csid,
struct local_client **new_client);
static void *lvm_thread_fn(void *);
static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
int msglen, char *csid);
int msglen, const char *csid);
static int distribute_command(struct local_client *thisfd);
static void hton_clvm(struct clvm_header *hdr);
static void ntoh_clvm(struct clvm_header *hdr);
static void add_reply_to_list(struct local_client *client, int status,
char *csid, const char *buf, int len);
const char *csid, const char *buf, int len);
static void usage(char *prog, FILE *file)
{
@@ -295,6 +291,15 @@ int main(int argc, char *argv[])
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to GULM");
}
#endif
#ifdef USE_OPENAIS
if (!clops)
if ((clops = init_openais_cluster())) {
max_csid_len = OPENAIS_CSID_LEN;
max_cluster_message = OPENAIS_MAX_CLUSTER_MESSAGE;
max_cluster_member_name_len = OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN;
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to OpenAIS");
}
#endif
if (!clops) {
DEBUGLOG("Can't initialise cluster interface\n");
@@ -359,7 +364,8 @@ void clvmd_cluster_init_completed()
/* Data on a connected socket */
static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
char *csid, struct local_client **new_client)
const char *csid,
struct local_client **new_client)
{
*new_client = NULL;
return read_from_local_sock(thisfd);
@@ -367,7 +373,7 @@ static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
/* Data on a connected socket */
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
int len, char *csid,
int len, const char *csid,
struct local_client **new_client)
{
/* Someone connected to our local socket, accept it. */
@@ -408,7 +414,7 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
}
static int local_pipe_callback(struct local_client *thisfd, char *buf,
int maxlen, char *csid,
int maxlen, const char *csid,
struct local_client **new_client)
{
int len;
@@ -484,7 +490,7 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
add one with "ETIMEDOUT".
NOTE: This won't race with real replies because they happen in the same thread.
*/
static void timedout_callback(struct local_client *client, char *csid,
static void timedout_callback(struct local_client *client, const char *csid,
int node_up)
{
if (node_up) {
@@ -1051,31 +1057,6 @@ int add_client(struct local_client *new_client)
return 0;
}
/*
* Send a long message using the System LV
*/
static int send_long_message(struct local_client *thisfd, struct clvm_header *inheader, int len)
{
struct clvm_header new_header;
int status;
DEBUGLOG("Long message: being sent via system LV:\n");
/* Use System LV */
status = system_lv_write_data((char *)inheader, len);
if (status < 0)
return errno;
/* Send message indicating System-LV is being used */
memcpy(&new_header, inheader, sizeof(new_header));
new_header.flags |= CLVMD_FLAG_SYSTEMLV;
new_header.xid = thisfd->xid;
return send_message(&new_header, sizeof(new_header), NULL, -1,
"Error forwarding long message to cluster");
}
/* Called when the pre-command has completed successfully - we
now execute the real command on all the requested nodes */
static int distribute_command(struct local_client *thisfd)
@@ -1102,13 +1083,9 @@ static int distribute_command(struct local_client *thisfd)
add_to_lvmqueue(thisfd, inheader, len, NULL);
DEBUGLOG("Sending message to all cluster nodes\n");
if (len > MAX_INLINE_MESSAGE) {
send_long_message(thisfd, inheader, len );
} else {
inheader->xid = thisfd->xid;
send_message(inheader, len, NULL, -1,
"Error forwarding message to cluster");
}
inheader->xid = thisfd->xid;
send_message(inheader, len, NULL, -1,
"Error forwarding message to cluster");
} else {
/* Do it on a single node */
char csid[MAX_CSID_LEN];
@@ -1129,14 +1106,10 @@ static int distribute_command(struct local_client *thisfd)
} else {
DEBUGLOG("Sending message to single node: %s\n",
inheader->node);
if (len > MAX_INLINE_MESSAGE) {
send_long_message(thisfd, inheader, len );
} else {
inheader->xid = thisfd->xid;
send_message(inheader, len,
csid, -1,
"Error forwarding message to cluster node");
}
inheader->xid = thisfd->xid;
send_message(inheader, len,
csid, -1,
"Error forwarding message to cluster node");
}
}
}
@@ -1152,7 +1125,7 @@ static int distribute_command(struct local_client *thisfd)
/* Process a command from a remote node and return the result */
static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
char *csid)
const char *csid)
{
char *replyargs;
char nodename[max_cluster_member_name_len];
@@ -1167,55 +1140,6 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
DEBUGLOG("process_remote_command %d for clientid 0x%x XID %d on node %s\n",
msg->cmd, msg->clientid, msg->xid, nodename);
/* Is the data to be found in the system LV ? */
if (msg->flags & CLVMD_FLAG_SYSTEMLV) {
struct clvm_header *newmsg;
DEBUGLOG("Reading message from system LV\n");
newmsg =
(struct clvm_header *) malloc(msg->arglen +
sizeof(struct clvm_header));
if (newmsg) {
ssize_t len;
if (system_lv_read_data(nodename, (char *) newmsg,
&len) == 0) {
msg = newmsg;
msg_malloced = 1;
msglen = len;
} else {
struct clvm_header head;
DEBUGLOG("System LV read failed\n");
/* Return a failure response */
head.cmd = CLVMD_CMD_REPLY;
head.status = EFBIG;
head.flags = 0;
head.clientid = msg->clientid;
head.arglen = 0;
head.node[0] = '\0';
send_message(&head, sizeof(struct clvm_header),
csid, fd,
"Error sending ENOMEM command reply");
return;
}
} else {
struct clvm_header head;
DEBUGLOG
("Error attempting to malloc %d bytes for system LV read\n",
msg->arglen);
/* Return a failure response */
head.cmd = CLVMD_CMD_REPLY;
head.status = ENOMEM;
head.flags = 0;
head.clientid = msg->clientid;
head.arglen = 0;
head.node[0] = '\0';
send_message(&head, sizeof(struct clvm_header), csid,
fd, "Error sending ENOMEM command reply");
return;
}
}
/* Check for GOAWAY and sulk */
if (msg->cmd == CLVMD_CMD_GOAWAY) {
@@ -1290,40 +1214,16 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
replyargs, replylen);
agghead->xid = msg->xid;
/* Use the system LV ? */
if (replylen > MAX_INLINE_MESSAGE) {
agghead->cmd = CLVMD_CMD_REPLY;
agghead->status = status;
agghead->flags = CLVMD_FLAG_SYSTEMLV;
agghead->clientid = msg->clientid;
agghead->arglen = replylen;
agghead->node[0] = '\0';
/* If System LV operation failed then report it as EFBIG but only do it
if the data buffer has something in it. */
if (system_lv_write_data(aggreply,
replylen + sizeof(struct clvm_header)) < 0
&& replylen > 0)
agghead->status = EFBIG;
send_message(agghead,
sizeof(struct clvm_header), csid,
fd,
"Error sending long command reply");
} else {
agghead->cmd = CLVMD_CMD_REPLY;
agghead->status = status;
agghead->flags = 0;
agghead->clientid = msg->clientid;
agghead->arglen = replylen;
agghead->node[0] = '\0';
send_message(aggreply,
sizeof(struct clvm_header) +
replylen, csid, fd,
"Error sending command reply");
}
agghead->cmd = CLVMD_CMD_REPLY;
agghead->status = status;
agghead->flags = 0;
agghead->clientid = msg->clientid;
agghead->arglen = replylen;
agghead->node[0] = '\0';
send_message(aggreply,
sizeof(struct clvm_header) +
replylen, csid, fd,
"Error sending command reply");
} else {
struct clvm_header head;
@@ -1352,7 +1252,7 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
If we have got a full set then send them to the waiting client down the local
socket */
static void add_reply_to_list(struct local_client *client, int status,
char *csid, const char *buf, int len)
const char *csid, const char *buf, int len)
{
struct node_reply *reply;
@@ -1529,7 +1429,7 @@ static int process_local_command(struct clvm_header *msg, int msglen,
return status;
}
static int process_reply(struct clvm_header *msg, int msglen, char *csid)
static int process_reply(const struct clvm_header *msg, int msglen, const char *csid)
{
struct local_client *client = NULL;
@@ -1679,7 +1579,7 @@ static void send_version_message()
}
/* Send a message to either a local client or another server */
static int send_message(void *buf, int msglen, char *csid, int fd,
static int send_message(void *buf, int msglen, const char *csid, int fd,
const char *errtext)
{
int len;
@@ -1701,7 +1601,7 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
if (retry_cnt > MAX_RETRIES)
{
errno = saved_errno;
log_error(errtext);
log_error("%s", errtext);
errno = saved_errno;
break;
}
@@ -1725,7 +1625,7 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
continue;
}
log_error(errtext);
log_error("%s", errtext);
break;
}
ptr += len;
@@ -1811,7 +1711,7 @@ static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
/* Pass down some work to the LVM thread */
static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
int msglen, char *csid)
int msglen, const char *csid)
{
struct lvm_thread_cmd *cmd;
@@ -1889,7 +1789,8 @@ static int open_local_sock()
return local_socket;
}
void process_message(struct local_client *client, char *buf, int len, char *csid)
void process_message(struct local_client *client, const char *buf, int len,
const char *csid)
{
struct clvm_header *inheader;
@@ -1902,7 +1803,7 @@ void process_message(struct local_client *client, char *buf, int len, char *csid
}
static void check_all_callback(struct local_client *client, char *csid,
static void check_all_callback(struct local_client *client, const char *csid,
int node_up)
{
if (!node_up)

View File

@@ -76,7 +76,8 @@ struct netsock_bits {
};
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
char *csid, struct local_client ** new_client);
const char *csid,
struct local_client ** new_client);
/* One of these for each fd we are listening on */
struct local_client {
@@ -112,7 +113,8 @@ extern void cmd_client_cleanup(struct local_client *client);
extern int add_client(struct local_client *new_client);
extern void clvmd_cluster_init_completed(void);
extern void process_message(struct local_client *client, char *buf, int len, char *csid);
extern void process_message(struct local_client *client, const char *buf,
int len, const char *csid);
extern void debuglog(const char *fmt, ... );
int sync_lock(const char *resource, int mode, int flags, int *lockid);

View File

@@ -1,371 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Routines dealing with the System LV */
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/utsname.h>
#include <syslog.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <mntent.h>
#include <libdlm.h>
#ifdef HAVE_CCS
#include <ccs.h>
#endif
#include "log.h"
#include "list.h"
#include "locking.h"
#include "system-lv.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
#define SYSTEM_LV_FILESYSTEM "ext2"
#define SYSTEM_LV_MOUNTPOINT "/tmp/.clvmd-XXXXXX"
extern char *config_filename(void);
static char system_lv_name[PATH_MAX] = { '\0' };
static char mount_point[PATH_MAX] = { '\0' };
static int mounted = 0;
static int mounted_rw = 0;
static int lockid;
static const char *lock_name = "CLVM_SYSTEM_LV";
/* Look in /proc/mounts or (as a last resort) /etc/mtab to
see if the system-lv is mounted. If it is mounted and we
think it's not then abort because we don't have the right
lock status and we don't know what other processes are doing with it.
Returns 1 for mounted, 0 for not mounted so it matches the condition
of the "mounted" static variable above.
*/
static int is_really_mounted(void)
{
FILE *mountfile;
struct mntent *ment;
mountfile = setmntent("/proc/mounts", "r");
if (!mountfile) {
mountfile = setmntent("/etc/mtab", "r");
if (!mountfile) {
log_error("Unable to open /proc/mounts or /etc/mtab");
return -1;
}
}
/* Look for system LV name in the file */
do {
ment = getmntent(mountfile);
if (ment) {
if (strcmp(ment->mnt_fsname, system_lv_name) == 0) {
endmntent(mountfile);
return 1;
}
}
}
while (ment);
endmntent(mountfile);
return 0;
}
/* Get the system LV name from the config file */
static int find_system_lv(void)
{
if (system_lv_name[0] == '\0') {
#ifdef HAVE_CCS
int error;
ccs_node_t *ctree;
/* Read the cluster config file */
/* Open the config file */
error = open_ccs_file(&ctree, "clvm.ccs");
if (error) {
perror("reading config file");
return -1;
}
strcpy(system_lv_name, find_ccs_str(ctree,
"cluster/systemlv", '/',
"/dev/vg/system_lv"));
/* Finished with config file */
close_ccs_file(ctree);
#else
if (getenv("CLVMD_SYSTEM_LV"))
strcpy(system_lv_name, getenv("CLVMD_SYSTEM_LV"));
else
return -1;
#endif
}
/* See if it has been mounted outside our control */
if (is_really_mounted() != mounted) {
log_error
("The system LV state has been mounted/umounted outside the control of clvmd\n"
"it cannot not be used for cluster communications until this is fixed.\n");
return -1;
}
return 0;
}
/* No prizes */
int system_lv_umount(void)
{
if (!mounted)
return 0;
if (umount(mount_point) < 0) {
log_error("umount of system LV (%s) failed: %m\n",
system_lv_name);
return -1;
}
sync_unlock(lock_name, lockid);
mounted = 0;
/* Remove the mount point */
rmdir(mount_point);
return 0;
}
int system_lv_mount(int readwrite)
{
int status;
int saved_errno;
int fd;
if (find_system_lv()) {
errno = EBUSY;
return -1;
}
/* Is it already mounted suitably? */
if (mounted) {
if (!readwrite || (readwrite && mounted_rw)) {
return 0;
} else {
/* Mounted RO and we need RW */
if (system_lv_umount() < 0)
return -1;
}
}
/* Randomize the mount point */
strcpy(mount_point, SYSTEM_LV_MOUNTPOINT);
fd = mkstemp(mount_point);
if (fd < 0) {
log_error("mkstemp for system LV mount point failed: %m\n");
return -1;
}
/* Race condition here but there's no mkstemp for directories */
close(fd);
unlink(mount_point);
mkdir(mount_point, 0600);
/* Make sure we have a system-lv lock */
status =
sync_lock(lock_name, (readwrite) ? LKM_EXMODE : LKM_CRMODE, 0,
&lockid);
if (status < 0)
return -1;
/* Mount it */
if (mount(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_SYNCHRONOUS
| (readwrite ? 0 : MS_RDONLY), NULL) < 0) {
/* mount(2) returns EINVAL if the volume has no FS on it. So, if we want to
write to it we try to make a filesystem in it and retry the mount */
if (errno == EINVAL && readwrite) {
char cmd[256];
log_error("Attempting mkfs on system LV device %s\n",
system_lv_name);
snprintf(cmd, sizeof(cmd), "/sbin/mkfs -t %s %s",
SYSTEM_LV_FILESYSTEM, system_lv_name);
system(cmd);
if (mount
(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC |
MS_SYNCHRONOUS | (readwrite ? 0 : MS_RDONLY),
NULL) == 0)
goto mounted;
}
saved_errno = errno;
log_error("mount of system LV (%s, %s, %s) failed: %m\n",
system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM);
sync_unlock(lock_name, lockid);
errno = saved_errno;
return -1;
}
mounted:
/* Set the internal flags */
mounted = 1;
mounted_rw = readwrite;
return 0;
}
/* Erase *all* files in the root directory of the system LV.
This *MUST* be called with an appropriate lock held!
The LV is left mounted RW because it is assumed that the
caller wants to write something here after clearing some space */
int system_lv_eraseall(void)
{
DIR *dir;
struct dirent *ent;
char fname[PATH_MAX];
/* Must be mounted R/W */
system_lv_mount(1);
dir = opendir(mount_point);
if (!dir)
return -1;
while ((ent = readdir(dir))) {
struct stat st;
snprintf(fname, sizeof(fname), "%s/%s", mount_point,
ent->d_name);
if (stat(fname, &st)) {
if (S_ISREG(st.st_mode))
unlink(fname);
}
}
closedir(dir);
return 0;
}
/* This is a "high-level" routine - it mounts the system LV, writes
the data into a file named after this node and then umounts the LV
again */
int system_lv_write_data(char *data, ssize_t len)
{
struct utsname nodeinfo;
char fname[PATH_MAX];
int outfile;
ssize_t thiswrite;
ssize_t written;
if (system_lv_mount(1))
return -1;
/* Build the file name we are goingto use. */
uname(&nodeinfo);
snprintf(fname, sizeof(fname), "%s/%s", mount_point, nodeinfo.nodename);
/* Open the file for output */
outfile = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0600);
if (outfile < 0) {
int saved_errno = errno;
system_lv_umount();
errno = saved_errno;
return -1;
}
written = 0;
do {
thiswrite = write(outfile, data + written, len - written);
if (thiswrite > 0)
written += thiswrite;
} while (written < len && thiswrite > 0);
close(outfile);
system_lv_umount();
return (thiswrite < 0) ? -1 : 0;
}
/* This is a "high-level" routine - it mounts the system LV, reads
the data from a named file and then umounts the LV
again */
int system_lv_read_data(char *fname_base, char *data, ssize_t *len)
{
char fname[PATH_MAX];
int outfile;
struct stat st;
ssize_t filesize;
ssize_t thisread;
ssize_t readbytes;
if (system_lv_mount(0))
return -1;
/* Build the file name we are going to use. */
snprintf(fname, sizeof(fname), "%s/%s", mount_point, fname_base);
/* Get the file size and stuff. Actually we only need the file size but
this will also check that the file exists */
if (stat(fname, &st) < 0) {
int saved_errno = errno;
log_error("stat of file %s on system LV failed: %m\n", fname);
system_lv_umount();
errno = saved_errno;
return -1;
}
filesize = st.st_size;
outfile = open(fname, O_RDONLY);
if (outfile < 0) {
int saved_errno = errno;
log_error("open of file %s on system LV failed: %m\n", fname);
system_lv_umount();
errno = saved_errno;
return -1;
}
readbytes = 0;
do {
thisread =
read(outfile, data + readbytes, filesize - readbytes);
if (thisread > 0)
readbytes += thisread;
} while (readbytes < filesize && thisread > 0);
close(outfile);
system_lv_umount();
*len = readbytes;
return (thisread < 0) ? -1 : 0;
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _CLVM_SYSTEM_LV_H
#define _CLVM_SYSTEM_LV_H
/* Prototypes for System-LV functions */
/* "low-level" functions */
extern int system_lv_umount(void);
extern int system_lv_mount(int readwrite);
extern int system_lv_eraseall(void);
/* "high-level" functions */
extern int system_lv_write_data(char *data, ssize_t len);
extern int system_lv_read_data(char *fname_base, char *data, ssize_t *len);
#endif

View File

@@ -92,41 +92,37 @@ int init_comms(unsigned short port)
return 0;
}
void tcp_remove_client(char *csid)
{
void tcp_remove_client(const char *c_csid)
{
struct local_client *client;
char csid[GULM_MAX_CSID_LEN];
unsigned int i;
memcpy(csid, c_csid, sizeof csid);
DEBUGLOG("tcp_remove_client\n");
/* Don't actually close the socket here - that's the
job of clvmd.c whch will do the job when it notices the
other end has gone. We just need to remove the client(s) from
the hash table so we don't try to use it for sending any more */
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (client)
for (i = 0; i < 2; i++)
{
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (client)
{
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
}
/* Look for a mangled one too, on the 2nd iteration. */
csid[0] ^= 0x80;
}
/* Look for a mangled one too */
csid[0] ^= 0x80;
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (client)
{
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
}
/* Put it back as we found it */
csid[0] ^= 0x80;
}
int alloc_client(int fd, char *csid, struct local_client **new_client)
int alloc_client(int fd, const char *c_csid, struct local_client **new_client)
{
struct local_client *client;
char csid[GULM_MAX_CSID_LEN];
memcpy(csid, c_csid, sizeof csid);
DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid));
@@ -315,7 +311,7 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
return status;
}
int gulm_connect_csid(char *csid, struct local_client **newclient)
int gulm_connect_csid(const char *csid, struct local_client **newclient)
{
int fd;
struct sockaddr_in6 addr;
@@ -366,7 +362,7 @@ int gulm_connect_csid(char *csid, struct local_client **newclient)
}
/* Send a message to a known CSID */
static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const char *errtext)
static int tcp_send_message(void *buf, int msglen, const char *csid, const char *errtext)
{
int status;
struct local_client *client;
@@ -465,7 +461,7 @@ static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
}
/* Get someone else's IP address from DNS */
int get_ip_address(char *node, char *addr)
int get_ip_address(const char *node, char *addr)
{
struct hostent *he;
@@ -493,7 +489,7 @@ int get_ip_address(char *node, char *addr)
return 0;
}
char *print_csid(char *csid)
char *print_csid(const char *csid)
{
static char buf[128];
int *icsid = (int *)csid;

View File

@@ -5,9 +5,9 @@
#define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128
extern int init_comms(unsigned short);
extern char *print_csid(char *);
extern char *print_csid(const char *);
int get_main_gulm_cluster_fd(void);
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client);
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext);
void get_our_gulm_csid(char *csid);
int gulm_connect_csid(char *csid, struct local_client **newclient);
int gulm_connect_csid(const char *csid, struct local_client **newclient);

View File

@@ -187,7 +187,7 @@ int device_is_usable(dev_t dev)
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
/* Skip if target type doesn't match */
if (!strcmp(target_type, "mirror"))
if (target_type && !strcmp(target_type, "mirror"))
goto out;
} while (next);
@@ -937,6 +937,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return 1;
}
/* FIXME: symlinks should be created/destroyed at the same time
* as the kernel devices but we can't do that from within libdevmapper
* at present so we must walk the tree twice instead. */
/*
* Create LV symlinks for children of supplied root node.
*/
@@ -969,6 +973,32 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
return r;
}
/*
* Remove LV symlinks for children of supplied root node.
*/
static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root)
{
void *handle = NULL;
struct dm_tree_node *child;
char *vgname, *lvname, *layer;
int r = 1;
while ((child = dm_tree_next_child(&handle, root, 0))) {
if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
r = 0;
continue;
}
/* only top level layer has symlinks */
if (*layer)
continue;
fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname);
}
return r;
}
static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
{
void *handle = NULL;
@@ -1028,6 +1058,8 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
/* Deactivate LV and all devices it references that nothing else has open. */
if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
goto_out;
if (!_remove_lv_symlinks(dm, root))
log_error("Failed to remove all device symlinks associated with %s.", lv->name);
break;
case SUSPEND:
dm_tree_skip_lockfs(root);

View File

@@ -338,6 +338,11 @@ int fs_del_lv(const struct logical_volume *lv)
"", "");
}
int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name)
{
return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "");
}
int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name)
{

View File

@@ -25,6 +25,7 @@
*/
int fs_add_lv(const struct logical_volume *lv, const char *dev);
int fs_del_lv(const struct logical_volume *lv);
int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name);
int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name);
void fs_unlock(void);

View File

@@ -188,7 +188,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
int r = 0;
int use_mmap = 1;
off_t mmap_offset = 0;
char *buf;
char *buf = NULL;
if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
stack;

View File

@@ -258,6 +258,33 @@ void pvdisplay_colons(struct physical_volume *pv)
return;
}
void pvdisplay_segments(struct physical_volume *pv)
{
struct pv_segment *pvseg;
if (pv->pe_size)
log_print("--- Physical Segments ---");
list_iterate_items(pvseg, &pv->segments) {
log_print("Physical extent %u to %u:",
pvseg->pe, pvseg->pe + pvseg->len - 1);
if (pvseg->lvseg) {
log_print(" Logical volume\t%s%s/%s",
pvseg->lvseg->lv->vg->cmd->dev_dir,
pvseg->lvseg->lv->vg->name,
pvseg->lvseg->lv->name);
log_print(" Logical extents\t%d to %d",
pvseg->lvseg->le, pvseg->lvseg->le +
pvseg->lvseg->len - 1);
} else
log_print(" FREE");
}
log_print(" ");
return;
}
/* FIXME Include label fields */
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
void *handle __attribute((unused)))

View File

@@ -31,6 +31,7 @@ char *display_uuid(char *uuidstr);
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
void pvdisplay_colons(struct physical_volume *pv);
void pvdisplay_segments(struct physical_volume *pv);
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
void *handle);
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,

View File

@@ -362,6 +362,22 @@ int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
return 1;
}
int archive_list_file(struct cmd_context *cmd, const char *file)
{
struct archive_file af;
af.path = (char *)file;
if (!path_exists(af.path)) {
log_err("Archive file %s not found.", af.path);
return 0;
}
_display_archive(cmd, &af);
return 1;
}
int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
{
struct archive_file af;

View File

@@ -148,6 +148,17 @@ int archive_display(struct cmd_context *cmd, const char *vg_name)
return r1 && r2;
}
int archive_display_file(struct cmd_context *cmd, const char *file)
{
int r;
init_partial(1);
r = archive_list_file(cmd, file);
init_partial(0);
return r;
}
int backup_init(struct cmd_context *cmd, const char *dir)
{
if (!(cmd->backup_params = dm_pool_zalloc(cmd->libmem,

View File

@@ -38,6 +38,7 @@ void archive_exit(struct cmd_context *cmd);
void archive_enable(struct cmd_context *cmd, int flag);
int archive(struct volume_group *vg);
int archive_display(struct cmd_context *cmd, const char *vg_name);
int archive_display_file(struct cmd_context *cmd, const char *file);
int backup_init(struct cmd_context *cmd, const char *dir);
void backup_exit(struct cmd_context *cmd);

View File

@@ -33,6 +33,7 @@ int archive_vg(struct volume_group *vg,
* Displays a list of vg backups in a particular archive directory.
*/
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname);
int archive_list_file(struct cmd_context *cmd, const char *file);
int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname);
/*

View File

@@ -34,6 +34,87 @@ static int _vg_lock_count = 0; /* Number of locks held */
static int _vg_write_lock_held = 0; /* VG write lock held? */
static int _signals_blocked = 0;
static volatile sig_atomic_t _sigint_caught = 0;
static volatile sig_atomic_t _handler_installed;
static struct sigaction _oldhandler;
static int _oldmasked;
static void _catch_sigint(int unused __attribute__((unused)))
{
_sigint_caught = 1;
}
int sigint_caught() {
return _sigint_caught;
}
void sigint_clear()
{
_sigint_caught = 0;
}
/* Temporarily allow keyboard interrupts to be intercepted and noted;
saves interrupt handler state for sigint_restore(). Users should
use the sigint_caught() predicate to check whether interrupt was
requested and act appropriately. Interrupt flags are never
automatically cleared by this code, but lvm_run_command() clears
the flag before running any command. All other places where the
flag needs to be cleared need to call sigint_clear(). */
void sigint_allow()
{
struct sigaction handler;
sigset_t sigs;
/* do not overwrite the backed up handler data with our
override ones; we just increase nesting count */
if (_handler_installed) {
_handler_installed++;
return;
}
/* grab old sigaction for SIGINT; shall not fail */
sigaction(SIGINT, NULL, &handler);
handler.sa_flags &= ~SA_RESTART; /* clear restart flag */
handler.sa_handler = _catch_sigint;
_handler_installed = 1;
/* override the signal handler; shall not fail */
sigaction(SIGINT, &handler, &_oldhandler);
/* unmask SIGINT, remember to mask it again on restore */
sigprocmask(0, NULL, &sigs);
if ((_oldmasked = sigismember(&sigs, SIGINT))) {
sigdelset(&sigs, SIGINT);
sigprocmask(SIG_SETMASK, &sigs, NULL);
}
}
void sigint_restore()
{
/* extra call, ignore */
if (!_handler_installed)
return;
if (_handler_installed > 1) {
_handler_installed--;
return;
}
/* nesting count went down to 0 */
_handler_installed = 0;
if (_oldmasked) {
sigset_t sigs;
sigprocmask(0, NULL, &sigs);
sigaddset(&sigs, SIGINT);
sigprocmask(SIG_SETMASK, &sigs, NULL);
}
sigaction(SIGINT, &_oldhandler, NULL);
}
static void _block_signals(int flags __attribute((unused)))
{
sigset_t set;

View File

@@ -115,4 +115,11 @@ int suspend_lvs(struct cmd_context *cmd, struct list *lvs);
int resume_lvs(struct cmd_context *cmd, struct list *lvs);
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs);
/* interrupt handling */
void sigint_clear();
void sigint_allow();
void sigint_restore();
int sigint_caught();
#endif

View File

@@ -24,9 +24,43 @@
#include "pv_alloc.h"
#include "activate.h"
#include "display.h"
#include "locking.h"
#include <sys/param.h>
/*
* FIXME: Check for valid handle before dereferencing field or log error?
*/
#define pv_field(handle, field) \
(((struct physical_volume *)(handle))->field)
static struct physical_volume *_pv_read(struct cmd_context *cmd,
const char *pv_name,
struct list *mdas,
uint64_t *label_sector,
int warnings);
static struct physical_volume *_pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id, uint64_t size,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas);
static int _pv_write(struct cmd_context *cmd __attribute((unused)),
struct physical_volume *pv,
struct list *mdas, int64_t label_sector);
static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
const char *pv_name);
static struct pv_list *_find_pv_in_vg(struct volume_group *vg, const char *pv_name);
static struct physical_volume *_find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id);
unsigned long pe_align(void)
{
return MAX(65536UL, lvm_getpagesize()) >> SECTOR_SHIFT;
@@ -49,7 +83,7 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
}
list_init(&mdas);
if (!(pv = pv_read(fid->fmt->cmd, pv_name, &mdas, NULL, 1))) {
if (!(pv = _pv_read(fid->fmt->cmd, pv_name, &mdas, NULL, 1))) {
log_error("%s not identified as an existing physical volume",
pv_name);
return 0;
@@ -102,7 +136,7 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
return 0;
}
if (find_pv_in_vg(vg, pv_name)) {
if (_find_pv_in_vg(vg, pv_name)) {
log_error("Physical volume '%s' listed more than once.",
pv_name);
return 0;
@@ -532,8 +566,44 @@ int vg_split_mdas(struct cmd_context *cmd, struct volume_group *vg_from,
return 1;
}
/**
* pv_create - initialize a physical volume for use with a volume group
* @fmt: format type
* @dev: PV device to initialize
* @id: PV UUID to use for initialization
* @size: size of the PV in sectors
* @pe_start: physical extent start
* @existing_extent_count
* @existing_extent_size
* @pvmetadatacopies
* @pvmetadatasize
* @mdas
*
* Returns:
* PV handle - physical volume initialized successfully
* NULL - invalid parameter or problem initializing the physical volume
*
* Note:
* FIXME - liblvm todo - tidy up arguments for external use (fmt, mdas, etc)
*/
pv_t *pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id, uint64_t size,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas)
{
return _pv_create(fmt, dev, id, size, pe_start,
existing_extent_count,
existing_extent_size,
pvmetadatacopies,
pvmetadatasize, mdas);
}
/* Sizes in sectors */
struct physical_volume *pv_create(const struct format_type *fmt,
static struct physical_volume *_pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id, uint64_t size,
uint64_t pe_start,
@@ -609,7 +679,13 @@ struct physical_volume *pv_create(const struct format_type *fmt,
return NULL;
}
/* FIXME: liblvm todo - make into function that returns handle */
struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
{
return _find_pv_in_vg(vg, pv_name);
}
static struct pv_list *_find_pv_in_vg(struct volume_group *vg, const char *pv_name)
{
struct pv_list *pvl;
@@ -631,8 +707,26 @@ int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
return 0;
}
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id)
/**
* find_pv_in_vg_by_uuid - Find PV in VG by PV UUID
* @vg: volume group to search
* @id: UUID of the PV to match
*
* Returns:
* PV handle - if UUID of PV found in VG
* NULL - invalid parameter or UUID of PV not found in VG
*
* Note
* FIXME - liblvm todo - make into function that takes VG handle
*/
pv_t *find_pv_in_vg_by_uuid(struct volume_group *vg, struct id *id)
{
return _find_pv_in_vg_by_uuid(vg, id);
}
static struct physical_volume *_find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id)
{
struct pv_list *pvl;
@@ -690,12 +784,20 @@ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
return NULL;
}
/* FIXME: liblvm todo - make into function that returns handle */
struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
const char *pv_name)
{
return _find_pv_by_name(cmd, pv_name);
}
static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
const char *pv_name)
{
struct physical_volume *pv;
if (!(pv = pv_read(cmd, pv_name, NULL, NULL, 1))) {
if (!(pv = _pv_read(cmd, pv_name, NULL, NULL, 1))) {
log_error("Physical volume %s not found", pv_name);
return NULL;
}
@@ -979,7 +1081,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
}
list_iterate_items(info, &vginfo->infos) {
if (!(pv = pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
if (!(pv = _pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
continue;
}
if (!(pvl = dm_pool_zalloc(cmd->mem, sizeof(*pvl)))) {
@@ -1385,10 +1487,34 @@ struct logical_volume *lv_from_lvid(struct cmd_context *cmd, const char *lvid_s,
return lvl->lv;
}
/* FIXME Use label functions instead of PV functions */
/**
* pv_read - read and return a handle to a physical volume
* @cmd: LVM command initiating the pv_read
* @pv_name: full device name of the PV, including the path
* @mdas: list of metadata areas of the PV
* @label_sector: sector number where the PV label is stored on @pv_name
* @warnings:
*
* Returns:
* PV handle - valid pv_name and successful read of the PV, or
* NULL - invalid parameter or error in reading the PV
*
* Note:
* FIXME - liblvm todo - make into function that returns handle
*/
struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
struct list *mdas, uint64_t *label_sector,
int warnings)
{
return _pv_read(cmd, pv_name, mdas, label_sector, warnings);
}
/* FIXME Use label functions instead of PV functions */
static struct physical_volume *_pv_read(struct cmd_context *cmd,
const char *pv_name,
struct list *mdas,
uint64_t *label_sector,
int warnings)
{
struct physical_volume *pv;
struct label *label;
@@ -1509,8 +1635,17 @@ struct list *get_pvs(struct cmd_context *cmd)
return results;
}
int pv_write(struct cmd_context *cmd __attribute((unused)), struct physical_volume *pv,
/* FIXME: liblvm todo - make into function that takes handle */
int pv_write(struct cmd_context *cmd __attribute((unused)),
struct physical_volume *pv,
struct list *mdas, int64_t label_sector)
{
return _pv_write(cmd, pv, mdas, label_sector);
}
static int _pv_write(struct cmd_context *cmd __attribute((unused)),
struct physical_volume *pv,
struct list *mdas, int64_t label_sector)
{
if (!pv->fmt->ops->pv_write) {
log_error("Format does not support writing physical volumes");
@@ -1543,7 +1678,7 @@ int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
return 0;
}
if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
if (!_pv_write(cmd, pv, NULL, INT64_C(-1))) {
log_error("Failed to clear metadata from physical "
"volume \"%s\" after removal from \"%s\"",
dev_name(pv->dev), old_vg_name);
@@ -1552,6 +1687,17 @@ int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
return 1;
}
/**
* is_orphan - Determine whether a pv is an orphan based on its vg_name
* @pv: handle to the physical volume
*/
int is_orphan(pv_t *pv)
{
return (pv_field(pv, vg_name)[0] ? 0 : 1);
}
/*
* Returns:
* 0 - fail
@@ -1593,3 +1739,102 @@ int pv_analyze(struct cmd_context *cmd, const char *pv_name,
return 1;
}
/**
* vg_check_status - check volume group status flags and log error
* @vg - volume group to check status flags
* @status_flags - specific status flags to check (e.g. EXPORTED_VG)
*
* Returns:
* 0 - fail
* 1 - success
*/
int vg_check_status(struct volume_group *vg, uint32_t status_flags)
{
if ((status_flags & CLUSTERED) &&
(vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg->name);
return 0;
}
if ((status_flags & EXPORTED_VG) &&
(vg->status & EXPORTED_VG)) {
log_error("Volume group %s is exported", vg->name);
return 0;
}
if ((status_flags & LVM_WRITE) &&
!(vg->status & LVM_WRITE)) {
log_error("Volume group %s is read-only", vg->name);
return 0;
}
if ((status_flags & RESIZEABLE_VG) &&
!(vg->status & RESIZEABLE_VG)) {
log_error("Volume group %s is not resizeable.", vg->name);
return 0;
}
return 1;
}
/*
* Gets/Sets for external LVM library
*/
struct id get_pv_id(pv_t *pv)
{
return pv_field(pv, id);
}
const struct format_type *get_pv_format_type(pv_t *pv)
{
return pv_field(pv, fmt);
}
struct id get_pv_vgid(pv_t *pv)
{
return pv_field(pv, vgid);
}
struct device *get_pv_dev(pv_t *pv)
{
return pv_field(pv, dev);
}
const char *get_pv_vg_name(pv_t *pv)
{
return pv_field(pv, vg_name);
}
uint64_t get_pv_size(pv_t *pv)
{
return pv_field(pv, size);
}
uint32_t get_pv_status(pv_t *pv)
{
return pv_field(pv, status);
}
uint32_t get_pv_pe_size(pv_t *pv)
{
return pv_field(pv, pe_size);
}
uint64_t get_pv_pe_start(pv_t *pv)
{
return pv_field(pv, pe_start);
}
uint32_t get_pv_pe_count(pv_t *pv)
{
return pv_field(pv, pe_count);
}
uint32_t get_pv_pe_alloc_count(pv_t *pv)
{
return pv_field(pv, pe_alloc_count);
}

View File

@@ -142,6 +142,7 @@ struct physical_volume {
struct list tags;
};
typedef struct physical_volume pv_t;
struct metadata_area;
struct format_instance;
@@ -435,18 +436,19 @@ struct list *get_vgids(struct cmd_context *cmd, int full_scan);
int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
struct list *mdas, int64_t label_sector);
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
int is_orphan(pv_t *pv);
/* pe_start and pe_end relate to any existing data so that new metadata
* areas can avoid overlap */
struct physical_volume *pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id,
uint64_t size,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas);
pv_t *pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id,
uint64_t size,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas);
int pv_resize(struct physical_volume *pv, struct volume_group *vg,
uint32_t new_pe_count);
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
@@ -500,8 +502,7 @@ struct physical_volume *pv_find(struct volume_group *vg, const char *pv_name);
/* Find a PV within a given VG */
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);
pv_t *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 *vgid, const char *pvid,
struct physical_volume *pv);
@@ -578,6 +579,8 @@ int vg_add_snapshot(struct format_instance *fid, const char *name,
int vg_remove_snapshot(struct logical_volume *cow);
int vg_check_status(struct volume_group *vg, uint32_t status_flags);
/*
* Mirroring functions
*/
@@ -633,4 +636,19 @@ uint32_t find_free_lvnum(struct logical_volume *lv);
char *generate_lv_name(struct volume_group *vg, const char *format,
char *buffer, size_t len);
/*
* Gets/Sets for external LVM library
*/
struct id get_pv_id(pv_t *pv);
const struct format_type *get_pv_format_type(pv_t *pv);
struct id get_pv_vgid(pv_t *pv);
struct device *get_pv_dev(pv_t *pv);
const char *get_pv_vg_name(pv_t *pv);
uint64_t get_pv_size(pv_t *pv);
uint32_t get_pv_status(pv_t *pv);
uint32_t get_pv_pe_size(pv_t *pv);
uint64_t get_pv_pe_start(pv_t *pv);
uint32_t get_pv_pe_count(pv_t *pv);
uint32_t get_pv_pe_alloc_count(pv_t *pv);
#endif

View File

@@ -5,18 +5,29 @@ vgcfgrestore \- restore volume group descriptor area
.B vgcfgrestore
.RB [ \-d | \-\-debug ]
.RB [ \-f | \-\-file " filename" ]
.RB [ \-l[l] | \-\-list [--list] ]
.RB [ \-l[l] | \-\-list ]
.RB [ \-h | \-\-help ]
.RB [ \-M | \-\-Metadatatype 1|2]
.RB [ \-n | \-\-name " VolumeGroupName" ]
.RB [ \-t | \-\-test ]
.RB [ \-v | \-\-verbose ]
.RI [ VolumeGroupName ...]
.RI \fIVolumeGroupName\fP
.SH DESCRIPTION
.B vgcfgrestore
allows you to restore the metadata
of your volume groups from a text backup file produced by \fBvgcfgbackup\fP.
allows you to restore the metadata of \fIVolumeGroupName\fP from a text
backup file produced by \fBvgcfgbackup\fP. You can specify a backup file to
use with the \fP-f\fP option. If no backup file is specified, the latest
backup file is used. A list of backup and archive files of
\fIVolumeGroupName\fP may be listed with the \fB-l\fP option.
.SH OPTIONS
.TP
\fB-l | --list\fP \(em List files pertaining to \fIVolumeGroupName\fP
List metadata backup and archive files pertaining to \fIVolumeGroupName\fP.
May be used with the \fB-f\fP option. Does not restore \fIVolumeGroupName\fP.
.TP
\fB-f | --file\fP filename \(em Name of LVM metadata backup file
Specifies a metadata backup or archive file to be used for restoring
VolumeGroupName. Often this file has been created with \fBvgcfgbackup\fP.
.TP
See \fBlvm\fP for common options.
.SH REPLACING PHYSICAL VOLUMES
\fBvgdisplay --partial --verbose\fP will show you the UUIDs and sizes of

View File

@@ -8,11 +8,15 @@ vgrename \- rename a volume group
[\-h/\-?/\-\-help]
[\-t/\-\-test]
[\-v/\-\-verbose]
OldVolumeGroupPath/\-Name NewVolumeGroupPath/\-Name
.IR OldVolumeGroup { Path | Name | UUID }
.IR NewVolumeGroup { Path | Name }
.SH DESCRIPTION
vgrename renames an existing (see
.B vgcreate(8)
) volume group.
) volume group from
.IR OldVolumeGroup { Name | Path | UUID }
to
.IR NewVolumeGroup { Name | Path }.
.SH OPTIONS
See \fBlvm\fP for common options.
.SH Examples
@@ -20,6 +24,9 @@ See \fBlvm\fP for common options.
volume group "vg02" to "my_volume_group".
.TP
"vgrename vg02 my_volume_group" does the same.
.TP
"vgrename Zvlifi-Ep3t-e0Ng-U42h-o0ye-KHu1-nl7Ns4 VolGroup00_tmp" renames a volume group with UUID Zvlifi-Ep3t-e0Ng-U42h-o0ye-KHu1-nl7Ns4 to the volume group named "VolGroup00_tmp". Using the UUID option to name a volume group may be useful in cases where one machine has two physical volumes, each with the same volume group name, but a separate volume group UUID (this situation will cause error messages with lvm commands). One way duplicate volume group names occur is if an old disk with a root volume is moved to a new machine with its own root volume. In this case, both volume groups may have the same name (for example, "VolGroup00"), but different UUIDs.
.TP
.SH SEE ALSO
.BR lvm (8),
.BR vgchange (8),

View File

@@ -90,6 +90,11 @@ extern char *optarg;
#define ARGS_MAX 256
#define LOOP_TABLE_SIZE (PATH_MAX + 255)
/* FIXME Should be imported */
#ifndef DM_MAX_TYPE_NAME
# define DM_MAX_TYPE_NAME 16
#endif
/* FIXME Should be elsewhere */
#define SECTOR_SHIFT 9L
#define DEV_PATH "/dev/"
@@ -121,12 +126,20 @@ enum {
TARGET_ARG,
TREE_ARG,
UID_ARG,
UNBUFFERED_ARG,
UUID_ARG,
VERBOSE_ARG,
VERSION_ARG,
NUM_SWITCHES
};
typedef enum {
DR_TASK = 1,
DR_INFO = 2,
DR_DEPS = 4,
DR_TREE = 8 /* Complete dependency tree required */
} report_type_t;
static int _switches[NUM_SWITCHES];
static int _int_args[NUM_SWITCHES];
static char *_string_args[NUM_SWITCHES];
@@ -137,6 +150,7 @@ static char *_target;
static char *_command;
static struct dm_tree *_dtree;
static struct dm_report *_report;
static report_type_t _report_type;
/*
* Commands
@@ -240,11 +254,45 @@ static int _parse_file(struct dm_task *dmt, const char *file)
struct dmsetup_report_obj {
struct dm_task *task;
struct dm_info *info;
struct dm_task *deps_task;
struct dm_tree_node *tree_node;
};
static struct dm_task *_get_deps_task(int major, int minor)
{
struct dm_task *dmt;
struct dm_info info;
if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
return NULL;
if (!dm_task_set_major(dmt, major) ||
!dm_task_set_minor(dmt, minor))
goto err;
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
goto err;
if (!dm_task_run(dmt))
goto err;
if (!dm_task_get_info(dmt, &info))
goto err;
if (!info.exists)
goto err;
return dmt;
err:
dm_task_destroy(dmt);
return NULL;
}
static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
{
struct dmsetup_report_obj obj;
int r = 0;
if (!info->exists) {
fprintf(stderr, "Device does not exist.\n");
@@ -253,11 +301,23 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
obj.task = dmt;
obj.info = info;
obj.deps_task = NULL;
if (_report_type & DR_TREE)
obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor);
if (_report_type & DR_DEPS)
obj.deps_task = _get_deps_task(info->major, info->minor);
if (!dm_report_object(_report, &obj))
return 0;
goto out;
return 1;
r = 1;
out:
if (obj.deps_task)
dm_task_destroy(obj.deps_task);
return r;
}
static void _display_info_long(struct dm_task *dmt, struct dm_info *info)
@@ -1419,7 +1479,8 @@ static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
/*
* Walk the dependency tree
*/
static void _tree_walk_children(struct dm_tree_node *node, unsigned depth)
static void _display_tree_walk_children(struct dm_tree_node *node,
unsigned depth)
{
struct dm_tree_node *child, *next_child;
void *handle = NULL;
@@ -1438,7 +1499,7 @@ static void _tree_walk_children(struct dm_tree_node *node, unsigned depth)
next_child ? 0U : 1U, has_children);
if (has_children)
_tree_walk_children(child, depth + 1);
_display_tree_walk_children(child, depth + 1);
first_child = 0;
}
@@ -1457,17 +1518,28 @@ static int _add_dep(int argc __attribute((unused)), char **argv __attribute((unu
/*
* Create and walk dependency tree
*/
static int _tree(int argc, char **argv, void *data __attribute((unused)))
static int _build_whole_deptree(void)
{
if (_dtree)
return 1;
if (!(_dtree = dm_tree_create()))
return 0;
if (!_process_all(argc, argv, 0, _add_dep))
if (!_process_all(0, NULL, 0, _add_dep))
return 0;
_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);
return 1;
}
dm_tree_free(_dtree);
static int _display_tree(int argc __attribute((unused)),
char **argv __attribute((unused)),
void *data __attribute((unused)))
{
if (!_build_whole_deptree())
return 0;
_display_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);
return 1;
}
@@ -1490,8 +1562,8 @@ static int _int32_disp(struct dm_report *rh,
static int _uint32_disp(struct dm_report *rh,
struct dm_pool *mem __attribute((unused)),
struct dm_report_field *field, const void *data,
void *private __attribute((unused)))
struct dm_report_field *field, const void *data,
void *private __attribute((unused)))
{
const uint32_t value = *(const int32_t *)data;
@@ -1539,8 +1611,203 @@ static int _dm_info_status_disp(struct dm_report *rh,
return dm_report_field_string(rh, field, &s);
}
/* Report types */
enum { DR_TASK = 1, DR_INFO = 2 };
static int _dm_info_devno_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private)
{
char buf[DM_MAX_TYPE_NAME], *repstr;
struct dm_info *info = (struct dm_info *) data;
if (!dm_pool_begin_object(mem, 8)) {
log_error("dm_pool_begin_object failed");
return 0;
}
if (dm_snprintf(buf, sizeof(buf), "%d:%d",
info->major, info->minor) < 0) {
log_error("dm_pool_alloc failed");
goto out_abandon;
}
if (!dm_pool_grow_object(mem, buf, strlen(buf))) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
repstr = dm_pool_end_object(mem);
dm_report_field_set_value(field, repstr, repstr);
return 1;
out_abandon:
dm_pool_abandon_object(mem);
return 0;
}
static int _dm_tree_names(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private, unsigned inverted)
{
struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;
void *t = NULL;
const char *name;
int first_node = 1;
char *repstr;
if (!dm_pool_begin_object(mem, 16)) {
log_error("dm_pool_begin_object failed");
return 0;
}
while ((parent = dm_tree_next_child(&t, node, inverted))) {
name = dm_tree_node_get_name(parent);
if (!name || !*name)
continue;
if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (!dm_pool_grow_object(mem, name, strlen(name))) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (first_node)
first_node = 0;
}
if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
repstr = dm_pool_end_object(mem);
dm_report_field_set_value(field, repstr, repstr);
return 1;
out_abandon:
dm_pool_abandon_object(mem);
return 0;
}
static int _dm_deps_names_disp(struct dm_report *rh,
struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
return _dm_tree_names(rh, mem, field, data, private, 0);
}
static int _dm_tree_parents_names_disp(struct dm_report *rh,
struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
return _dm_tree_names(rh, mem, field, data, private, 1);
}
static int _dm_tree_parents_devs_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;
void *t = NULL;
const struct dm_info *info;
int first_node = 1;
char buf[DM_MAX_TYPE_NAME], *repstr;
if (!dm_pool_begin_object(mem, 16)) {
log_error("dm_pool_begin_object failed");
return 0;
}
while ((parent = dm_tree_next_child(&t, node, 1))) {
info = dm_tree_node_get_info(parent);
if (!info->major && !info->minor)
continue;
if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (dm_snprintf(buf, sizeof(buf), "%d:%d",
info->major, info->minor) < 0) {
log_error("dm_snprintf failed");
goto out_abandon;
}
if (!dm_pool_grow_object(mem, buf, strlen(buf))) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (first_node)
first_node = 0;
}
if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
repstr = dm_pool_end_object(mem);
dm_report_field_set_value(field, repstr, repstr);
return 1;
out_abandon:
dm_pool_abandon_object(mem);
return 0;
}
static int _dm_tree_parents_count_disp(struct dm_report *rh,
struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
struct dm_tree_node *node = (struct dm_tree_node *) data;
int num_parent = dm_tree_node_num_children(node, 1);
return dm_report_field_int(rh, field, &num_parent);
}
static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private)
{
struct dm_deps *deps = (struct dm_deps *) data;
int i;
char buf[DM_MAX_TYPE_NAME], *repstr;
if (!dm_pool_begin_object(mem, 16)) {
log_error("dm_pool_begin_object failed");
return 0;
}
for (i = 0; i < deps->count; i++) {
if (dm_snprintf(buf, sizeof(buf), "%d:%d",
(int) MAJOR(deps->device[i]),
(int) MINOR(deps->device[i])) < 0) {
log_error("dm_snprintf failed");
goto out_abandon;
}
if (!dm_pool_grow_object(mem, buf, strlen(buf))) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
if (i + 1 < deps->count && !dm_pool_grow_object(mem, ",", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
}
if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
goto out_abandon;
}
repstr = dm_pool_end_object(mem);
dm_report_field_set_value(field, repstr, repstr);
return 1;
out_abandon:
dm_pool_abandon_object(mem);
return 0;
}
static void *_task_get_obj(void *obj)
{
@@ -1552,9 +1819,21 @@ static void *_info_get_obj(void *obj)
return ((struct dmsetup_report_obj *)obj)->info;
}
static void *_deps_get_obj(void *obj)
{
return dm_task_get_deps(((struct dmsetup_report_obj *)obj)->deps_task);
}
static void *_tree_get_obj(void *obj)
{
return ((struct dmsetup_report_obj *)obj)->tree_node;
}
static const struct dm_report_object_type _report_types[] = {
{ DR_TASK, "Mapped Device Name", "", _task_get_obj },
{ DR_INFO, "Mapped Device Information", "", _info_get_obj },
{ DR_DEPS, "Mapped Device Relationship Information", "", _deps_get_obj },
{ DR_TREE, "Mapped Device Relationship Information", "", _tree_get_obj },
{ 0, "", "", NULL },
};
@@ -1570,11 +1849,20 @@ static const struct dm_report_field_type _report_fields[] = {
FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.")
FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")
FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.")
FIELD_F(INFO, STR, "DevNo", 5, dm_info_devno, "devno", "Device major and minor numbers")
FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.")
FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.")
FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.")
FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.")
FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.")
FIELD_O(DEPS, dm_deps, NUM, "#Devs", count, 5, int32, "device_count", "Number of devices used by this one.")
FIELD_F(TREE, STR, "DevNames", 8, dm_deps_names, "devs_used", "List of names of mapped devices used by this one.")
FIELD_F(DEPS, STR, "DevNos", 6, dm_deps, "devnos_used", "List of device numbers of devices used by this one.")
FIELD_F(TREE, NUM, "#Refs", 5, dm_tree_parents_count, "device_ref_count", "Number of mapped devices referencing this one.")
FIELD_F(TREE, STR, "RefNames", 8, dm_tree_parents_names, "names_using_dev", "List of names of mapped devices using this one.")
FIELD_F(TREE, STR, "RefDevNos", 9, dm_tree_parents_devs, "devnos_using_dev", "List of device numbers of mapped devices using this one.")
{0, 0, 0, 0, "", "", NULL, NULL},
/* *INDENT-ON* */
};
@@ -1591,8 +1879,7 @@ static int _report_init(struct command *c)
char *options = (char *) default_report_options;
const char *keys = "";
const char *separator = " ";
int aligned = 1, headings = 1, buffered = 0;
uint32_t report_type = 0;
int aligned = 1, headings = 1, buffered = 1;
uint32_t flags = 0;
size_t len = 0;
int r = 0;
@@ -1604,6 +1891,9 @@ static int _report_init(struct command *c)
headings = 0;
}
if (_switches[UNBUFFERED_ARG])
buffered = 0;
if (_switches[OPTIONS_ARG] && _string_args[OPTIONS_ARG]) {
if (*_string_args[OPTIONS_ARG] != '+')
options = _string_args[OPTIONS_ARG];
@@ -1646,11 +1936,16 @@ static int _report_init(struct command *c)
if (headings)
flags |= DM_REPORT_OUTPUT_HEADINGS;
if (!(_report = dm_report_init(&report_type,
_report_types, _report_fields,
options, separator, flags, keys, NULL)))
if (!(_report = dm_report_init(&_report_type,
_report_types, _report_fields,
options, separator, flags, keys, NULL)))
goto out;
if ((_report_type & DR_TREE) && !_build_whole_deptree()) {
err("Internal device dependency tree creation failed.");
goto out;
}
r = 1;
out:
@@ -1669,7 +1964,7 @@ static int _ls(int argc, char **argv, void *data)
(_switches[EXEC_ARG] && _command))
return _status(argc, argv, data);
else if ((_switches[TREE_ARG]))
return _tree(argc, argv, data);
return _display_tree(argc, argv, data);
else
return _process_all(argc, argv, 0, _display_name);
}
@@ -2079,6 +2374,7 @@ static int _process_switches(int *argc, char ***argv)
{"tree", 0, &ind, TREE_ARG},
{"uid", 1, &ind, UID_ARG},
{"uuid", 1, &ind, UUID_ARG},
{"unbuffered", 0, &ind, UNBUFFERED_ARG},
{"verbose", 1, &ind, VERBOSE_ARG},
{"version", 0, &ind, VERSION_ARG},
{0, 0, 0, 0}
@@ -2210,6 +2506,8 @@ static int _process_switches(int *argc, char ***argv)
}
if ((ind == TREE_ARG))
_switches[TREE_ARG]++;
if ((ind == UNBUFFERED_ARG))
_switches[UNBUFFERED_ARG]++;
if ((ind == VERSION_ARG))
_switches[VERSION_ARG]++;
}
@@ -2289,5 +2587,8 @@ out:
dm_report_free(_report);
}
if (_dtree)
dm_tree_free(_dtree);
return r;
}

View File

@@ -212,6 +212,9 @@ static int lvchange_resync(struct cmd_context *cmd,
return ECMD_FAILED;
}
if (sigint_caught())
return ECMD_FAILED;
active = 1;
}
}
@@ -454,6 +457,10 @@ static int lvchange_persistent(struct cmd_context *cmd,
lv->name);
return 0;
}
if (sigint_caught())
return 0;
log_verbose("Ensuring %s is inactive.", lv->name);
if (!deactivate_lv(cmd, lv)) {
log_error("%s: deactivation failed", lv->name);
@@ -626,6 +633,8 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
archived = 1;
doit += lvchange_persistent(cmd, lv);
if (sigint_caught())
return ECMD_FAILED;
}
/* add tag */

View File

@@ -557,21 +557,8 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
goto error;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", lp.vg_name);
if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG | LVM_WRITE))
goto error;
}
if (vg->status & EXPORTED_VG) {
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", lp.vg_name);
goto error;
}
if (!(lvl = find_lv_in_vg(vg, lp.lv_name))) {
log_error("Logical volume \"%s\" not found in "

View File

@@ -493,21 +493,8 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", lp->vg_name);
if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG | LVM_WRITE))
return 0;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", lp->vg_name);
return 0;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", lp->vg_name);
return 0;
}
if (lp->lv_name && find_lv_in_vg(vg, lp->lv_name)) {
log_error("Logical volume \"%s\" already exists in "

View File

@@ -373,6 +373,7 @@ char yes_no_prompt(const char *prompt, ...)
int c = 0, ret = 0;
va_list ap;
sigint_allow();
do {
if (c == '\n' || !c) {
va_start(ap, prompt);
@@ -390,6 +391,8 @@ char yes_no_prompt(const char *prompt, ...)
ret = c;
} while (!ret || c != '\n');
sigint_restore();
if (c != '\n')
printf("\n");
@@ -865,6 +868,9 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
int ret = 0;
int locking_type;
/* each command should start out with sigint flag cleared */
sigint_clear();
if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv)))
return ECMD_FAILED;

View File

@@ -109,21 +109,8 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
goto error;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg->name);
if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG | LVM_WRITE))
goto error;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg->name);
goto error;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_name);
goto error;
}
if (find_lv_in_vg(vg, lv_name_new)) {
log_error("Logical volume \"%s\" already exists in "

View File

@@ -141,21 +141,8 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
return ECMD_FAILED;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg->name);
if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG | LVM_WRITE))
return ECMD_FAILED;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group %s is exported", vg->name);
return ECMD_FAILED;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group %s is read-only", lp->vg_name);
return ECMD_FAILED;
}
/* does LV exist? */
if (!(lvl = find_lv_in_vg(vg, lp->lv_name))) {
@@ -498,6 +485,8 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
"reduced", lp->lv_name);
return ECMD_FAILED;
}
if (sigint_caught())
return ECMD_FAILED;
}
}
}

View File

@@ -26,7 +26,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
uint64_t sector;
uint32_t orig_pe_alloc_count;
const char *pv_name = dev_name(pv->dev);
const char *pv_name = dev_name(get_pv_dev(pv));
const char *tag = NULL;
const char *orig_vg_name;
char uuid[64] __attribute((aligned(8)));
@@ -51,55 +51,43 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
}
/* If in a VG, must change using volume group. */
if (*pv->vg_name) {
if (*get_pv_vg_name(pv)) {
log_verbose("Finding volume group of physical volume \"%s\"",
pv_name);
if (!lock_vol(cmd, pv->vg_name, LCK_VG_WRITE)) {
log_error("Can't get lock for %s", pv->vg_name);
if (!lock_vol(cmd, get_pv_vg_name(pv), LCK_VG_WRITE)) {
log_error("Can't get lock for %s", get_pv_vg_name(pv));
return 0;
}
if (!(vg = vg_read(cmd, pv->vg_name, NULL, &consistent))) {
unlock_vg(cmd, pv->vg_name);
if (!(vg = vg_read(cmd, get_pv_vg_name(pv), NULL, &consistent))) {
unlock_vg(cmd, get_pv_vg_name(pv));
log_error("Unable to find volume group of \"%s\"",
pv_name);
return 0;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg->name);
return 0;
}
if (vg->status & EXPORTED_VG) {
unlock_vg(cmd, pv->vg_name);
log_error("Volume group \"%s\" is exported", vg->name);
return 0;
}
if (!(vg->status & LVM_WRITE)) {
unlock_vg(cmd, pv->vg_name);
log_error("Volume group \"%s\" is read-only", vg->name);
if (!vg_check_status(vg,
CLUSTERED | EXPORTED_VG | LVM_WRITE)) {
unlock_vg(cmd, get_pv_vg_name(pv));
return 0;
}
if (!(pvl = find_pv_in_vg(vg, pv_name))) {
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
log_error
("Unable to find \"%s\" in volume group \"%s\"",
pv_name, vg->name);
return 0;
}
if (tagarg && !(vg->fid->fmt->features & FMT_TAGS)) {
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
log_error("Volume group containing %s does not "
"support tags", pv_name);
return 0;
}
if (arg_count(cmd, uuid_ARG) && lvs_in_vg_activated(vg)) {
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
log_error("Volume group containing %s has active "
"logical volumes", pv_name);
return 0;
@@ -127,7 +115,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
}
if (arg_count(cmd, allocatable_ARG)) {
if (!*pv->vg_name &&
if (!*get_pv_vg_name(pv) &&
!(pv->fmt->features & FMT_ORPHAN_ALLOCATABLE)) {
log_error("Allocatability not supported by orphan "
"%s format PV %s", pv->fmt->name, pv_name);
@@ -136,21 +124,21 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
}
/* change allocatability for a PV */
if (allocatable && (pv->status & ALLOCATABLE_PV)) {
if (allocatable && (get_pv_status(pv) & ALLOCATABLE_PV)) {
log_error("Physical volume \"%s\" is already "
"allocatable", pv_name);
if (*pv->vg_name)
unlock_vg(cmd, pv->vg_name);
if (*get_pv_vg_name(pv))
unlock_vg(cmd, get_pv_vg_name(pv));
else
unlock_vg(cmd, ORPHAN);
return 1;
}
if (!allocatable && !(pv->status & ALLOCATABLE_PV)) {
if (!allocatable && !(get_pv_status(pv) & ALLOCATABLE_PV)) {
log_error("Physical volume \"%s\" is already "
"unallocatable", pv_name);
if (*pv->vg_name)
unlock_vg(cmd, pv->vg_name);
if (*get_pv_vg_name(pv))
unlock_vg(cmd, get_pv_vg_name(pv));
else
unlock_vg(cmd, ORPHAN);
return 1;
@@ -192,9 +180,9 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
return 0;
}
log_verbose("Changing uuid of %s to %s.", pv_name, uuid);
if (*pv->vg_name) {
orig_vg_name = pv->vg_name;
orig_pe_alloc_count = pv->pe_alloc_count;
if (*get_pv_vg_name(pv)) {
orig_vg_name = get_pv_vg_name(pv);
orig_pe_alloc_count = get_pv_pe_alloc_count(pv);
pv->vg_name = ORPHAN;
pv->pe_alloc_count = 0;
if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
@@ -208,15 +196,15 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
}
log_verbose("Updating physical volume \"%s\"", pv_name);
if (*pv->vg_name) {
if (*get_pv_vg_name(pv)) {
if (!vg_write(vg) || !vg_commit(vg)) {
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
log_error("Failed to store physical volume \"%s\" in "
"volume group \"%s\"", pv_name, vg->name);
return 0;
}
backup(vg);
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
} else {
if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
unlock_vg(cmd, ORPHAN);

View File

@@ -45,19 +45,22 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
/* Allow partial & exported VGs to be destroyed. */
/* We must have -ff to overwrite a non orphan */
if (pv && pv->vg_name[0] && arg_count(cmd, force_ARG) != 2) {
if (pv && !is_orphan(pv) && arg_count(cmd, force_ARG) != 2) {
log_error("Can't initialize physical volume \"%s\" of "
"volume group \"%s\" without -ff", name, pv->vg_name);
"volume group \"%s\" without -ff", name, get_pv_vg_name(pv));
return 0;
}
/* prompt */
if (pv && pv->vg_name[0] && !arg_count(cmd, yes_ARG) &&
yes_no_prompt(_really_init, name, pv->vg_name) == 'n') {
if (pv && !is_orphan(pv) && !arg_count(cmd, yes_ARG) &&
yes_no_prompt(_really_init, name, get_pv_vg_name(pv)) == 'n') {
log_print("%s: physical volume not initialized", name);
return 0;
}
if (sigint_caught())
return 0;
dev = dev_cache_get(name, cmd->filter);
/* Is there an md superblock here? */
@@ -103,12 +106,15 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
}
}
if (pv && pv->vg_name[0] && arg_count(cmd, force_ARG)) {
if (sigint_caught())
return 0;
if (pv && !is_orphan(pv) && arg_count(cmd, force_ARG)) {
log_print("WARNING: Forcing physical volume creation on "
"%s%s%s%s", name,
pv->vg_name[0] ? " of volume group \"" : "",
pv->vg_name[0] ? pv->vg_name : "",
pv->vg_name[0] ? "\"" : "");
!is_orphan(pv) ? " of volume group \"" : "",
!is_orphan(pv) ? get_pv_vg_name(pv) : "",
!is_orphan(pv) ? "\"" : "");
}
return 1;
@@ -118,7 +124,8 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
void *handle)
{
struct pvcreate_params *pp = (struct pvcreate_params *) handle;
struct physical_volume *pv, *existing_pv;
void *pv;
void *existing_pv;
struct id id, *idp = NULL;
const char *uuid = NULL;
uint64_t size = 0;
@@ -159,9 +166,9 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
uuid, restorefile);
return ECMD_FAILED;
}
pe_start = existing_pv->pe_start;
extent_size = existing_pv->pe_size;
extent_count = existing_pv->pe_count;
pe_start = get_pv_pe_start(existing_pv);
extent_size = get_pv_pe_size(existing_pv);
extent_count = get_pv_pe_count(existing_pv);
}
if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) {
@@ -172,6 +179,9 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
if (!pvcreate_check(cmd, pv_name))
goto error;
if (sigint_caught())
goto error;
if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) {
log_error("Physical volume size may not be negative");
goto error;
@@ -210,10 +220,10 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
}
log_verbose("Set up physical volume for \"%s\" with %" PRIu64
" available sectors", pv_name, pv->size);
" available sectors", pv_name, get_pv_size(pv));
/* Wipe existing label first */
if (!label_remove(pv->dev)) {
if (!label_remove(get_pv_dev(pv))) {
log_error("Failed to wipe existing label on %s", pv_name);
goto error;
}
@@ -235,7 +245,8 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
log_very_verbose("Writing physical volume data to disk \"%s\"",
pv_name);
if (!(pv_write(cmd, pv, &mdas, arg_int64_value(cmd, labelsector_ARG,
if (!(pv_write(cmd, (struct physical_volume *)pv, &mdas,
arg_int64_value(cmd, labelsector_ARG,
DEFAULT_LABELSECTOR)))) {
log_error("Failed to write physical volume \"%s\"", pv_name);
goto error;
@@ -307,6 +318,8 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
r = pvcreate_single(cmd, argv[i], &pp);
if (r > ret)
ret = r;
if (sigint_caught())
return ret;
}
return ret;

View File

@@ -19,36 +19,48 @@ static int _pvdisplay_single(struct cmd_context *cmd,
struct volume_group *vg __attribute((unused)),
struct physical_volume *pv, void *handle)
{
struct pv_list *pvl;
int consistent = 0;
int ret = ECMD_PROCESSED;
uint64_t size;
const char *pv_name = dev_name(pv->dev);
const char *pv_name = dev_name(get_pv_dev(pv));
if (pv->vg_name) {
if (!lock_vol(cmd, pv->vg_name, LCK_VG_READ)) {
log_error("Can't lock %s: skipping", pv->vg_name);
if (get_pv_vg_name(pv)) {
if (!lock_vol(cmd, get_pv_vg_name(pv), LCK_VG_READ)) {
log_error("Can't lock %s: skipping", get_pv_vg_name(pv));
return ECMD_FAILED;
}
if (!(vg = vg_read(cmd, pv->vg_name, (char *)&pv->vgid, &consistent))) {
log_error("Can't read %s: skipping", pv->vg_name);
if (!(vg = vg_read(cmd, get_pv_vg_name(pv), (char *)&pv->vgid, &consistent))) {
log_error("Can't read %s: skipping", get_pv_vg_name(pv));
goto out;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s",
vg->name);
if (!vg_check_status(vg, CLUSTERED)) {
ret = ECMD_FAILED;
goto out;
}
}
if (!*pv->vg_name)
size = pv->size;
/*
* Replace possibly incomplete PV structure with new one
* allocated in vg_read() path.
*/
if (!(pvl = find_pv_in_vg(vg, pv_name))) {
log_error("Unable to find \"%s\" in volume group \"%s\"",
pv_name, vg->name);
ret = ECMD_FAILED;
goto out;
}
pv = pvl->pv;
}
if (!*get_pv_vg_name(pv))
size = get_pv_size(pv);
else
size = (pv->pe_count - pv->pe_alloc_count) * pv->pe_size;
size = (get_pv_pe_count(pv) - get_pv_pe_alloc_count(pv)) *
get_pv_pe_size(pv);
if (arg_count(cmd, short_ARG)) {
log_print("Device \"%s\" has a capacity of %s", pv_name,
@@ -56,11 +68,11 @@ static int _pvdisplay_single(struct cmd_context *cmd,
goto out;
}
if (pv->status & EXPORTED_VG)
if (get_pv_status(pv) & EXPORTED_VG)
log_print("Physical volume \"%s\" of volume group \"%s\" "
"is exported", pv_name, pv->vg_name);
"is exported", pv_name, get_pv_vg_name(pv));
if (!pv->vg_name)
if (!get_pv_vg_name(pv))
log_print("\"%s\" is a new physical volume of \"%s\"",
pv_name, display_size(cmd, size));
@@ -71,12 +83,12 @@ static int _pvdisplay_single(struct cmd_context *cmd,
pvdisplay_full(cmd, pv, handle);
if (!arg_count(cmd, maps_ARG))
goto out;
if (arg_count(cmd, maps_ARG))
pvdisplay_segments(pv);
out:
if (pv->vg_name)
unlock_vg(cmd, pv->vg_name);
if (get_pv_vg_name(pv))
unlock_vg(cmd, get_pv_vg_name(pv));
return ret;
}

View File

@@ -66,20 +66,7 @@ static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname)
return NULL;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vgname);
return NULL;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vgname);
unlock_vg(cmd, vgname);
return NULL;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vgname);
if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG | LVM_WRITE)) {
unlock_vg(cmd, vgname);
return NULL;
}
@@ -113,7 +100,7 @@ static struct list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
pvl = list_item(pvh, struct pv_list);
/* Don't allocate onto the PV we're clearing! */
if ((alloc != ALLOC_ANYWHERE) && (pvl->pv->dev == pv->dev)) {
if ((alloc != ALLOC_ANYWHERE) && (pvl->pv->dev == get_pv_dev(pv))) {
list_del(&pvl->list);
continue;
}
@@ -294,7 +281,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
}
if (arg_count(cmd, name_ARG)) {
if (!(lv_name = _extract_lvname(cmd, pv->vg_name,
if (!(lv_name = _extract_lvname(cmd, get_pv_vg_name(pv),
arg_value(cmd, name_ARG)))) {
stack;
return EINVALID_CMD_LINE;
@@ -302,14 +289,14 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
}
/* Read VG */
log_verbose("Finding volume group \"%s\"", pv->vg_name);
log_verbose("Finding volume group \"%s\"", get_pv_vg_name(pv));
if (!(vg = _get_vg(cmd, pv->vg_name))) {
if (!(vg = _get_vg(cmd, get_pv_vg_name(pv)))) {
stack;
return ECMD_FAILED;
}
if ((lv_mirr = find_pvmove_lv(vg, pv->dev, PVMOVE))) {
if ((lv_mirr = find_pvmove_lv(vg, get_pv_dev(pv), PVMOVE))) {
log_print("Detected pvmove in progress for %s", pv_name);
if (argc || lv_name)
log_error("Ignoring remaining command line arguments");
@@ -317,7 +304,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) {
log_error
("ABORTING: Failed to generate list of moving LVs");
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ECMD_FAILED;
}
@@ -325,7 +312,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
if (!activate_lv_excl(cmd, lv_mirr)) {
log_error
("ABORTING: Temporary mirror activation failed.");
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ECMD_FAILED;
}
@@ -335,7 +322,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
if (!(source_pvl = create_pv_list(cmd->mem, vg, 1,
&pv_name_arg, 0))) {
stack;
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ECMD_FAILED;
}
@@ -347,12 +334,12 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
if (!(allocatable_pvs = _get_allocatable_pvs(cmd, argc, argv,
vg, pv, alloc))) {
stack;
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ECMD_FAILED;
}
if (!archive(vg)) {
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
stack;
return ECMD_FAILED;
}
@@ -361,7 +348,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
allocatable_pvs, alloc,
&lvs_changed))) {
stack;
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ECMD_FAILED;
}
}
@@ -369,7 +356,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
/* Lock lvs_changed for exclusive use and activate (with old metadata) */
if (!activate_lvs_excl(cmd, lvs_changed)) {
stack;
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ECMD_FAILED;
}
@@ -381,13 +368,13 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
if (!_update_metadata
(cmd, vg, lv_mirr, lvs_changed, first_time)) {
stack;
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ECMD_FAILED;
}
}
/* LVs are all in status LOCKED */
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ECMD_PROCESSED;
}
@@ -482,7 +469,7 @@ static struct volume_group *_get_move_vg(struct cmd_context *cmd,
return NULL;
}
return _get_vg(cmd, pv->vg_name);
return _get_vg(cmd, get_pv_vg_name(pv));
}
static struct poll_functions _pvmove_fns = {

View File

@@ -43,20 +43,20 @@ static int pvremove_check(struct cmd_context *cmd, const char *name)
}
/* orphan ? */
if (!pv->vg_name[0])
if (is_orphan(pv))
return 1;
/* Allow partial & exported VGs to be destroyed. */
/* we must have -ff to overwrite a non orphan */
if (arg_count(cmd, force_ARG) < 2) {
log_error("Can't pvremove physical volume \"%s\" of "
"volume group \"%s\" without -ff", name, pv->vg_name);
"volume group \"%s\" without -ff", name, get_pv_vg_name(pv));
return 0;
}
/* prompt */
if (!arg_count(cmd, yes_ARG) &&
yes_no_prompt(_really_wipe, name, pv->vg_name) == 'n') {
yes_no_prompt(_really_wipe, name, get_pv_vg_name(pv)) == 'n') {
log_print("%s: physical volume label not removed", name);
return 0;
}
@@ -64,9 +64,9 @@ static int pvremove_check(struct cmd_context *cmd, const char *name)
if (arg_count(cmd, force_ARG)) {
log_print("WARNING: Wiping physical volume label from "
"%s%s%s%s", name,
pv->vg_name[0] ? " of volume group \"" : "",
pv->vg_name[0] ? pv->vg_name : "",
pv->vg_name[0] ? "\"" : "");
!is_orphan(pv) ? " of volume group \"" : "",
!is_orphan(pv) ? get_pv_vg_name(pv) : "",
!is_orphan(pv) ? "\"" : "");
}
return 1;

View File

@@ -33,7 +33,7 @@ static int _pvresize_single(struct cmd_context *cmd,
uint64_t size = 0;
uint32_t new_pe_count = 0;
struct list mdas;
const char *pv_name = dev_name(pv->dev);
const char *pv_name = dev_name(get_pv_dev(pv));
struct pvresize_params *params = (struct pvresize_params *) handle;
const char *vg_name;
@@ -41,7 +41,7 @@ static int _pvresize_single(struct cmd_context *cmd,
params->total++;
if (!*pv->vg_name) {
if (!*get_pv_vg_name(pv)) {
vg_name = ORPHAN;
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
@@ -63,10 +63,10 @@ static int _pvresize_single(struct cmd_context *cmd,
return ECMD_FAILED;
}
} else {
vg_name = pv->vg_name;
vg_name = get_pv_vg_name(pv);
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
log_error("Can't get lock for %s", pv->vg_name);
log_error("Can't get lock for %s", get_pv_vg_name(pv));
return ECMD_FAILED;
}
@@ -77,22 +77,8 @@ static int _pvresize_single(struct cmd_context *cmd,
return ECMD_FAILED;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG | LVM_WRITE)) {
unlock_vg(cmd, vg_name);
log_error("Skipping clustered volume group %s", vg->name);
return ECMD_FAILED;
}
if (vg->status & EXPORTED_VG) {
unlock_vg(cmd, vg_name);
log_error("Volume group \"%s\" is exported", vg->name);
return ECMD_FAILED;
}
if (!(vg->status & LVM_WRITE)) {
unlock_vg(cmd, pv->vg_name);
log_error("Volume group \"%s\" is read-only", vg->name);
return ECMD_FAILED;
}
@@ -117,7 +103,7 @@ static int _pvresize_single(struct cmd_context *cmd,
}
/* Get new size */
if (!dev_get_size(pv->dev, &size)) {
if (!dev_get_size(get_pv_dev(pv), &size)) {
log_error("%s: Couldn't get size.", pv_name);
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
@@ -128,7 +114,7 @@ static int _pvresize_single(struct cmd_context *cmd,
log_print("WARNING: %s: Overriding real size. "
"You could lose data.", pv_name);
log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64
" sectors.", pv_name, params->new_size, pv->size);
" sectors.", pv_name, params->new_size, get_pv_size(pv));
size = params->new_size;
}
@@ -139,9 +125,9 @@ static int _pvresize_single(struct cmd_context *cmd,
return ECMD_FAILED;
}
if (size < pv->pe_start) {
if (size < get_pv_pe_start(pv)) {
log_error("%s: Size must exceed physical extent start of "
"%" PRIu64 " sectors.", pv_name, pv->pe_start);
"%" PRIu64 " sectors.", pv_name, get_pv_pe_start(pv));
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
}
@@ -149,14 +135,14 @@ static int _pvresize_single(struct cmd_context *cmd,
pv->size = size;
if (vg) {
pv->size -= pv->pe_start;
new_pe_count = pv->size / vg->extent_size;
pv->size -= get_pv_pe_start(pv);
new_pe_count = get_pv_size(pv) / vg->extent_size;
if (!new_pe_count) {
log_error("%s: Size must leave space for at "
"least one physical extent of "
"%" PRIu32 " sectors.", pv_name,
pv->pe_size);
get_pv_pe_size(pv));
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
}
@@ -169,12 +155,12 @@ static int _pvresize_single(struct cmd_context *cmd,
}
log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
pv_name, pv->size);
pv_name, get_pv_size(pv));
log_verbose("Updating physical volume \"%s\"", pv_name);
if (*pv->vg_name) {
if (*get_pv_vg_name(pv)) {
if (!vg_write(vg) || !vg_commit(vg)) {
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
log_error("Failed to store physical volume \"%s\" in "
"volume group \"%s\"", pv_name, vg->name);
return ECMD_FAILED;

View File

@@ -31,7 +31,7 @@ static void _pvscan_display_single(struct cmd_context *cmd,
/* short listing? */
if (arg_count(cmd, short_ARG) > 0) {
log_print("%s", dev_name(pv->dev));
log_print("%s", dev_name(get_pv_dev(pv)));
return;
}
@@ -48,7 +48,7 @@ static void _pvscan_display_single(struct cmd_context *cmd,
memset(pv_tmp_name, 0, sizeof(pv_tmp_name));
vg_name_len = strlen(pv->vg_name) + 1;
vg_name_len = strlen(get_pv_vg_name(pv)) + 1;
if (arg_count(cmd, uuid_ARG)) {
if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
@@ -57,42 +57,43 @@ static void _pvscan_display_single(struct cmd_context *cmd,
}
sprintf(pv_tmp_name, "%-*s with UUID %s",
pv_max_name_len - 2, dev_name(pv->dev), uuid);
pv_max_name_len - 2, dev_name(get_pv_dev(pv)), uuid);
} else {
sprintf(pv_tmp_name, "%s", dev_name(pv->dev));
sprintf(pv_tmp_name, "%s", dev_name(get_pv_dev(pv)));
}
if (!*pv->vg_name) {
if (!*get_pv_vg_name(pv)) {
log_print("PV %-*s %-*s %s [%s]",
pv_max_name_len, pv_tmp_name,
vg_max_name_len, " ",
pv->fmt ? pv->fmt->name : " ",
display_size(cmd, pv->size));
display_size(cmd, get_pv_size(pv)));
return;
}
if (pv->status & EXPORTED_VG) {
strncpy(vg_name_this, pv->vg_name, vg_name_len);
if (get_pv_status(pv) & EXPORTED_VG) {
strncpy(vg_name_this, get_pv_vg_name(pv), vg_name_len);
log_print("PV %-*s is in exported VG %s "
"[%s / %s free]",
pv_max_name_len, pv_tmp_name,
vg_name_this,
display_size(cmd, (uint64_t) pv->pe_count *
pv->pe_size),
display_size(cmd, (uint64_t) (pv->pe_count -
pv->pe_alloc_count)
* pv->pe_size));
display_size(cmd, (uint64_t) get_pv_pe_count(pv) *
get_pv_pe_size(pv)),
display_size(cmd, (uint64_t) (get_pv_pe_count(pv) -
get_pv_pe_alloc_count(pv))
* get_pv_pe_size(pv)));
return;
}
sprintf(vg_tmp_name, "%s", pv->vg_name);
sprintf(vg_tmp_name, "%s", get_pv_vg_name(pv));
log_print("PV %-*s VG %-*s %s [%s / %s free]", pv_max_name_len,
pv_tmp_name, vg_max_name_len, vg_tmp_name,
pv->fmt ? pv->fmt->name : " ",
display_size(cmd, (uint64_t) pv->pe_count * pv->pe_size),
display_size(cmd,
(uint64_t) (pv->pe_count - pv->pe_alloc_count) *
pv->pe_size));
display_size(cmd, (uint64_t) get_pv_pe_count(pv) *
get_pv_pe_size(pv)),
display_size(cmd, (uint64_t) (get_pv_pe_count(pv) -
get_pv_pe_alloc_count(pv)) *
get_pv_pe_size(pv)));
return;
}
@@ -135,8 +136,8 @@ int pvscan(struct cmd_context *cmd, int argc __attribute((unused)),
pv = pvl->pv;
if ((arg_count(cmd, exported_ARG)
&& !(pv->status & EXPORTED_VG))
|| (arg_count(cmd, novolumegroup_ARG) && (*pv->vg_name))) {
&& !(get_pv_status(pv) & EXPORTED_VG))
|| (arg_count(cmd, novolumegroup_ARG) && (*get_pv_vg_name(pv)))) {
list_del(&pvl->list);
continue;
}
@@ -153,22 +154,22 @@ int pvscan(struct cmd_context *cmd, int argc __attribute((unused)),
********/
pvs_found++;
if (!*pv->vg_name) {
if (!*get_pv_vg_name(pv)) {
new_pvs_found++;
size_new += pv->size;
size_total += pv->size;
size_new += get_pv_size(pv);
size_total += get_pv_size(pv);
} else
size_total += pv->pe_count * pv->pe_size;
size_total += get_pv_pe_count(pv) * get_pv_pe_size(pv);
}
/* find maximum pv name length */
pv_max_name_len = vg_max_name_len = 0;
list_iterate_items(pvl, pvslist) {
pv = pvl->pv;
len = strlen(dev_name(pv->dev));
len = strlen(dev_name(get_pv_dev(pv)));
if (pv_max_name_len < len)
pv_max_name_len = len;
len = strlen(pv->vg_name);
len = strlen(get_pv_vg_name(pv));
if (vg_max_name_len < len)
vg_max_name_len = len;
}

View File

@@ -61,19 +61,17 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv = pvseg->pv;
int ret = ECMD_PROCESSED;
if (!lock_vol(cmd, pv->vg_name, LCK_VG_READ)) {
log_error("Can't lock %s: skipping", pv->vg_name);
if (!lock_vol(cmd, get_pv_vg_name(pv), LCK_VG_READ)) {
log_error("Can't lock %s: skipping", get_pv_vg_name(pv));
return ECMD_FAILED;
}
if (!(vg = vg_read(cmd, pv->vg_name, NULL, &consistent))) {
log_error("Can't read %s: skipping", pv->vg_name);
if (!(vg = vg_read(cmd, get_pv_vg_name(pv), NULL, &consistent))) {
log_error("Can't read %s: skipping", get_pv_vg_name(pv));
goto out;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg->name);
if (!vg_check_status(vg, CLUSTERED)) {
ret = ECMD_FAILED;
goto out;
}
@@ -82,7 +80,7 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg,
ret = ECMD_FAILED;
out:
unlock_vg(cmd, pv->vg_name);
unlock_vg(cmd, get_pv_vg_name(pv));
return ret;
}
@@ -108,21 +106,18 @@ static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg,
int consistent = 0;
int ret = ECMD_PROCESSED;
if (pv->vg_name) {
if (!lock_vol(cmd, pv->vg_name, LCK_VG_READ)) {
log_error("Can't lock %s: skipping", pv->vg_name);
if (get_pv_vg_name(pv)) {
if (!lock_vol(cmd, get_pv_vg_name(pv), LCK_VG_READ)) {
log_error("Can't lock %s: skipping", get_pv_vg_name(pv));
return ECMD_FAILED;
}
if (!(vg = vg_read(cmd, pv->vg_name, (char *)&pv->vgid, &consistent))) {
log_error("Can't read %s: skipping", pv->vg_name);
if (!(vg = vg_read(cmd, get_pv_vg_name(pv), (char *)&pv->vgid, &consistent))) {
log_error("Can't read %s: skipping", get_pv_vg_name(pv));
goto out;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s",
vg->name);
if (!vg_check_status(vg, CLUSTERED)) {
ret = ECMD_FAILED;
goto out;
}
@@ -132,8 +127,8 @@ static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg,
ret = ECMD_FAILED;
out:
if (pv->vg_name)
unlock_vg(cmd, pv->vg_name);
if (get_pv_vg_name(pv))
unlock_vg(cmd, get_pv_vg_name(pv));
return ret;
}

View File

@@ -209,6 +209,8 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
ret = process_single(cmd, lvl->lv, handle);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
if (lvargs_supplied && lvargs_matched != list_size(arg_lvnames)) {
@@ -357,11 +359,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
log_error("Volume group \"%s\" "
"not found", vgname);
else {
if ((vg->status & CLUSTERED) &&
!locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume "
"group %s", vgname);
if (!vg_check_status(vg, CLUSTERED)) {
if (ret_max < ECMD_FAILED)
ret_max = ECMD_FAILED;
continue;
@@ -377,10 +375,8 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
}
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
if (!vg_check_status(vg, CLUSTERED)) {
unlock_vg(cmd, vgname);
log_error("Skipping clustered volume group %s", vgname);
if (ret_max < ECMD_FAILED)
ret_max = ECMD_FAILED;
continue;
@@ -413,6 +409,8 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
unlock_vg(cmd, vgname);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
return ret_max;
@@ -435,6 +433,8 @@ int process_each_segment_in_pv(struct cmd_context *cmd,
ret = process_single(cmd, vg, pvseg, handle);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
return ret_max;
@@ -455,6 +455,8 @@ int process_each_segment_in_lv(struct cmd_context *cmd,
ret = process_single(cmd, seg, handle);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
return ret_max;
@@ -485,9 +487,7 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
return ECMD_FAILED;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg_name);
if (!vg_check_status(vg, CLUSTERED)) {
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
}
@@ -506,6 +506,9 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
ret_max = ret;
}
if (sigint_caught())
return ret_max;
unlock_vg(cmd, vg_name);
return ret_max;
@@ -581,6 +584,8 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
&arg_vgnames,
lock_type, consistent, handle,
ret_max, process_single);
if (sigint_caught())
return ret_max;
}
} else {
list_iterate_items(sl, vgnames) {
@@ -591,6 +596,8 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
&arg_vgnames,
lock_type, consistent, handle,
ret_max, process_single);
if (sigint_caught())
return ret_max;
}
}
@@ -615,6 +622,8 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
}
if ((ret = process_single(cmd, vg, pvl->pv, handle)) > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
return ret_max;
@@ -651,6 +660,8 @@ static int _process_all_devs(struct cmd_context *cmd, void *handle,
ret = process_single(cmd, NULL, pv, handle);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
dev_iter_destroy(iter);
@@ -723,6 +734,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
ret = process_single(cmd, vg, pv, handle);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
if (!list_empty(&tags) && (vgnames = get_vgs(cmd, 0)) &&
!list_empty(vgnames)) {
@@ -735,19 +748,16 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
if (!consistent)
continue;
if ((vg->status & CLUSTERED) &&
!locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume "
"group %s", sll->str);
if (!vg_check_status(vg, CLUSTERED))
continue;
}
ret = process_each_pv_in_vg(cmd, vg, &tags,
handle,
process_single);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
}
} else {
@@ -758,10 +768,14 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
process_single);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
} else if (arg_count(cmd, all_ARG)) {
ret = _process_all_devs(cmd, handle, process_single);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
} else {
log_verbose("Scanning for physical volume names");
if (!(pvslist = get_pvs(cmd)))
@@ -772,6 +786,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
handle);
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
return ret_max;
}
}
}

View File

@@ -17,28 +17,29 @@
int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv)
{
char *vg_name;
char *vg_name = NULL;
if (argc != 1) {
if (argc == 1) {
vg_name = skip_dev_dir(cmd, argv[0], NULL);
if (!validate_name(vg_name)) {
log_error("Volume group name \"%s\" is invalid", vg_name);
return ECMD_FAILED;
}
} else if (!(arg_count(cmd, list_ARG) && arg_count(cmd, file_ARG))) {
log_err("Please specify a *single* volume group to restore.");
return ECMD_FAILED;
}
vg_name = skip_dev_dir(cmd, argv[0], NULL);
if (!validate_name(vg_name)) {
log_error("Volume group name \"%s\" is invalid", vg_name);
return ECMD_FAILED;
}
/*
* FIXME: overloading the -l arg for now to display a
* list of archive files for a particular vg
*/
if (arg_count(cmd, list_ARG)) {
if (!archive_display(cmd, vg_name))
if (!(arg_count(cmd,file_ARG) ?
archive_display_file(cmd,
arg_str_value(cmd, file_ARG, "")) :
archive_display(cmd, vg_name)))
return ECMD_FAILED;
return ECMD_PROCESSED;
}

View File

@@ -114,18 +114,18 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
list_iterate_items(pvl, &vg->pvs) {
existing_pv = pvl->pv;
pe_start = existing_pv->pe_start;
pe_end = existing_pv->pe_count * existing_pv->pe_size
pe_start = get_pv_pe_start(existing_pv);
pe_end = get_pv_pe_count(existing_pv) * get_pv_pe_size(existing_pv)
+ pe_start - 1;
list_init(&mdas);
if (!(pv = pv_create(cmd->fmt, existing_pv->dev,
if (!(pv = pv_create(cmd->fmt, get_pv_dev(existing_pv),
&existing_pv->id, size,
pe_start, existing_pv->pe_count,
existing_pv->pe_size, pvmetadatacopies,
pe_start, get_pv_pe_count(existing_pv),
get_pv_pe_size(existing_pv), pvmetadatacopies,
pvmetadatasize, &mdas))) {
log_error("Failed to setup physical volume \"%s\"",
dev_name(existing_pv->dev));
dev_name(get_pv_dev(existing_pv)));
if (change_made)
log_error("Use pvcreate and vgcfgrestore to "
"repair from archived metadata.");
@@ -136,30 +136,30 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
change_made = 1;
log_verbose("Set up physical volume for \"%s\" with %" PRIu64
" available sectors", dev_name(pv->dev), pv->size);
" available sectors", dev_name(get_pv_dev(pv)), get_pv_size(pv));
/* Wipe existing label first */
if (!label_remove(pv->dev)) {
if (!label_remove(get_pv_dev(pv))) {
log_error("Failed to wipe existing label on %s",
dev_name(pv->dev));
dev_name(get_pv_dev(pv)));
log_error("Use pvcreate and vgcfgrestore to repair "
"from archived metadata.");
return ECMD_FAILED;
}
log_very_verbose("Writing physical volume data to disk \"%s\"",
dev_name(pv->dev));
dev_name(get_pv_dev(pv)));
if (!(pv_write(cmd, pv, &mdas,
arg_int64_value(cmd, labelsector_ARG,
DEFAULT_LABELSECTOR)))) {
log_error("Failed to write physical volume \"%s\"",
dev_name(pv->dev));
dev_name(get_pv_dev(pv)));
log_error("Use pvcreate and vgcfgrestore to repair "
"from archived metadata.");
return ECMD_FAILED;
}
log_verbose("Physical volume \"%s\" successfully created",
dev_name(pv->dev));
dev_name(get_pv_dev(pv)));
}

View File

@@ -59,26 +59,9 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
goto error;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg->name);
if (!vg_check_status(vg, CLUSTERED | EXPORTED_VG |
LVM_WRITE | RESIZEABLE_VG))
goto error;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg->name);
goto error;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_name);
goto error;
}
if (!(vg->status & RESIZEABLE_VG)) {
log_error("Volume group \"%s\" is not resizeable.", vg_name);
goto error;
}
/********** FIXME
log_print("maximum logical volume size is %s",

View File

@@ -41,21 +41,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
return ECMD_FAILED;
}
if ((vg_to->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg_name_to);
unlock_vg(cmd, vg_name_to);
return ECMD_FAILED;
}
if (vg_to->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg_to->name);
unlock_vg(cmd, vg_name_to);
return ECMD_FAILED;
}
if (!(vg_to->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_to->name);
if (!vg_check_status(vg_to, CLUSTERED | EXPORTED_VG | LVM_WRITE)) {
unlock_vg(cmd, vg_name_to);
return ECMD_FAILED;
}
@@ -73,21 +59,8 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
goto error;
}
if ((vg_from->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg_name_from);
if (!vg_check_status(vg_from, CLUSTERED | EXPORTED_VG | LVM_WRITE))
goto error;
}
if (vg_from->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg_from->name);
goto error;
}
if (!(vg_from->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_from->name);
goto error;
}
if ((active = lvs_in_vg_activated(vg_from))) {
log_error("Logical volumes in \"%s\" must be inactive",

View File

@@ -185,7 +185,7 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
/* FIXME Also check for segs on deleted LVs */
pv = seg_pv(seg, s);
if (!pv || !pv->dev) {
if (!pv || !get_pv_dev(pv)) {
if (arg_count(cmd, mirrorsonly_ARG) &&
!(lv->status & MIRROR_IMAGE)) {
log_error("Non-mirror-image LV %s found: can't remove.", lv->name);
@@ -365,9 +365,9 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
void *handle __attribute((unused)))
{
struct pv_list *pvl;
const char *name = dev_name(pv->dev);
const char *name = dev_name(get_pv_dev(pv));
if (pv->pe_alloc_count) {
if (get_pv_pe_alloc_count(pv)) {
log_error("Physical volume \"%s\" still in use", name);
return ECMD_FAILED;
}
@@ -391,14 +391,14 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
pv->vg_name = ORPHAN;
pv->status = ALLOCATABLE_PV;
if (!dev_get_size(pv->dev, &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(pv->dev));
if (!dev_get_size(get_pv_dev(pv), &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(get_pv_dev(pv)));
return ECMD_FAILED;
}
vg->pv_count--;
vg->free_count -= pv->pe_count - pv->pe_alloc_count;
vg->extent_count -= pv->pe_count;
vg->free_count -= get_pv_pe_count(pv) - get_pv_pe_alloc_count(pv);
vg->extent_count -= get_pv_pe_count(pv);
if (!vg_write(vg) || !vg_commit(vg)) {
log_error("Removal of physical volume \"%s\" from "
@@ -484,9 +484,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
if (vg && (vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg->name);
if (vg && !vg_check_status(vg, CLUSTERED)) {
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
}
@@ -506,10 +504,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
}
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s",
vg->name);
if (!vg_check_status(vg, CLUSTERED)) {
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
}

View File

@@ -54,12 +54,12 @@ static int vgremove_single(struct cmd_context *cmd, const char *vg_name,
list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
log_verbose("Removing physical volume \"%s\" from "
"volume group \"%s\"", dev_name(pv->dev), vg_name);
"volume group \"%s\"", dev_name(get_pv_dev(pv)), vg_name);
pv->vg_name = ORPHAN;
pv->status = ALLOCATABLE_PV;
if (!dev_get_size(pv->dev, &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(pv->dev));
if (!dev_get_size(get_pv_dev(pv), &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(get_pv_dev(pv)));
ret = ECMD_FAILED;
continue;
}
@@ -68,7 +68,7 @@ static int vgremove_single(struct cmd_context *cmd, const char *vg_name,
if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
log_error("Failed to remove physical volume \"%s\""
" from volume group \"%s\"",
dev_name(pv->dev), vg_name);
dev_name(get_pv_dev(pv)), vg_name);
ret = ECMD_FAILED;
}
}

View File

@@ -102,21 +102,13 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
if ((vg_old->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg_old->name);
if (!vg_check_status(vg_old, CLUSTERED | LVM_WRITE)) {
unlock_vg(cmd, vg_name_old);
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);
log_error("Volume group \"%s\" is read-only", vg_old->name);
return ECMD_FAILED;
}
/* Don't return failure for EXPORTED_VG */
vg_check_status(vg_old, EXPORTED_VG);
if (lvs_in_vg_activated_by_uuid_only(vg_old)) {
unlock_vg(cmd, vg_name_old);

View File

@@ -35,11 +35,11 @@ static int _move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
pv = list_item(pvl, struct pv_list)->pv;
vg_from->extent_count -= pv->pe_count;
vg_to->extent_count += pv->pe_count;
vg_from->extent_count -= get_pv_pe_count(pv);
vg_to->extent_count += get_pv_pe_count(pv);
vg_from->free_count -= pv->pe_count - pv->pe_alloc_count;
vg_to->free_count += pv->pe_count - pv->pe_alloc_count;
vg_from->free_count -= get_pv_pe_count(pv) - get_pv_pe_alloc_count(pv);
vg_to->free_count += get_pv_pe_count(pv) - get_pv_pe_alloc_count(pv);
return 1;
}
@@ -105,7 +105,7 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
continue;
}
log_error("Physical Volume %s not found",
dev_name(pv->dev));
dev_name(get_pv_dev(pv)));
return 0;
}
@@ -145,13 +145,16 @@ static int _move_snapshots(struct volume_group *vg_from,
list_iterate_items(seg, &lv->segments) {
cow_from = _lv_is_in_vg(vg_from, seg->cow);
origin_from = _lv_is_in_vg(vg_from, seg->origin);
if (cow_from && origin_from)
continue;
if ((!cow_from && origin_from) ||
(cow_from && !origin_from)) {
log_error("Can't split snapshot %s between"
" two Volume Groups", seg->cow->name);
return 0;
}
}
if (cow_from && origin_from)
continue;
if ((!cow_from && origin_from) || (cow_from && !origin_from)) {
log_error("Snapshot %s split", seg->cow->name);
return 0;
}
/* Move this snapshot */
list_del(lvh);
@@ -190,7 +193,8 @@ static int _move_mirrors(struct volume_group *vg_from,
if ((seg_in && seg_in < seg->area_count) ||
(seg_in && seg->log_lv && !log_in) ||
(!seg_in && seg->log_lv && log_in)) {
log_error("Mirror %s split", lv->name);
log_error("Can't split mirror %s between "
"two Volume Groups", lv->name);
return 0;
}
@@ -247,27 +251,8 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
if ((vg_from->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg_from->name);
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
}
if (vg_from->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg_from->name);
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
}
if (!(vg_from->status & RESIZEABLE_VG)) {
log_error("Volume group \"%s\" is not resizeable", vg_from->name);
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
}
if (!(vg_from->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_from->name);
if (!vg_check_status(vg_from, CLUSTERED | EXPORTED_VG |
RESIZEABLE_VG | LVM_WRITE)) {
unlock_vg(cmd, vg_name_from);
return ECMD_FAILED;
}