mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-29 06:57:46 +03:00
Compare commits
45 Commits
dm_v1_02_1
...
dm_v1_02_2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd2a3f40e1 | ||
|
|
78f76c1690 | ||
|
|
4788066a5f | ||
|
|
10e4254e7d | ||
|
|
0106e4df9d | ||
|
|
8ac718a3a2 | ||
|
|
46d45273a1 | ||
|
|
8da9ec3599 | ||
|
|
01fdf84d69 | ||
|
|
cc78386e75 | ||
|
|
3755157c61 | ||
|
|
80f8436f0a | ||
|
|
f88a4b7760 | ||
|
|
de229b8ab0 | ||
|
|
a3ba37e45e | ||
|
|
50c779b3c6 | ||
|
|
192372e1c3 | ||
|
|
f88fd88c38 | ||
|
|
6e15145af1 | ||
|
|
4b5fad4e48 | ||
|
|
7a13e71c80 | ||
|
|
3c10943900 | ||
|
|
696b8811c2 | ||
|
|
9fd2c8602a | ||
|
|
a3636a5af4 | ||
|
|
f2e5f07718 | ||
|
|
16c6fdde60 | ||
|
|
2155c93426 | ||
|
|
c394631e4c | ||
|
|
8b370b7cc1 | ||
|
|
607db9971c | ||
|
|
6768f64e2f | ||
|
|
f1813b1cc6 | ||
|
|
fb665bd0dd | ||
|
|
65dda2ef3d | ||
|
|
b162b992af | ||
|
|
67a3a3d130 | ||
|
|
92cd9bf7d2 | ||
|
|
bf97034485 | ||
|
|
1ded1fc509 | ||
|
|
e0592c58b3 | ||
|
|
5ead2706b4 | ||
|
|
52ada4853c | ||
|
|
c2b27a8298 | ||
|
|
3934c1d437 |
22
WHATS_NEW
22
WHATS_NEW
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
756
daemons/clvmd/clvmd-openais.c
Normal file
756
daemons/clvmd/clvmd-openais.c
Normal 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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -187,7 +187,7 @@ int device_is_usable(dev_t dev)
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
/* 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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
337
tools/dmsetup.c
337
tools/dmsetup.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user