mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-28 04:23:49 +03:00
Compare commits
89 Commits
dm_v1_00_2
...
dm_v1_01_0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33d516748f | ||
|
|
de17f6f0fd | ||
|
|
756731fc02 | ||
|
|
e46be0415f | ||
|
|
aa02fb50bf | ||
|
|
8b6cd9c772 | ||
|
|
cdd0d3351a | ||
|
|
8b6d584529 | ||
|
|
f49fdd4141 | ||
|
|
b26e1be81a | ||
|
|
bacab38d7f | ||
|
|
701c05ce96 | ||
|
|
438c452585 | ||
|
|
0a7a1eff3f | ||
|
|
87e743e381 | ||
|
|
a03f1b3d55 | ||
|
|
2d8dc3d243 | ||
|
|
b982232cc5 | ||
|
|
61c8d728ac | ||
|
|
851a2bf855 | ||
|
|
e0bdde3630 | ||
|
|
6a0dcd7f0e | ||
|
|
75f0b4c879 | ||
|
|
db536a9504 | ||
|
|
0fb114dede | ||
|
|
e703342179 | ||
|
|
35c8f4a611 | ||
|
|
7c89ae44a9 | ||
|
|
84fe06da22 | ||
|
|
806318c8b3 | ||
|
|
3aac2e1822 | ||
|
|
168baef433 | ||
|
|
6dba6cd78d | ||
|
|
502250d08f | ||
|
|
7395f0e680 | ||
|
|
494d3fdaca | ||
|
|
7b86a157de | ||
|
|
0988c41785 | ||
|
|
522db1bf01 | ||
|
|
06f066f90d | ||
|
|
f37b20677b | ||
|
|
cd2eac1032 | ||
|
|
8ac38d58d7 | ||
|
|
4c80cc313a | ||
|
|
1c65fee9b4 | ||
|
|
90dda7edc1 | ||
|
|
da054fae20 | ||
|
|
bdb6611e30 | ||
|
|
9284f973f1 | ||
|
|
2bfd64c3c9 | ||
|
|
939d24cce5 | ||
|
|
27b0183c46 | ||
|
|
d14efacac7 | ||
|
|
150a002c40 | ||
|
|
ce0def3bd8 | ||
|
|
ee20fa97c2 | ||
|
|
7403b7d700 | ||
|
|
87ef173e0a | ||
|
|
52a3fb6bc7 | ||
|
|
92e2a257a6 | ||
|
|
32e175752c | ||
|
|
d43f7180dc | ||
|
|
0129c2b0fc | ||
|
|
4ed1990001 | ||
|
|
5bd6ab27ae | ||
|
|
f3593b89fa | ||
|
|
23d84b2310 | ||
|
|
fdc49402ec | ||
|
|
5457c133e1 | ||
|
|
292e588ee3 | ||
|
|
243494c25e | ||
|
|
e4365f3706 | ||
|
|
310f3038d3 | ||
|
|
4e6033273d | ||
|
|
73718586d3 | ||
|
|
011abe61e8 | ||
|
|
fe3a37f89d | ||
|
|
8aea44e77b | ||
|
|
5529aec0d6 | ||
|
|
369549d23f | ||
|
|
181ea9a381 | ||
|
|
76b8f2854e | ||
|
|
320e5198f9 | ||
|
|
e522539e2d | ||
|
|
7c996b83d2 | ||
|
|
3dd354d7aa | ||
|
|
f4ad6e2157 | ||
|
|
8b170dc2bf | ||
|
|
dcb9d779bf |
86
WHATS_NEW
86
WHATS_NEW
@@ -1,10 +1,94 @@
|
||||
Version 2.00.33 -
|
||||
Version 2.01.09 -
|
||||
=================================
|
||||
|
||||
Version 2.01.08 - 22nd March 2005
|
||||
=================================
|
||||
Add clustered attribute so vgchange can identify clustered VGs w/o locking.
|
||||
Improve detection of external changes affecting internal cache.
|
||||
Add 'already in device cache' debug message.
|
||||
Add -a to pvdisplay -C.
|
||||
Avoid rmdir opendir error messsages when dir was already removed.
|
||||
Tighten signal handlers.
|
||||
Avoid some compiler warnings.
|
||||
Additional rename failure error message.
|
||||
read/write may be macros.
|
||||
clvmd: don't take out lvm thread lock at startup, it only protects jobs list.
|
||||
|
||||
Version 2.01.07 - 8th March 2005
|
||||
================================
|
||||
Cope with new devices appearing by rescanning /dev if a uuid can't be found.
|
||||
Remove DESTDIR from LVM_SHARED_PATH.
|
||||
clvmd fixes: make FDs close-on-exec
|
||||
gulm unlocks VG & orphan locks at startup in case they are stale
|
||||
gulm now unlocks VG & orphan locks if client dies.
|
||||
|
||||
Version 2.01.06 - 1st March 2005
|
||||
================================
|
||||
Suppress 'open failed' error messages during scanning.
|
||||
Option to suppress warnings of file descriptors left open.
|
||||
Fix default value of metadatacopies in documentation (2->1).
|
||||
Fix clvmd-gulm locking.
|
||||
./configure --enable-debug now enables debugging code in clvmd.
|
||||
Fix clvmd-gulm node up/down code so it actually works.
|
||||
clvmd-gulm now releases locks when shut down.
|
||||
|
||||
Version 2.01.05 - 18th February 2005
|
||||
====================================
|
||||
Static binary invokes dynamic binary if appropriate.
|
||||
Make clvmd config check a little more tolerant.
|
||||
gulm clvmd can now cope with >1 message arriving in a TCP message.
|
||||
|
||||
Version 2.01.04 - 9th February 2005
|
||||
===================================
|
||||
Add fixed offset to imported pool minor numbers.
|
||||
Update binary pathnames in clvmd_init_rhel4.
|
||||
lvm2cmd.so should skip the check for open fds.
|
||||
Remove unused -f from pvmove.
|
||||
Gulm clvmd doesn't report "connection refused" errors.
|
||||
clvmd does a basic config file sanity check at startup.
|
||||
Fix potential thread shutdown race in clvmd.
|
||||
|
||||
Version 2.01.03 - 1st February 2005
|
||||
===================================
|
||||
More 64-bit display/report fixes.
|
||||
More informative startup mesg if can't create /etc/lvm.
|
||||
Fix snapshot device size bug (since 2.01.01).
|
||||
clvmd announces startup and cluster connection in syslog.
|
||||
Gulm clvmd doesn't hang trying to talk to a rebooted node.
|
||||
Gulm clvmd doesn't print cman error on startup.
|
||||
|
||||
Version 2.01.02 - 21st January 2005
|
||||
===================================
|
||||
Update clvmd_init_rhel4: use lvm.static and don't load dlm.
|
||||
Fix some size_t printing.
|
||||
Fix 64 bit xlate consts.
|
||||
Split out pool sptype_names to avoid unused const.
|
||||
Always fail if random id generation fails.
|
||||
Recognise gnbd devices.
|
||||
Fix clvmd startup bug introduced in cman/gulm amalgamation.
|
||||
Improve reporting of node-specific locking errors.
|
||||
|
||||
Version 2.01.01 - 19th January 2005
|
||||
===================================
|
||||
Fix clvmd lv_info_by_lvid open_count.
|
||||
Store snapshot and origin sizes separately.
|
||||
Update vgcreate man page.
|
||||
|
||||
Version 2.01.00 - 17th January 2005
|
||||
===================================
|
||||
Fix vgscan metadata auto-correction.
|
||||
Only ask libdevmapper for open_count when we need it.
|
||||
Adjust RHEL4 clvmd init script priority.
|
||||
Enable building of CMAN & GULM versions of clvmd into a single binary
|
||||
|
||||
Version 2.00.33 - 7th January 2005
|
||||
==================================
|
||||
pvcreate wipes first 4 sectors unless given --zero n.
|
||||
gulm clvmd now uses new ccsd key names.
|
||||
gulm clvmd now doesn't ignore the first node in cluster.conf
|
||||
Improve clvmd failure message if it's already running.
|
||||
Allow user to kill clvmd during initialisation.
|
||||
Fix off-by-one error in cluster_locking that could cause read hangs.
|
||||
|
||||
Version 2.00.32 - 22nd December 2004
|
||||
====================================
|
||||
|
||||
15
WHATS_NEW_DM
15
WHATS_NEW_DM
@@ -1,3 +1,18 @@
|
||||
Version 1.01.01 - 29 Mar 2005
|
||||
=============================
|
||||
Update dmsetup man page.
|
||||
Drop-in devmap_name replacement.
|
||||
Add option to compile without ioctl for testing.
|
||||
Fix DM_LIB_VERSION sed.
|
||||
|
||||
Version 1.01.00 - 17 Jan 2005
|
||||
=============================
|
||||
Add dm_task_no_open_count() to skip getting open_count.
|
||||
|
||||
Version 1.00.21 - 7 Jan 2005
|
||||
============================
|
||||
Fix /proc/devices parsing.
|
||||
|
||||
Version 1.00.20 - 6 Jan 2005
|
||||
============================
|
||||
Attempt to fix /dev/mapper/control transparently if it's wrong.
|
||||
|
||||
@@ -281,12 +281,12 @@ AC_MSG_RESULT($SELINUX)
|
||||
dnl -- Build cluster LVM daemon
|
||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
|
||||
AC_ARG_WITH(clvmd,
|
||||
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/none
|
||||
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/none/all
|
||||
[TYPE=none] ],
|
||||
[ CLVMD="$withval" ],
|
||||
[ CLVMD="none" ])
|
||||
if test x$CLVMD = xyes; then
|
||||
CLVMD=cman
|
||||
CLVMD=all
|
||||
fi
|
||||
AC_MSG_RESULT($CLVMD)
|
||||
|
||||
@@ -481,7 +481,7 @@ if test x$READLINE = xyes; then
|
||||
AC_CHECK_HEADERS(readline/readline.h readline/history.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$CLVMD = xyes; then
|
||||
if test x$CLVMD != xnone; then
|
||||
AC_CHECK_HEADERS(mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_FUNCS(dup2 getmntent memmove select socket,,AC_MSG_ERROR(bailing out))
|
||||
AC_FUNC_GETMNTENT
|
||||
|
||||
@@ -18,19 +18,36 @@ VPATH = @srcdir@
|
||||
SOURCES = \
|
||||
clvmd-command.c \
|
||||
clvmd.c \
|
||||
libclvm.c \
|
||||
lvm-functions.c \
|
||||
system-lv.c
|
||||
|
||||
ifeq ("@CLVMD@", "gulm")
|
||||
GULM = yes
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "cman")
|
||||
CMAN = yes
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "all")
|
||||
GULM = yes
|
||||
CMAN = yes
|
||||
endif
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
||||
ifeq ("$(GULM)", "yes")
|
||||
SOURCES += clvmd-gulm.c tcp-comms.c
|
||||
LMLIBS += -lccs -lgulm
|
||||
CFLAGS += -DUSE_GULM
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "cman")
|
||||
ifeq ("$(CMAN)", "yes")
|
||||
SOURCES += clvmd-cman.c
|
||||
LMLIBS += -ldlm
|
||||
CFLAGS += -DUSE_CMAN
|
||||
endif
|
||||
|
||||
TARGETS = \
|
||||
|
||||
@@ -43,6 +43,7 @@ struct clvm_header {
|
||||
/* Flags */
|
||||
#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
|
||||
#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
|
||||
#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */
|
||||
|
||||
/* Name of the local socket to communicate between libclvm and clvmd */
|
||||
//static const char CLVMD_SOCKNAME[]="/var/run/clvmd";
|
||||
|
||||
@@ -66,7 +66,7 @@ struct lock_wait {
|
||||
struct dlm_lksb lksb;
|
||||
};
|
||||
|
||||
int init_cluster()
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
struct sockaddr_cl saddr;
|
||||
int port = CLUSTER_PORT_CLVMD;
|
||||
@@ -74,9 +74,11 @@ int init_cluster()
|
||||
/* Open the cluster communication socket */
|
||||
cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT);
|
||||
if (cluster_sock == -1) {
|
||||
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
|
||||
/* Don't print an error here because we could be just probing for CMAN */
|
||||
return -1;
|
||||
}
|
||||
/* Set Close-on-exec */
|
||||
fcntl(cluster_sock, F_SETFD, 1);
|
||||
|
||||
/* Bind to our port number on the cluster.
|
||||
Writes to this will block if the cluster loses quorum */
|
||||
@@ -101,21 +103,27 @@ int init_cluster()
|
||||
return -1;
|
||||
}
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_main_cluster_fd()
|
||||
static void _cluster_init_completed(void)
|
||||
{
|
||||
clvmd_cluster_init_completed();
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd()
|
||||
{
|
||||
return cluster_sock;
|
||||
}
|
||||
|
||||
int get_num_nodes()
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* send_message with the fd check removed */
|
||||
int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct msghdr msg;
|
||||
@@ -135,7 +143,7 @@ int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
if (csid) {
|
||||
msg.msg_name = &saddr;
|
||||
msg.msg_namelen = sizeof(saddr);
|
||||
memcpy(&saddr.scl_nodeid, csid, MAX_CSID_LEN);
|
||||
memcpy(&saddr.scl_nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
} else { /* Cluster broadcast */
|
||||
|
||||
msg.msg_name = NULL;
|
||||
@@ -151,26 +159,26 @@ int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
return len;
|
||||
}
|
||||
|
||||
void get_our_csid(char *csid)
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
int i;
|
||||
memset(csid, 0, MAX_CSID_LEN);
|
||||
memset(csid, 0, CMAN_MAX_CSID_LEN);
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (nodes[i].us)
|
||||
memcpy(csid, &nodes[i].node_id, MAX_CSID_LEN);
|
||||
memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call a callback routine for each node that known (down mean not running a clvmd) */
|
||||
int cluster_do_node_callback(struct local_client *client,
|
||||
static int _cluster_do_node_callback(struct local_client *client,
|
||||
void (*callback) (struct local_client *, char *,
|
||||
int))
|
||||
{
|
||||
int i;
|
||||
int somedown = 0;
|
||||
|
||||
for (i = 0; i < get_num_nodes(); i++) {
|
||||
for (i = 0; i < _get_num_nodes(); i++) {
|
||||
callback(client, (char *)&nodes[i].node_id, node_updown[nodes[i].node_id]);
|
||||
if (!node_updown[nodes[i].node_id])
|
||||
somedown = -1;
|
||||
@@ -202,7 +210,7 @@ static void process_oob_msg(char *buf, int len, int nodeid)
|
||||
}
|
||||
}
|
||||
|
||||
int cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
|
||||
static int _cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
@@ -254,7 +262,7 @@ int cluster_fd_callback(struct local_client *client, char *buf, int len, char *c
|
||||
return len;
|
||||
}
|
||||
|
||||
void add_up_node(char *csid)
|
||||
static void _add_up_node(char *csid)
|
||||
{
|
||||
/* It's up ! */
|
||||
int nodeid = nodeid_from_csid(csid);
|
||||
@@ -278,7 +286,7 @@ void add_up_node(char *csid)
|
||||
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
||||
}
|
||||
|
||||
void cluster_closedown()
|
||||
static void _cluster_closedown()
|
||||
{
|
||||
unlock_all();
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
@@ -307,7 +315,7 @@ static int is_listening(int nodeid)
|
||||
|
||||
/* Populate the list of CLVMDs running.
|
||||
called only at startup time */
|
||||
void count_clvmds_running(void)
|
||||
static void count_clvmds_running(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -366,13 +374,13 @@ static void get_members()
|
||||
}
|
||||
|
||||
/* Convert a node name to a CSID */
|
||||
int csid_from_name(char *csid, char *name)
|
||||
static int _csid_from_name(char *csid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (strcmp(name, nodes[i].name) == 0) {
|
||||
memcpy(csid, &nodes[i].node_id, MAX_CSID_LEN);
|
||||
memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -380,12 +388,12 @@ int csid_from_name(char *csid, char *name)
|
||||
}
|
||||
|
||||
/* Convert a CSID to a node name */
|
||||
int name_from_csid(char *csid, char *name)
|
||||
static int _name_from_csid(char *csid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (memcmp(csid, &nodes[i].node_id, MAX_CSID_LEN) == 0) {
|
||||
if (memcmp(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN) == 0) {
|
||||
strcpy(name, nodes[i].name);
|
||||
return 0;
|
||||
}
|
||||
@@ -396,7 +404,7 @@ int name_from_csid(char *csid, char *name)
|
||||
}
|
||||
|
||||
/* Convert a node ID to a node name */
|
||||
int name_from_nodeid(int nodeid, char *name)
|
||||
static int name_from_nodeid(int nodeid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -416,12 +424,12 @@ static int nodeid_from_csid(char *csid)
|
||||
{
|
||||
int nodeid;
|
||||
|
||||
memcpy(&nodeid, csid, MAX_CSID_LEN);
|
||||
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
|
||||
return nodeid;
|
||||
}
|
||||
|
||||
int is_quorate()
|
||||
static int _is_quorate()
|
||||
{
|
||||
return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
|
||||
}
|
||||
@@ -435,7 +443,7 @@ static void sync_ast_routine(void *arg)
|
||||
pthread_mutex_unlock(&lwait->mutex);
|
||||
}
|
||||
|
||||
int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
@@ -478,7 +486,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||
static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
@@ -505,3 +513,28 @@ int sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_cman_ops = {
|
||||
.cluster_init_completed = _cluster_init_completed,
|
||||
.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,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.sync_lock = _sync_lock,
|
||||
.sync_unlock = _sync_unlock,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_cman_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_cman_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -274,9 +274,10 @@ void cmd_client_cleanup(struct local_client *client)
|
||||
|
||||
hash_iterate(v, lock_hash) {
|
||||
int lkid = (int)(long)hash_get_data(lock_hash, v);
|
||||
char *lockname = hash_get_key(lock_hash, v);
|
||||
|
||||
DEBUGLOG("cleanup: Unlocking lkid %x\n", lkid);
|
||||
sync_unlock("DUMMY", lkid);
|
||||
DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
|
||||
sync_unlock(lockname, lkid);
|
||||
}
|
||||
|
||||
hash_destroy(lock_hash);
|
||||
|
||||
@@ -22,33 +22,47 @@
|
||||
|
||||
struct local_client;
|
||||
|
||||
extern int cluster_send_message(void *buf, int msglen, char *csid,
|
||||
struct cluster_ops {
|
||||
void (*cluster_init_completed) (void);
|
||||
|
||||
int (*cluster_send_message) (void *buf, int msglen, char *csid,
|
||||
const char *errtext);
|
||||
extern int name_from_csid(char *csid, char *name);
|
||||
extern int csid_from_name(char *csid, char *name);
|
||||
extern int get_num_nodes(void);
|
||||
extern int cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
int (*name_from_csid) (char *csid, char *name);
|
||||
int (*csid_from_name) (char *csid, 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);
|
||||
extern int init_cluster(void);
|
||||
extern int get_main_cluster_fd(void); /* gets accept FD or cman cluster socket */
|
||||
extern int cluster_do_node_callback(struct local_client *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));
|
||||
extern int is_quorate(void);
|
||||
int (*is_quorate) (void);
|
||||
|
||||
extern void get_our_csid(char *csid);
|
||||
extern void add_up_node(char *csid);
|
||||
extern void cluster_closedown(void);
|
||||
void (*get_our_csid) (char *csid);
|
||||
void (*add_up_node) (char *csid);
|
||||
void (*cluster_closedown) (void);
|
||||
|
||||
extern int sync_lock(const char *resource, int mode, int flags, int *lockid);
|
||||
extern int sync_unlock(const char *resource, int lockid);
|
||||
int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
|
||||
int (*sync_unlock) (const char *resource, int lockid);
|
||||
|
||||
};
|
||||
|
||||
#ifdef USE_GULM
|
||||
#include "tcp-comms.h"
|
||||
#else
|
||||
/* cman */
|
||||
#include "cnxman-socket.h"
|
||||
#define MAX_CSID_LEN 4
|
||||
# include "tcp-comms.h"
|
||||
struct cluster_ops *init_gulm_cluster(void);
|
||||
#define MAX_CSID_LEN GULM_MAX_CSID_LEN
|
||||
#define MAX_CLUSTER_MEMBER_NAME_LEN GULM_MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
#endif
|
||||
|
||||
#ifdef USE_CMAN
|
||||
# include "cnxman-socket.h"
|
||||
# define CMAN_MAX_CSID_LEN 4
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
|
||||
# endif
|
||||
# undef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
struct cluster_ops *init_cman_cluster(void);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
|
||||
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
@@ -46,6 +47,7 @@
|
||||
#include "log.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvmd.h"
|
||||
#include "hash.h"
|
||||
#include "clvmd-gulm.h"
|
||||
@@ -65,6 +67,7 @@ static uint8_t current_corestate;
|
||||
static int num_nodes;
|
||||
|
||||
static char *cluster_name;
|
||||
static int in_shutdown = 0;
|
||||
|
||||
static pthread_mutex_t lock_start_mutex;
|
||||
static volatile int lock_start_flag;
|
||||
@@ -72,7 +75,7 @@ static volatile int lock_start_flag;
|
||||
struct node_info
|
||||
{
|
||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
};
|
||||
|
||||
struct lock_wait
|
||||
@@ -88,6 +91,8 @@ static int read_from_core_sock(struct local_client *client, char *buf, int len,
|
||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client);
|
||||
static int get_all_cluster_nodes(void);
|
||||
static int _csid_from_name(char *csid, char *name);
|
||||
static void _cluster_closedown(void);
|
||||
|
||||
/* In tcp-comms.c */
|
||||
extern struct hash_table *sock_hash;
|
||||
@@ -112,6 +117,9 @@ static int add_internal_client(int fd, fd_callback_t callback)
|
||||
client->callback = callback;
|
||||
add_client(client);
|
||||
|
||||
/* Set Close-on-exec */
|
||||
fcntl(fd, F_SETFD, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -123,7 +131,7 @@ static lg_lockspace_callbacks_t lock_callbacks;
|
||||
static void badsig_handler(int sig)
|
||||
{
|
||||
DEBUGLOG("got sig %d\n", sig);
|
||||
cluster_closedown();
|
||||
_cluster_closedown();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -135,7 +143,7 @@ static void sighup_handler(int sig)
|
||||
get_all_cluster_nodes();
|
||||
}
|
||||
|
||||
int init_cluster()
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
int status;
|
||||
int ccs_h;
|
||||
@@ -222,7 +230,7 @@ int init_cluster()
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/* Request a list of nodes, we can;t really do anything until
|
||||
/* Request a list of nodes, we can't really do anything until
|
||||
this comes back */
|
||||
status = lg_core_nodelist(gulm_if);
|
||||
if (status)
|
||||
@@ -241,9 +249,11 @@ int init_cluster()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cluster_closedown()
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
in_shutdown = 1;
|
||||
unlock_all();
|
||||
lg_lock_logout(gulm_if);
|
||||
lg_core_logout(gulm_if);
|
||||
lg_release(gulm_if);
|
||||
@@ -256,6 +266,7 @@ static void drop_expired_locks(char *nodename)
|
||||
struct utsname nodeinfo;
|
||||
uint8_t mask[GIO_KEY_SIZE];
|
||||
|
||||
DEBUGLOG("Dropping expired locks for %s\n", nodename?nodename:"(null)");
|
||||
memset(mask, 0xff, GIO_KEY_SIZE);
|
||||
|
||||
if (!nodename)
|
||||
@@ -339,7 +350,7 @@ static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = hash_lookup_binary(node_hash, (char *)ip, MAX_CSID_LEN);
|
||||
ninfo = hash_lookup_binary(node_hash, (char *)ip, GULM_MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
/* If we can't find that node then re-read the config file in case it
|
||||
@@ -348,7 +359,7 @@ static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_
|
||||
get_all_cluster_nodes();
|
||||
|
||||
/* Now try again */
|
||||
ninfo = hash_lookup_binary(node_hash, (char *)ip, MAX_CSID_LEN);
|
||||
ninfo = hash_lookup_binary(node_hash, (char *)ip, GULM_MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
DEBUGLOG("Ignoring node %s, not part of the SAN cluster\n", name);
|
||||
@@ -356,11 +367,16 @@ static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_
|
||||
}
|
||||
}
|
||||
|
||||
set_node_state(ninfo, (char *)&ip, state);
|
||||
set_node_state(ninfo, (char *)ip, state);
|
||||
|
||||
return ninfo;
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
get_our_gulm_csid(csid);
|
||||
}
|
||||
|
||||
static int core_nodelist(void *misc, lglcb_t type, char *name, struct in6_addr *ip, uint8_t state)
|
||||
{
|
||||
DEBUGLOG("CORE nodelist\n");
|
||||
@@ -381,14 +397,14 @@ static int core_nodelist(void *misc, lglcb_t type, char *name, struct in6_addr *
|
||||
{
|
||||
if (type == lglcb_stop)
|
||||
{
|
||||
char ourcsid[MAX_CSID_LEN];
|
||||
char ourcsid[GULM_MAX_CSID_LEN];
|
||||
|
||||
DEBUGLOG("Got Nodelist, stop\n");
|
||||
clvmd_cluster_init_completed();
|
||||
|
||||
/* Mark ourself as up */
|
||||
get_our_csid(ourcsid);
|
||||
add_up_node(ourcsid);
|
||||
_get_our_csid(ourcsid);
|
||||
gulm_add_up_node(ourcsid);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -417,7 +433,7 @@ static int core_nodechange(void *misc, char *nodename, struct in6_addr *nodeip,
|
||||
|
||||
/* If we don't get nodeip here, try a lookup by name */
|
||||
if (!nodeip)
|
||||
csid_from_name((char *)nodeip, nodename);
|
||||
_csid_from_name((char *)nodeip, nodename);
|
||||
if (!nodeip)
|
||||
return 0;
|
||||
|
||||
@@ -458,7 +474,7 @@ static int lock_login_reply(void *misc, uint32_t error, uint8_t which)
|
||||
lock_start_flag = 0;
|
||||
pthread_mutex_unlock(&lock_start_mutex);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -471,6 +487,10 @@ static int lock_lock_state(void *misc, uint8_t *key, uint16_t keylen,
|
||||
|
||||
DEBUGLOG("LOCK lock state: %s, error = %d\n", key, error);
|
||||
|
||||
/* No waiting process to wake up when we are shutting down */
|
||||
if (in_shutdown)
|
||||
return 0;
|
||||
|
||||
lwait = hash_lookup(lock_hash, key);
|
||||
if (!lwait)
|
||||
{
|
||||
@@ -540,15 +560,15 @@ int get_next_node_csid(void **context, char *csid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(csid, hash_get_key(node_hash, *context), MAX_CSID_LEN);
|
||||
memcpy(csid, hash_get_key(node_hash, *context), GULM_MAX_CSID_LEN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int name_from_csid(char *csid, char *name)
|
||||
int gulm_name_from_csid(char *csid, char *name)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
|
||||
ninfo = hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
sprintf(name, "UNKNOWN %s", print_csid(csid));
|
||||
@@ -560,7 +580,7 @@ int name_from_csid(char *csid, char *name)
|
||||
}
|
||||
|
||||
|
||||
int csid_from_name(char *csid, char *name)
|
||||
static int _csid_from_name(char *csid, char *name)
|
||||
{
|
||||
struct hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
@@ -570,28 +590,31 @@ int csid_from_name(char *csid, char *name)
|
||||
ninfo = hash_get_data(node_hash, hn);
|
||||
if (strcmp(ninfo->name, name) == 0)
|
||||
{
|
||||
memcpy(csid, hash_get_key(node_hash, hn), MAX_CSID_LEN);
|
||||
memcpy(csid, hash_get_key(node_hash, hn), GULM_MAX_CSID_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int get_num_nodes()
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
void add_up_node(char *csid)
|
||||
void gulm_add_up_node(char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
ninfo = hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
DEBUGLOG("gulm_add_up_node no node_hash entry for csid %s\n", print_csid(csid));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGLOG("gulm_add_up_node %s\n", ninfo->name);
|
||||
ninfo->state = NODE_CLVMD;
|
||||
return;
|
||||
|
||||
@@ -601,7 +624,7 @@ void add_down_node(char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
|
||||
ninfo = hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
return;
|
||||
|
||||
@@ -609,30 +632,42 @@ void add_down_node(char *csid)
|
||||
running clvmd - gulm may set it DOWN quite soon */
|
||||
if (ninfo->state == NODE_CLVMD)
|
||||
ninfo->state = NODE_UP;
|
||||
drop_expired_locks(ninfo->name);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
int cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *, char *csid, int node_up))
|
||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *, char *csid, int node_up))
|
||||
{
|
||||
struct hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
|
||||
hash_iterate(hn, node_hash)
|
||||
{
|
||||
char csid[MAX_CSID_LEN];
|
||||
char csid[GULM_MAX_CSID_LEN];
|
||||
struct local_client *client;
|
||||
|
||||
ninfo = hash_get_data(node_hash, hn);
|
||||
memcpy(csid, hash_get_key(node_hash, hn), MAX_CSID_LEN);
|
||||
memcpy(csid, hash_get_key(node_hash, hn), GULM_MAX_CSID_LEN);
|
||||
|
||||
DEBUGLOG("down_callback. node %s, state = %d\n", ninfo->name, ninfo->state);
|
||||
|
||||
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
if (client)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
client = hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (!client)
|
||||
{
|
||||
/* If it's up but not connected, try to make contact */
|
||||
if (ninfo->state == NODE_UP)
|
||||
gulm_connect_csid(csid, &client);
|
||||
|
||||
client = hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
|
||||
}
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -643,15 +678,13 @@ static int gulm_to_errno(int gulm_ret)
|
||||
switch (gulm_ret)
|
||||
{
|
||||
case lg_err_TryFailed:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
|
||||
case lg_err_AlreadyPend:
|
||||
errno = EBUSY;
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
|
||||
/* More?? */
|
||||
default:
|
||||
errno = EINVAL;
|
||||
errno = EINVAL;
|
||||
}
|
||||
|
||||
return gulm_ret ? -1 : 0;
|
||||
@@ -722,6 +755,11 @@ static int _unlock_resource(char *resource, int lockid)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* When we are shutting down, don't wait for unlocks
|
||||
to be acknowledged, just do it. */
|
||||
if (in_shutdown)
|
||||
return status;
|
||||
|
||||
/* Wait for it to complete */
|
||||
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
@@ -742,7 +780,7 @@ static int _unlock_resource(char *resource, int lockid)
|
||||
To aid unlocking, we store the lock mode in the lockid (as GULM
|
||||
doesn't use this).
|
||||
*/
|
||||
int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
char lock1[strlen(resource)+3];
|
||||
@@ -758,7 +796,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
/* If we can't get this lock then bail out */
|
||||
/* If we can't get this lock too then bail out */
|
||||
status = _lock_resource(lock2, lg_lock_state_Exclusive, LCK_NONBLOCK, lockid);
|
||||
if (status == lg_err_TryFailed)
|
||||
{
|
||||
@@ -770,10 +808,16 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
|
||||
case LCK_READ:
|
||||
status = _lock_resource(lock1, lg_lock_state_Shared, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
status = _unlock_resource(lock2, *lockid);
|
||||
break;
|
||||
|
||||
case LCK_WRITE:
|
||||
status = _lock_resource(lock2, lg_lock_state_Exclusive, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
status = _unlock_resource(lock1, *lockid);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -786,7 +830,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
return status;
|
||||
}
|
||||
|
||||
int sync_unlock(const char *resource, int lockid)
|
||||
static int _sync_unlock(const char *resource, int lockid)
|
||||
{
|
||||
int status = 0;
|
||||
char lock1[strlen(resource)+3];
|
||||
@@ -800,29 +844,14 @@ int sync_unlock(const char *resource, int lockid)
|
||||
lockid == LCK_READ ||
|
||||
lockid == LCK_WRITE);
|
||||
|
||||
switch (lockid)
|
||||
{
|
||||
case LCK_EXCL:
|
||||
status = _unlock_resource(lock1, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
status = _unlock_resource(lock2, lockid);
|
||||
break;
|
||||
status = _unlock_resource(lock1, lockid);
|
||||
if (!status)
|
||||
status = _unlock_resource(lock2, lockid);
|
||||
|
||||
case LCK_READ:
|
||||
status = _unlock_resource(lock1, lockid);
|
||||
break;
|
||||
|
||||
case LCK_WRITE:
|
||||
status = _unlock_resource(lock2, lockid);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
int is_quorate()
|
||||
static int _is_quorate()
|
||||
{
|
||||
if (current_corestate == lg_core_Slave ||
|
||||
current_corestate == lg_core_Master ||
|
||||
@@ -854,7 +883,7 @@ static int get_all_cluster_nodes()
|
||||
for (i=1;;i++)
|
||||
{
|
||||
char nodekey[256];
|
||||
char nodeip[MAX_CSID_LEN];
|
||||
char nodeip[GULM_MAX_CSID_LEN];
|
||||
int clvmflag = 1;
|
||||
char *clvmflagstr;
|
||||
char key[256];
|
||||
@@ -877,7 +906,7 @@ static int get_all_cluster_nodes()
|
||||
struct node_info *ninfo;
|
||||
|
||||
/* If it's not in the list, then add it */
|
||||
ninfo = hash_lookup_binary(node_hash, nodeip, MAX_CSID_LEN);
|
||||
ninfo = hash_lookup_binary(node_hash, nodeip, GULM_MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
@@ -890,7 +919,7 @@ static int get_all_cluster_nodes()
|
||||
strcpy(ninfo->name, nodename);
|
||||
|
||||
ninfo->state = NODE_DOWN;
|
||||
hash_insert_binary(node_hash, nodeip, MAX_CSID_LEN, ninfo);
|
||||
hash_insert_binary(node_hash, nodeip, GULM_MAX_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -906,3 +935,42 @@ static int get_all_cluster_nodes()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd(void)
|
||||
{
|
||||
return get_main_gulm_cluster_fd();
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client)
|
||||
{
|
||||
return cluster_fd_gulm_callback(fd, buf, len, csid, new_client);
|
||||
}
|
||||
|
||||
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
{
|
||||
return gulm_cluster_send_message(buf, msglen, csid, errtext);
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_gulm_ops = {
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = gulm_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 = gulm_add_up_node,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.sync_lock = _sync_lock,
|
||||
.sync_unlock = _sync_unlock,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_gulm_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_gulm_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -7,3 +7,6 @@ extern int gulm_fd(void);
|
||||
extern int get_ip_address(char *node, char *addr);
|
||||
extern void tcp_remove_client(char *csid);
|
||||
extern int alloc_client(int fd, char *csid, struct local_client **new_client);
|
||||
|
||||
void gulm_add_up_node(char *csid);
|
||||
int gulm_name_from_csid(char *csid, char *name);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
@@ -55,9 +56,9 @@
|
||||
|
||||
/* 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 MAX_INLINE_MESSAGE (max_cluster_message-sizeof(struct clvm_header))
|
||||
|
||||
#define ISLOCAL_CSID(c) (memcmp(c, our_csid, MAX_CSID_LEN) == 0)
|
||||
#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0)
|
||||
|
||||
/* Head of the fd list. Also contains
|
||||
the cluster_socket details */
|
||||
@@ -65,7 +66,12 @@ static struct local_client local_client_head;
|
||||
|
||||
static unsigned short global_xid = 0; /* Last transaction ID issued */
|
||||
|
||||
static struct cluster_ops *clops = NULL;
|
||||
|
||||
static char our_csid[MAX_CSID_LEN];
|
||||
static unsigned max_csid_len;
|
||||
static unsigned max_cluster_message;
|
||||
static unsigned max_cluster_member_name_len;
|
||||
|
||||
/* Structure of items on the LVM thread list */
|
||||
struct lvm_thread_cmd {
|
||||
@@ -82,7 +88,7 @@ static pthread_t lvm_thread;
|
||||
static pthread_mutex_t lvm_thread_mutex;
|
||||
static pthread_cond_t lvm_thread_cond;
|
||||
static struct list lvm_cmd_head;
|
||||
static int quit = 0;
|
||||
static volatile sig_atomic_t quit = 0;
|
||||
static int child_pipe[2];
|
||||
|
||||
/* Reasons the daemon failed initialisation */
|
||||
@@ -159,6 +165,7 @@ int main(int argc, char *argv[])
|
||||
int debug = 0;
|
||||
int cmd_timeout = DEFAULT_CMD_TIMEOUT;
|
||||
sigset_t ss;
|
||||
int using_gulm = 0;
|
||||
|
||||
/* Deal with command-line arguments */
|
||||
opterr = 0;
|
||||
@@ -230,7 +237,26 @@ int main(int argc, char *argv[])
|
||||
init_lvhash();
|
||||
|
||||
/* Start the cluster interface */
|
||||
if (init_cluster()) {
|
||||
#ifdef USE_CMAN
|
||||
if ((clops = init_cman_cluster())) {
|
||||
max_csid_len = CMAN_MAX_CSID_LEN;
|
||||
max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
|
||||
max_cluster_member_name_len = CMAN_MAX_CLUSTER_MEMBER_NAME_LEN;
|
||||
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_GULM
|
||||
if (!clops)
|
||||
if ((clops = init_gulm_cluster())) {
|
||||
max_csid_len = GULM_MAX_CSID_LEN;
|
||||
max_cluster_message = GULM_MAX_CLUSTER_MESSAGE;
|
||||
max_cluster_member_name_len = GULM_MAX_CLUSTER_MEMBER_NAME_LEN;
|
||||
using_gulm = 1;
|
||||
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to GULM");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!clops) {
|
||||
DEBUGLOG("Can't initialise cluster interface\n");
|
||||
log_error("Can't initialise cluster interface\n");
|
||||
child_init_signal(DFAIL_CLUSTER_IF);
|
||||
@@ -239,12 +265,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Save our CSID */
|
||||
uname(&nodeinfo);
|
||||
get_our_csid(our_csid);
|
||||
clops->get_our_csid(our_csid);
|
||||
|
||||
/* Initialise the FD list head */
|
||||
local_client_head.fd = get_main_cluster_fd();
|
||||
local_client_head.fd = clops->get_main_cluster_fd();
|
||||
local_client_head.type = CLUSTER_MAIN_SOCK;
|
||||
local_client_head.callback = cluster_fd_callback;
|
||||
local_client_head.callback = clops->cluster_fd_callback;
|
||||
|
||||
/* Add the local socket to the list */
|
||||
newfd = malloc(sizeof(struct local_client));
|
||||
@@ -260,15 +286,14 @@ int main(int argc, char *argv[])
|
||||
/* This needs to be started after cluster initialisation
|
||||
as it may need to take out locks */
|
||||
DEBUGLOG("starting LVM thread\n");
|
||||
pthread_create(&lvm_thread, NULL, lvm_thread_fn, nodeinfo.nodename);
|
||||
pthread_create(&lvm_thread, NULL, lvm_thread_fn, (void *)using_gulm);
|
||||
|
||||
#ifndef USE_GULM
|
||||
/* Tell the rest of the cluster our version number */
|
||||
/* CMAN can do this immediately, gulm needs to wait until
|
||||
the core initialisation has finished and the node list
|
||||
has been gathered */
|
||||
send_version_message();
|
||||
#endif
|
||||
if (clops->cluster_init_completed)
|
||||
clops->cluster_init_completed();
|
||||
|
||||
DEBUGLOG("clvmd ready for work\n");
|
||||
child_init_signal(SUCCESS);
|
||||
@@ -417,9 +442,9 @@ static void timedout_callback(struct local_client *client, char *csid,
|
||||
{
|
||||
if (node_up) {
|
||||
struct node_reply *reply;
|
||||
char nodename[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
char nodename[max_cluster_member_name_len];
|
||||
|
||||
name_from_csid(csid, nodename);
|
||||
clops->name_from_csid(csid, nodename);
|
||||
DEBUGLOG("PJC: checking for a reply from %s\n", nodename);
|
||||
pthread_mutex_lock(&client->bits.localsock.reply_mutex);
|
||||
|
||||
@@ -448,7 +473,7 @@ static void timedout_callback(struct local_client *client, char *csid,
|
||||
static void request_timed_out(struct local_client *client)
|
||||
{
|
||||
DEBUGLOG("Request timed-out. padding\n");
|
||||
cluster_do_node_callback(client, timedout_callback);
|
||||
clops->cluster_do_node_callback(client, timedout_callback);
|
||||
|
||||
if (client->bits.localsock.num_replies !=
|
||||
client->bits.localsock.expected_replies) {
|
||||
@@ -473,7 +498,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
int select_status;
|
||||
struct local_client *thisfd;
|
||||
struct timeval tv = { cmd_timeout, 0 };
|
||||
int quorate = is_quorate();
|
||||
int quorate = clops->is_quorate();
|
||||
|
||||
/* Wait on the cluster FD and all local sockets/pipes */
|
||||
FD_ZERO(&in);
|
||||
@@ -488,7 +513,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
if ((select_status = select(FD_SETSIZE, &in, NULL, NULL, &tv)) > 0) {
|
||||
struct local_client *lastfd = NULL;
|
||||
char csid[MAX_CSID_LEN];
|
||||
char buf[MAX_CLUSTER_MESSAGE];
|
||||
char buf[max_cluster_message];
|
||||
|
||||
for (thisfd = &local_client_head; thisfd != NULL;
|
||||
thisfd = thisfd->next) {
|
||||
@@ -520,8 +545,9 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
lastfd->next = thisfd->next;
|
||||
free_fd = thisfd;
|
||||
thisfd = lastfd;
|
||||
cmd_client_cleanup(free_fd);
|
||||
free(free_fd);
|
||||
|
||||
/* Queue cleanup, this also frees the client struct */
|
||||
add_to_lvmqueue(free_fd, NULL, 0, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -573,7 +599,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
}
|
||||
|
||||
closedown:
|
||||
cluster_closedown();
|
||||
clops->cluster_closedown();
|
||||
close(local_sock);
|
||||
}
|
||||
|
||||
@@ -696,7 +722,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
if (thisfd->bits.localsock.threadid) {
|
||||
DEBUGLOG("Waiting for child thread\n");
|
||||
pthread_mutex_lock(&thisfd->bits.localsock.mutex);
|
||||
thisfd->bits.localsock.state = POST_COMMAND;
|
||||
thisfd->bits.localsock.state = PRE_COMMAND;
|
||||
pthread_cond_signal(&thisfd->bits.localsock.cond);
|
||||
pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
|
||||
pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
|
||||
@@ -765,7 +791,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
if (thisfd->bits.localsock.in_progress) {
|
||||
struct clvm_header reply;
|
||||
reply.cmd = CLVMD_CMD_REPLY;
|
||||
reply.status = -EBUSY;
|
||||
reply.status = EBUSY;
|
||||
reply.arglen = 0;
|
||||
reply.flags = 0;
|
||||
send_message(&reply, sizeof(reply), our_csid,
|
||||
@@ -788,7 +814,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
if (!thisfd->bits.localsock.cmd) {
|
||||
struct clvm_header reply;
|
||||
reply.cmd = CLVMD_CMD_REPLY;
|
||||
reply.status = -ENOMEM;
|
||||
reply.status = ENOMEM;
|
||||
reply.arglen = 0;
|
||||
reply.flags = 0;
|
||||
send_message(&reply, sizeof(reply), our_csid,
|
||||
@@ -829,13 +855,13 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
}
|
||||
|
||||
/* Check the node name for validity */
|
||||
if (inheader->node[0] && csid_from_name(csid, inheader->node)) {
|
||||
if (inheader->node[0] && clops->csid_from_name(csid, inheader->node)) {
|
||||
/* Error, node is not in the cluster */
|
||||
struct clvm_header reply;
|
||||
DEBUGLOG("Unknown node: '%s'\n", inheader->node);
|
||||
|
||||
reply.cmd = CLVMD_CMD_REPLY;
|
||||
reply.status = -ENOENT;
|
||||
reply.status = ENOENT;
|
||||
reply.flags = 0;
|
||||
reply.arglen = 0;
|
||||
send_message(&reply, sizeof(reply), our_csid,
|
||||
@@ -866,7 +892,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
close(comms_pipe[1]);
|
||||
|
||||
reply.cmd = CLVMD_CMD_REPLY;
|
||||
reply.status = -ENOMEM;
|
||||
reply.status = ENOMEM;
|
||||
reply.arglen = 0;
|
||||
reply.flags = 0;
|
||||
send_message(&reply, sizeof(reply), our_csid,
|
||||
@@ -961,7 +987,7 @@ static int distribute_command(struct local_client *thisfd)
|
||||
/* if node is empty then do it on the whole cluster */
|
||||
if (inheader->node[0] == '\0') {
|
||||
thisfd->bits.localsock.expected_replies =
|
||||
get_num_nodes();
|
||||
clops->get_num_nodes();
|
||||
thisfd->bits.localsock.num_replies = 0;
|
||||
thisfd->bits.localsock.sent_time = time(NULL);
|
||||
thisfd->bits.localsock.in_progress = TRUE;
|
||||
@@ -982,7 +1008,7 @@ static int distribute_command(struct local_client *thisfd)
|
||||
/* Do it on a single node */
|
||||
char csid[MAX_CSID_LEN];
|
||||
|
||||
if (csid_from_name(csid, inheader->node)) {
|
||||
if (clops->csid_from_name(csid, inheader->node)) {
|
||||
/* This has already been checked so should not happen */
|
||||
return 0;
|
||||
} else {
|
||||
@@ -992,7 +1018,7 @@ static int distribute_command(struct local_client *thisfd)
|
||||
thisfd->bits.localsock.in_progress = TRUE;
|
||||
|
||||
/* Are we the requested node ?? */
|
||||
if (memcmp(csid, our_csid, MAX_CSID_LEN) == 0) {
|
||||
if (memcmp(csid, our_csid, max_csid_len) == 0) {
|
||||
DEBUGLOG("Doing command on local node only\n");
|
||||
add_to_lvmqueue(thisfd, inheader, len, NULL);
|
||||
} else {
|
||||
@@ -1024,14 +1050,14 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
char *csid)
|
||||
{
|
||||
char *replyargs;
|
||||
char nodename[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
char nodename[max_cluster_member_name_len];
|
||||
int replylen = 0;
|
||||
int buflen = MAX_CLUSTER_MESSAGE - sizeof(struct clvm_header) - 1;
|
||||
int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
|
||||
int status;
|
||||
int msg_malloced = 0;
|
||||
|
||||
/* Get the node name as we /may/ need it later */
|
||||
name_from_csid(csid, nodename);
|
||||
clops->name_from_csid(csid, nodename);
|
||||
|
||||
DEBUGLOG("process_remote_command %d for clientid 0x%x on node %s\n",
|
||||
msg->cmd, msg->clientid, nodename);
|
||||
@@ -1056,7 +1082,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
|
||||
/* Return a failure response */
|
||||
head.cmd = CLVMD_CMD_REPLY;
|
||||
head.status = -EFBIG;
|
||||
head.status = EFBIG;
|
||||
head.flags = 0;
|
||||
head.clientid = msg->clientid;
|
||||
head.arglen = 0;
|
||||
@@ -1073,7 +1099,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
msg->arglen);
|
||||
/* Return a failure response */
|
||||
head.cmd = CLVMD_CMD_REPLY;
|
||||
head.status = -ENOMEM;
|
||||
head.status = ENOMEM;
|
||||
head.flags = 0;
|
||||
head.clientid = msg->clientid;
|
||||
head.arglen = 0;
|
||||
@@ -1097,7 +1123,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
if (msg->cmd == CLVMD_CMD_VERSION) {
|
||||
int *version_nums = (int *) msg->args;
|
||||
char node[256];
|
||||
name_from_csid(csid, node);
|
||||
clops->name_from_csid(csid, node);
|
||||
DEBUGLOG("Remote node %s is version %d.%d.%d\n",
|
||||
node,
|
||||
ntohl(version_nums[0]),
|
||||
@@ -1118,17 +1144,17 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
byebyemsg.flags = 0;
|
||||
byebyemsg.arglen = 0;
|
||||
byebyemsg.clientid = 0;
|
||||
cluster_send_message(&byebyemsg, sizeof(byebyemsg),
|
||||
clops->cluster_send_message(&byebyemsg, sizeof(byebyemsg),
|
||||
our_csid,
|
||||
"Error Sending GOAWAY message");
|
||||
} else {
|
||||
add_up_node(csid);
|
||||
clops->add_up_node(csid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate a default reply buffer */
|
||||
replyargs = malloc(MAX_CLUSTER_MESSAGE - sizeof(struct clvm_header));
|
||||
replyargs = malloc(max_cluster_message - sizeof(struct clvm_header));
|
||||
|
||||
if (replyargs != NULL) {
|
||||
/* Run the command */
|
||||
@@ -1136,7 +1162,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
do_command(NULL, msg, msglen, &replyargs, buflen,
|
||||
&replylen);
|
||||
} else {
|
||||
status = -ENOMEM;
|
||||
status = ENOMEM;
|
||||
}
|
||||
|
||||
/* If it wasn't a reply, then reply */
|
||||
@@ -1167,11 +1193,10 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
|
||||
/* 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
|
||||
if (system_lv_write_data(aggreply,
|
||||
replylen + sizeof(struct clvm_header)) < 0
|
||||
&& replylen > 0)
|
||||
agghead->status = -EFBIG;
|
||||
agghead->status = EFBIG;
|
||||
|
||||
send_message(agghead,
|
||||
sizeof(struct clvm_header), csid,
|
||||
@@ -1187,7 +1212,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
agghead->node[0] = '\0';
|
||||
send_message(aggreply,
|
||||
sizeof(struct clvm_header) +
|
||||
replylen + 2, csid, fd,
|
||||
replylen, csid, fd,
|
||||
"Error sending command reply");
|
||||
}
|
||||
} else {
|
||||
@@ -1196,7 +1221,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
DEBUGLOG("Error attempting to realloc return buffer\n");
|
||||
/* Return a failure response */
|
||||
head.cmd = CLVMD_CMD_REPLY;
|
||||
head.status = -ENOMEM;
|
||||
head.status = ENOMEM;
|
||||
head.flags = 0;
|
||||
head.clientid = msg->clientid;
|
||||
head.arglen = 0;
|
||||
@@ -1228,13 +1253,13 @@ static void add_reply_to_list(struct local_client *client, int status,
|
||||
reply = malloc(sizeof(struct node_reply));
|
||||
if (reply) {
|
||||
reply->status = status;
|
||||
name_from_csid(csid, reply->node);
|
||||
clops->name_from_csid(csid, reply->node);
|
||||
DEBUGLOG("Reply from node %s: %d bytes\n", reply->node, len);
|
||||
|
||||
if (len > 0) {
|
||||
reply->replymsg = malloc(len);
|
||||
if (!reply->replymsg) {
|
||||
reply->status = -ENOMEM;
|
||||
reply->status = ENOMEM;
|
||||
} else {
|
||||
memcpy(reply->replymsg, buf, len);
|
||||
}
|
||||
@@ -1313,13 +1338,12 @@ static void *pre_and_post_thread(void *arg)
|
||||
|
||||
DEBUGLOG("Got post command condition...\n");
|
||||
|
||||
/* POST function must always run, even if the client aborts */
|
||||
status = 0;
|
||||
do_post_command(client);
|
||||
|
||||
write(pipe_fd, &status, sizeof(int));
|
||||
|
||||
if (client->bits.localsock.finished)
|
||||
break;
|
||||
|
||||
DEBUGLOG("Waiting for next pre command\n");
|
||||
|
||||
pthread_mutex_lock(&client->bits.localsock.mutex);
|
||||
@@ -1341,8 +1365,8 @@ static int process_local_command(struct clvm_header *msg, int msglen,
|
||||
struct local_client *client,
|
||||
unsigned short xid)
|
||||
{
|
||||
char *replybuf = malloc(MAX_CLUSTER_MESSAGE);
|
||||
int buflen = MAX_CLUSTER_MESSAGE - sizeof(struct clvm_header) - 1;
|
||||
char *replybuf = malloc(max_cluster_message);
|
||||
int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
|
||||
int replylen = 0;
|
||||
int status;
|
||||
|
||||
@@ -1424,9 +1448,10 @@ static void send_local_reply(struct local_client *client, int status, int fd)
|
||||
replybuf = malloc(message_len);
|
||||
|
||||
clientreply = (struct clvm_header *) replybuf;
|
||||
clientreply->status = -status;
|
||||
clientreply->status = status;
|
||||
clientreply->cmd = CLVMD_CMD_REPLY;
|
||||
clientreply->node[0] = '\0';
|
||||
clientreply->flags = 0;
|
||||
|
||||
ptr = clientreply->args;
|
||||
|
||||
@@ -1438,6 +1463,9 @@ static void send_local_reply(struct local_client *client, int status, int fd)
|
||||
strcpy(ptr, thisreply->node);
|
||||
ptr += strlen(thisreply->node) + 1;
|
||||
|
||||
if (thisreply->status)
|
||||
clientreply->flags |= CLVMD_FLAG_NODEERRS;
|
||||
|
||||
*(int *) ptr = thisreply->status;
|
||||
ptr += sizeof(int);
|
||||
|
||||
@@ -1506,7 +1534,8 @@ static void send_version_message()
|
||||
version_nums[1] = htonl(CLVMD_MINOR_VERSION);
|
||||
version_nums[2] = htonl(CLVMD_PATCH_VERSION);
|
||||
|
||||
cluster_send_message(message, sizeof(message), NULL,
|
||||
hton_clvm(msg);
|
||||
clops->cluster_send_message(message, sizeof(message), NULL,
|
||||
"Error Sending version number");
|
||||
}
|
||||
|
||||
@@ -1518,8 +1547,8 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
|
||||
|
||||
/* Send remote messages down the cluster socket */
|
||||
if (csid == NULL || !ISLOCAL_CSID(csid)) {
|
||||
hton_clvm((struct clvm_header *) buf); /* Byte swap if necessary */
|
||||
return cluster_send_message(buf, msglen, csid, errtext);
|
||||
hton_clvm((struct clvm_header *) buf);
|
||||
return clops->cluster_send_message(buf, msglen, csid, errtext);
|
||||
} else {
|
||||
int ptr = 0;
|
||||
|
||||
@@ -1539,6 +1568,14 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
|
||||
|
||||
static int process_work_item(struct lvm_thread_cmd *cmd)
|
||||
{
|
||||
|
||||
/* If msg is NULL then this is a cleanup request */
|
||||
if (cmd->msg == NULL) {
|
||||
cmd_client_cleanup(cmd->client);
|
||||
free(cmd->client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cmd->remote) {
|
||||
DEBUGLOG("process_work_item: local\n");
|
||||
process_local_command(cmd->msg, cmd->msglen, cmd->client,
|
||||
@@ -1558,9 +1595,9 @@ static void *lvm_thread_fn(void *arg)
|
||||
{
|
||||
struct list *cmdl, *tmp;
|
||||
sigset_t ss;
|
||||
int using_gulm = (int)arg;
|
||||
|
||||
DEBUGLOG("LVM thread function started\n");
|
||||
pthread_mutex_lock(&lvm_thread_mutex);
|
||||
|
||||
/* Ignore SIGUSR1 & 2 */
|
||||
sigemptyset(&ss);
|
||||
@@ -1569,8 +1606,7 @@ static void *lvm_thread_fn(void *arg)
|
||||
pthread_sigmask(SIG_BLOCK, &ss, NULL);
|
||||
|
||||
/* Initialise the interface to liblvm */
|
||||
init_lvm();
|
||||
pthread_mutex_unlock(&lvm_thread_mutex);
|
||||
init_lvm(using_gulm);
|
||||
|
||||
/* Now wait for some actual work */
|
||||
for (;;) {
|
||||
@@ -1606,21 +1642,26 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
|
||||
|
||||
cmd = malloc(sizeof(struct lvm_thread_cmd));
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
|
||||
cmd->msg = malloc(msglen);
|
||||
if (!cmd->msg) {
|
||||
log_error("Unable to allocate buffer space\n");
|
||||
free(cmd);
|
||||
return -1;
|
||||
if (msglen) {
|
||||
cmd->msg = malloc(msglen);
|
||||
if (!cmd->msg) {
|
||||
log_error("Unable to allocate buffer space\n");
|
||||
free(cmd);
|
||||
return -1;
|
||||
}
|
||||
memcpy(cmd->msg, msg, msglen);
|
||||
}
|
||||
else {
|
||||
cmd->msg = NULL;
|
||||
}
|
||||
|
||||
cmd->client = client;
|
||||
cmd->msglen = msglen;
|
||||
cmd->xid = client->xid;
|
||||
memcpy(cmd->msg, msg, msglen);
|
||||
|
||||
if (csid) {
|
||||
memcpy(cmd->csid, csid, MAX_CSID_LEN);
|
||||
memcpy(cmd->csid, csid, max_csid_len);
|
||||
cmd->remote = 1;
|
||||
} else {
|
||||
cmd->remote = 0;
|
||||
@@ -1651,6 +1692,8 @@ static int open_local_sock()
|
||||
log_error("Can't create local socket: %m");
|
||||
return -1;
|
||||
}
|
||||
/* Set Close-on-exec */
|
||||
fcntl(local_socket, F_SETFD, 1);
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
|
||||
@@ -1688,7 +1731,7 @@ static void check_all_callback(struct local_client *client, char *csid,
|
||||
int node_up)
|
||||
{
|
||||
if (!node_up)
|
||||
add_reply_to_list(client, -EHOSTDOWN, csid, "CLVMD not running",
|
||||
add_reply_to_list(client, EHOSTDOWN, csid, "CLVMD not running",
|
||||
18);
|
||||
}
|
||||
|
||||
@@ -1698,7 +1741,7 @@ static void check_all_callback(struct local_client *client, char *csid,
|
||||
static int check_all_clvmds_running(struct local_client *client)
|
||||
{
|
||||
DEBUGLOG("check_all_clvmds_running\n");
|
||||
return cluster_do_node_callback(client, check_all_callback);
|
||||
return clops->cluster_do_node_callback(client, check_all_callback);
|
||||
}
|
||||
|
||||
/* Return a local_client struct given a client ID.
|
||||
@@ -1744,3 +1787,14 @@ static void sigterm_handler(int sig)
|
||||
quit = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
return clops->sync_lock(resource, mode, flags, lockid);
|
||||
}
|
||||
|
||||
int sync_unlock(const char *resource, int lockid)
|
||||
{
|
||||
return clops->sync_unlock(resource, lockid);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ struct local_client {
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUGLOG(fmt, args...) fprintf(stderr, "CLVMD[%d]: %ld ", getpid(), time(NULL) ); fprintf(stderr, fmt, ## args)
|
||||
#define DEBUGLOG(fmt, args...) fprintf(stderr, "CLVMD[%x]: %ld ", (int)pthread_self(), time(NULL) ); fprintf(stderr, fmt, ## args)
|
||||
#else
|
||||
#define DEBUGLOG(fmt, args...)
|
||||
#endif
|
||||
@@ -116,4 +116,8 @@ 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);
|
||||
|
||||
int sync_lock(const char *resource, int mode, int flags, int *lockid);
|
||||
int sync_unlock(const char *resource, int lockid);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -63,8 +63,8 @@
|
||||
|
||||
|
||||
/* Maximum size of a cluster message */
|
||||
#define MAX_CLUSTER_MESSAGE 1500
|
||||
#define MAX_CLUSTER_MEMBER_NAME_LEN 255
|
||||
#define CMAN_MAX_CLUSTER_MESSAGE 1500
|
||||
#define CMAN_MAX_CLUSTER_MEMBER_NAME_LEN 255
|
||||
#define MAX_BARRIER_NAME_LEN 33
|
||||
#define MAX_SA_ADDR_LEN 12
|
||||
#define MAX_CLUSTER_NAME_LEN 16
|
||||
@@ -147,7 +147,7 @@ struct cl_cluster_node {
|
||||
unsigned int leave_reason;
|
||||
unsigned int incarnation;
|
||||
nodestate_t state;
|
||||
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
char name[CMAN_MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
unsigned char votes;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,446 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 1997-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
|
||||
*/
|
||||
|
||||
/* library functions for Cluster LVM Daemon */
|
||||
|
||||
#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/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 <search.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "clvm.h"
|
||||
#include "libclvm.h"
|
||||
|
||||
/* CLVM in hex! */
|
||||
#define LVM_SIGNATURE 0x434C564D
|
||||
|
||||
#define MAX_CLUSTER_MEMBER_NAME_LEN 255
|
||||
|
||||
/* NOTE: the LVMD uses the socket FD as the client ID, this means
|
||||
that any client that calls fork() will inherit the context of
|
||||
it's parent. */
|
||||
static int clvmd_sock = -1;
|
||||
|
||||
static int open_local_sock(void)
|
||||
{
|
||||
int local_socket;
|
||||
struct sockaddr_un sockaddr;
|
||||
|
||||
/* Open local socket */
|
||||
local_socket = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (local_socket < 0) {
|
||||
perror("Can't create local socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fcntl(local_socket, F_SETFD, !FD_CLOEXEC);
|
||||
|
||||
strcpy(sockaddr.sun_path, CLVMD_SOCKNAME);
|
||||
sockaddr.sun_family = AF_UNIX;
|
||||
if (connect
|
||||
(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
|
||||
int saved_errno = errno;
|
||||
|
||||
close(local_socket);
|
||||
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
return local_socket;
|
||||
}
|
||||
|
||||
/* Send a request and return the status */
|
||||
static int send_request(char *inbuf, int inlen, char **retbuf)
|
||||
{
|
||||
char outbuf[PIPE_BUF];
|
||||
struct clvm_header *outheader = (struct clvm_header *) outbuf;
|
||||
int len;
|
||||
int off;
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(clvmd_sock, &fds);
|
||||
|
||||
/* Send it to CLVMD */
|
||||
if (write(clvmd_sock, inbuf, inlen) != inlen) {
|
||||
perror("Error writing to CLVMD");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the response */
|
||||
if ((len = read(clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
|
||||
perror("Error reading CLVMD");
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) {
|
||||
fprintf(stderr, "EOF reading CLVMD");
|
||||
errno = ENOTCONN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
*retbuf = malloc(len + outheader->arglen);
|
||||
if (!*retbuf) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy the header */
|
||||
memcpy(*retbuf, outbuf, len);
|
||||
outheader = (struct clvm_header *) *retbuf;
|
||||
|
||||
/* Read the returned values */
|
||||
off = 1; /* we've already read the first byte */
|
||||
|
||||
while (off < outheader->arglen && len > 0) {
|
||||
len = read(clvmd_sock, outheader->args + off, PIPE_BUF);
|
||||
if (len > 0)
|
||||
off += len;
|
||||
}
|
||||
|
||||
/* Was it an error ? */
|
||||
if (outheader->status < 0) {
|
||||
errno = -outheader->status;
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Build the structure header and parse-out wildcard node names */
|
||||
static void build_header(struct clvm_header *head, int cmd, const char *node,
|
||||
void *data, int len)
|
||||
{
|
||||
head->cmd = cmd;
|
||||
head->status = 0;
|
||||
head->flags = 0;
|
||||
head->clientid = 0;
|
||||
head->arglen = len;
|
||||
if (node) {
|
||||
/* Allow a couple of special node names:
|
||||
"*" for all nodes,
|
||||
"." for the local node only
|
||||
*/
|
||||
if (strcmp(node, "*") == 0) {
|
||||
head->node[0] = '\0';
|
||||
} else if (strcmp(node, ".") == 0) {
|
||||
head->node[0] = '\0';
|
||||
head->flags = CLVMD_FLAG_LOCAL;
|
||||
} else {
|
||||
strcpy(head->node, node);
|
||||
}
|
||||
} else {
|
||||
head->node[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a message to a(or all) node(s) in the cluster */
|
||||
int lvm_cluster_write(char cmd, char *node, void *data, int len)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
struct clvm_header *head = (struct clvm_header *) outbuf;
|
||||
|
||||
if (clvmd_sock == -1)
|
||||
clvmd_sock = open_local_sock();
|
||||
if (clvmd_sock == -1)
|
||||
return -1;
|
||||
|
||||
build_header(head, cmd, node, data, len);
|
||||
memcpy(head->node + strlen(head->node) + 1, data, len);
|
||||
|
||||
status =
|
||||
send_request(outbuf,
|
||||
sizeof(struct clvm_header) + strlen(head->node) + len,
|
||||
&retbuf);
|
||||
if (retbuf)
|
||||
free(retbuf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* API: Send a message to a(or all) node(s) in the cluster
|
||||
and wait for replies */
|
||||
int lvm_cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
int *outptr;
|
||||
char *inptr;
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
int i;
|
||||
int num_responses = 0;
|
||||
struct clvm_header *head = (struct clvm_header *) outbuf;
|
||||
lvm_response_t *rarray;
|
||||
|
||||
*num = 0;
|
||||
|
||||
if (clvmd_sock == -1)
|
||||
clvmd_sock = open_local_sock();
|
||||
if (clvmd_sock == -1)
|
||||
return -1;
|
||||
|
||||
build_header(head, cmd, node, data, len);
|
||||
memcpy(head->node + strlen(head->node) + 1, data, len);
|
||||
|
||||
status =
|
||||
send_request(outbuf,
|
||||
sizeof(struct clvm_header) + strlen(head->node) + len,
|
||||
&retbuf);
|
||||
if (status == 0 || status == -2) {
|
||||
/* Count the number of responses we got */
|
||||
head = (struct clvm_header *) retbuf;
|
||||
inptr = head->args;
|
||||
while (inptr[0]) {
|
||||
num_responses++;
|
||||
inptr += strlen(inptr) + 1;
|
||||
inptr += sizeof(int);
|
||||
inptr += strlen(inptr) + 1;
|
||||
}
|
||||
|
||||
/* Allocate response array. With an extra pair of INTs on the front to sanity
|
||||
check the pointer when we are given it back to free */
|
||||
outptr =
|
||||
malloc(sizeof(lvm_response_t) * num_responses +
|
||||
sizeof(int) * 2);
|
||||
if (!outptr) {
|
||||
if (retbuf)
|
||||
free(retbuf);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*response = (lvm_response_t *) (outptr + 2);
|
||||
outptr[0] = LVM_SIGNATURE;
|
||||
outptr[1] = num_responses;
|
||||
rarray = *response;
|
||||
|
||||
/* Unpack the response into an lvm_response_t array */
|
||||
inptr = head->args;
|
||||
i = 0;
|
||||
while (inptr[0]) {
|
||||
strcpy(rarray[i].node, inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
|
||||
rarray[i].status = *(int *) inptr;
|
||||
inptr += sizeof(int);
|
||||
|
||||
rarray[i].response = malloc(strlen(inptr) + 1);
|
||||
if (rarray[i].response == NULL) {
|
||||
/* Free up everything else and return error */
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
free(rarray[i].response);
|
||||
free(outptr);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(rarray[i].response, inptr);
|
||||
rarray[i].len = strlen(inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
i++;
|
||||
}
|
||||
*num = num_responses;
|
||||
*response = rarray;
|
||||
}
|
||||
|
||||
if (retbuf)
|
||||
free(retbuf);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* API: Free reply array */
|
||||
int lvm_cluster_free_request(lvm_response_t * response)
|
||||
{
|
||||
int *ptr = (int *) response - 2;
|
||||
int i;
|
||||
int num;
|
||||
|
||||
/* Check it's ours to free */
|
||||
if (response == NULL || *ptr != LVM_SIGNATURE) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
num = ptr[1];
|
||||
for (i = 0; i < num; i++) {
|
||||
free(response[i].response);
|
||||
}
|
||||
free(ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* These are a "higher-level" API providing black-box lock/unlock
|
||||
functions for cluster LVM...maybe */
|
||||
|
||||
/* Set by lock(), used by unlock() */
|
||||
static int num_responses;
|
||||
static lvm_response_t *response;
|
||||
|
||||
int lvm_lock_for_cluster(char scope, char *name, int verbosity)
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
char *args;
|
||||
int len;
|
||||
|
||||
if (name) {
|
||||
len = strlen(name) + 2;
|
||||
args = alloca(len);
|
||||
strcpy(args + 1, name);
|
||||
} else {
|
||||
len = 2;
|
||||
args = alloca(len);
|
||||
args[1] = '\0';
|
||||
}
|
||||
args[0] = scope;
|
||||
|
||||
status = lvm_cluster_request(CLVMD_CMD_LOCK,
|
||||
"", args, len, &response, &num_responses);
|
||||
|
||||
/* If any nodes were down then display them and return an error */
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status == -EHOSTDOWN) {
|
||||
if (verbosity)
|
||||
fprintf(stderr,
|
||||
"clvmd not running on node %s\n",
|
||||
response[i].node);
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there was an error then free the memory now as the caller won't
|
||||
want to do the unlock */
|
||||
if (status) {
|
||||
int saved_errno = errno;
|
||||
lvm_cluster_free_request(response);
|
||||
num_responses = 0;
|
||||
errno = saved_errno;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int lvm_unlock_for_cluster(char scope, char *name, int verbosity)
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
int len;
|
||||
int failed;
|
||||
int num_unlock_responses;
|
||||
char *args;
|
||||
lvm_response_t *unlock_response;
|
||||
|
||||
/* We failed - this should not have been called */
|
||||
if (num_responses == 0)
|
||||
return 0;
|
||||
|
||||
if (name) {
|
||||
len = strlen(name) + 2;
|
||||
args = alloca(len);
|
||||
strcpy(args + 1, name);
|
||||
} else {
|
||||
len = 2;
|
||||
args = alloca(len);
|
||||
args[1] = '\0';
|
||||
}
|
||||
args[0] = scope;
|
||||
|
||||
/* See if it failed anywhere */
|
||||
failed = 0;
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status != 0)
|
||||
failed++;
|
||||
}
|
||||
|
||||
/* If it failed on any nodes then we only unlock on
|
||||
the nodes that succeeded */
|
||||
if (failed) {
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
/* Unlock the ones that succeeded */
|
||||
if (response[i].status == 0) {
|
||||
status = lvm_cluster_request(CLVMD_CMD_UNLOCK,
|
||||
response[i].node,
|
||||
args, len,
|
||||
&unlock_response,
|
||||
&num_unlock_responses);
|
||||
if (status) {
|
||||
if (verbosity)
|
||||
fprintf(stderr,
|
||||
"cluster command to node %s failed: %s\n",
|
||||
response[i].node,
|
||||
strerror(errno));
|
||||
} else if (unlock_response[0].status != 0) {
|
||||
if (verbosity > 1)
|
||||
fprintf(stderr,
|
||||
"unlock on node %s failed: %s\n",
|
||||
response[i].node,
|
||||
strerror(unlock_response
|
||||
[0].status));
|
||||
}
|
||||
lvm_cluster_free_request(unlock_response);
|
||||
} else {
|
||||
if (verbosity)
|
||||
fprintf(stderr,
|
||||
"command on node %s failed: '%s' - will be left locked\n",
|
||||
response[i].node,
|
||||
strerror(response[i].status));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* All OK, we can do a full cluster unlock */
|
||||
status = lvm_cluster_request(CLVMD_CMD_UNLOCK,
|
||||
"",
|
||||
args, len,
|
||||
&unlock_response,
|
||||
&num_unlock_responses);
|
||||
if (status) {
|
||||
if (verbosity > 1)
|
||||
fprintf(stderr, "cluster command failed: %s\n",
|
||||
strerror(errno));
|
||||
} else {
|
||||
for (i = 0; i < num_unlock_responses; i++) {
|
||||
if (unlock_response[i].status != 0) {
|
||||
if (verbosity > 1)
|
||||
fprintf(stderr,
|
||||
"unlock on node %s failed: %s\n",
|
||||
response[i].node,
|
||||
strerror(unlock_response
|
||||
[0].status));
|
||||
}
|
||||
}
|
||||
}
|
||||
lvm_cluster_free_request(unlock_response);
|
||||
}
|
||||
lvm_cluster_free_request(response);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 1997-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 _LIBCLVM_H
|
||||
#define _LIBCLVM_H
|
||||
|
||||
typedef struct lvm_response {
|
||||
char node[255];
|
||||
char *response;
|
||||
int status;
|
||||
int len;
|
||||
|
||||
} lvm_response_t;
|
||||
|
||||
extern int lvm_cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num);
|
||||
extern int lvm_cluster_write(char cmd, char *node, void *data, int len);
|
||||
extern int lvm_cluster_free_request(lvm_response_t * response);
|
||||
|
||||
/* The "high-level" API */
|
||||
extern int lvm_lock_for_cluster(char scope, char *name, int verbosity);
|
||||
extern int lvm_unlock_for_cluster(char scope, char *name, int verbosity);
|
||||
|
||||
#endif
|
||||
@@ -198,7 +198,7 @@ static int do_activate_lv(char *resource, int mode)
|
||||
return errno;
|
||||
|
||||
/* If it's suspended then resume it */
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi))
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
|
||||
return EIO;
|
||||
|
||||
if (lvi.suspended)
|
||||
@@ -244,7 +244,7 @@ static int do_suspend_lv(char *resource)
|
||||
}
|
||||
|
||||
/* Only suspend it if it exists */
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi))
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
|
||||
return EIO;
|
||||
|
||||
if (lvi.exists) {
|
||||
@@ -363,7 +363,7 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
if (oldmode == LKM_PWMODE) {
|
||||
struct lvinfo lvi;
|
||||
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi))
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
|
||||
return EIO;
|
||||
|
||||
if (lvi.exists) {
|
||||
@@ -388,6 +388,44 @@ int do_check_lvm1(char *vgname)
|
||||
return status == 1 ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
|
||||
/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
|
||||
that might be hanging around if we died for any reason
|
||||
*/
|
||||
static void drop_vg_locks()
|
||||
{
|
||||
char vg[128];
|
||||
char line[255];
|
||||
FILE *vgs =
|
||||
popen
|
||||
("lvm pvs --nolocking --noheadings -o vg_name", "r");
|
||||
|
||||
sync_unlock("P_orphans", LCK_EXCL);
|
||||
|
||||
if (!vgs)
|
||||
return;
|
||||
|
||||
while (fgets(line, sizeof(line), vgs)) {
|
||||
char *vgend;
|
||||
char *vgstart;
|
||||
|
||||
if (line[strlen(line)-1] == '\n')
|
||||
line[strlen(line)-1] = '\0';
|
||||
|
||||
vgstart = line + strspn(line, " ");
|
||||
vgend = vgstart + strcspn(vgstart, " ");
|
||||
*vgend = '\0';
|
||||
|
||||
if (strncmp(vgstart, "WARNING:", 8) == 0)
|
||||
continue;
|
||||
|
||||
sprintf(vg, "V_%s", vgstart);
|
||||
sync_unlock(vg, LCK_EXCL);
|
||||
|
||||
}
|
||||
fclose(vgs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ideally, clvmd should be started before any LVs are active
|
||||
* but this may not be the case...
|
||||
@@ -400,7 +438,7 @@ static void *get_initial_state()
|
||||
char line[255];
|
||||
FILE *lvs =
|
||||
popen
|
||||
("/sbin/lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr",
|
||||
("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr",
|
||||
"r");
|
||||
|
||||
if (!lvs)
|
||||
@@ -438,6 +476,30 @@ static void *get_initial_state()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This checks some basic cluster-LVM configuration stuff */
|
||||
static void check_config()
|
||||
{
|
||||
int locking_type;
|
||||
|
||||
locking_type = find_config_int(cmd->cft->root, "global/locking_type", 1);
|
||||
|
||||
if (locking_type == 3) /* compiled-in cluster support */
|
||||
return;
|
||||
|
||||
if (locking_type == 2) { /* External library, check name */
|
||||
const char *libname;
|
||||
|
||||
libname = find_config_str(cmd->cft->root, "global/locking_library",
|
||||
"");
|
||||
if (strstr(libname, "liblvm2clusterlock.so"))
|
||||
return;
|
||||
|
||||
log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
|
||||
return;
|
||||
}
|
||||
log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
|
||||
}
|
||||
|
||||
void init_lvhash()
|
||||
{
|
||||
/* Create hash table for keeping LV locks & status */
|
||||
@@ -446,7 +508,7 @@ void init_lvhash()
|
||||
}
|
||||
|
||||
/* Called to initialise the LVM context of the daemon */
|
||||
int init_lvm(void)
|
||||
int init_lvm(int using_gulm)
|
||||
{
|
||||
if (!(cmd = create_toolcontext(NULL))) {
|
||||
log_error("Failed to allocate command context");
|
||||
@@ -457,6 +519,13 @@ int init_lvm(void)
|
||||
init_syslog(LOG_DAEMON);
|
||||
init_debug(_LOG_ERR);
|
||||
|
||||
/* Check lvm.conf is setup for cluster-LVM */
|
||||
check_config();
|
||||
|
||||
/* Remove any non-LV locks that may have been left around */
|
||||
if (using_gulm)
|
||||
drop_vg_locks();
|
||||
|
||||
get_initial_state();
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -25,7 +25,7 @@ extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_check_lvm1(char *vgname);
|
||||
extern int init_lvm(void);
|
||||
extern int init_lvm(int using_gulm);
|
||||
extern void init_lvhash(void);
|
||||
|
||||
extern int hold_unlock(char *resource);
|
||||
|
||||
@@ -42,7 +42,9 @@
|
||||
#include "list.h"
|
||||
#include "locking.h"
|
||||
#include "system-lv.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvmd.h"
|
||||
#ifdef HAVE_CCS
|
||||
#include "ccs.h"
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
|
||||
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
@@ -84,6 +85,9 @@ int init_comms(unsigned short port)
|
||||
|
||||
listen(listen_fd, 5);
|
||||
|
||||
/* Set Close-on-exec */
|
||||
fcntl(listen_fd, F_SETFD, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -96,19 +100,19 @@ void tcp_remove_client(char *csid)
|
||||
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 = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
client = hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (client)
|
||||
{
|
||||
hash_remove_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
/* Look for a mangled one too */
|
||||
csid[0] ^= 0x80;
|
||||
|
||||
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
client = hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (client)
|
||||
{
|
||||
hash_remove_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
/* Put it back as we found it */
|
||||
@@ -137,7 +141,7 @@ int alloc_client(int fd, char *csid, struct local_client **new_client)
|
||||
*new_client = client;
|
||||
|
||||
/* Add to our list of node sockets */
|
||||
if (hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN))
|
||||
if (hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN))
|
||||
{
|
||||
DEBUGLOG("alloc_client mangling CSID for second connection\n");
|
||||
/* This is a duplicate connection but we can't close it because
|
||||
@@ -150,7 +154,7 @@ int alloc_client(int fd, char *csid, struct local_client **new_client)
|
||||
|
||||
/* If it still exists then kill the connection as we should only
|
||||
ever have one incoming connection from each node */
|
||||
if (hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN))
|
||||
if (hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN))
|
||||
{
|
||||
DEBUGLOG("Multiple incoming connections from node\n");
|
||||
syslog(LOG_ERR, " Bogus incoming connection from %d.%d.%d.%d\n", csid[0],csid[1],csid[2],csid[3]);
|
||||
@@ -160,26 +164,26 @@ int alloc_client(int fd, char *csid, struct local_client **new_client)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
hash_insert_binary(sock_hash, csid, MAX_CSID_LEN, client);
|
||||
hash_insert_binary(sock_hash, csid, GULM_MAX_CSID_LEN, client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_main_cluster_fd()
|
||||
int get_main_gulm_cluster_fd()
|
||||
{
|
||||
return listen_fd;
|
||||
}
|
||||
|
||||
|
||||
/* Read on main comms (listen) socket, accept it */
|
||||
int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
int newfd;
|
||||
struct sockaddr_in6 addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int status;
|
||||
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
|
||||
DEBUGLOG("cluster_fd_callback\n");
|
||||
*new_client = NULL;
|
||||
@@ -196,7 +200,7 @@ int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
/* Check that the client is a member of the cluster
|
||||
and reject if not.
|
||||
*/
|
||||
if (name_from_csid((char *)&addr.sin6_addr, name) < 0)
|
||||
if (gulm_name_from_csid((char *)&addr.sin6_addr, name) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Got connect from non-cluster node %s\n",
|
||||
print_csid((char *)&addr.sin6_addr));
|
||||
@@ -227,16 +231,37 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
|
||||
{
|
||||
struct sockaddr_in6 addr;
|
||||
socklen_t slen = sizeof(addr);
|
||||
struct clvm_header *header = (struct clvm_header *)buf;
|
||||
int status;
|
||||
uint32_t arglen;
|
||||
|
||||
DEBUGLOG("read_from_tcpsock fd %d\n", client->fd);
|
||||
*new_client = NULL;
|
||||
|
||||
/* Get "csid" */
|
||||
getpeername(client->fd, (struct sockaddr *)&addr, &slen);
|
||||
memcpy(csid, &addr.sin6_addr, MAX_CSID_LEN);
|
||||
memcpy(csid, &addr.sin6_addr, GULM_MAX_CSID_LEN);
|
||||
|
||||
status = read(client->fd, buf, len);
|
||||
/* Read just the header first, then get the rest if there is any.
|
||||
* Stream sockets, sigh.
|
||||
*/
|
||||
status = read(client->fd, buf, sizeof(struct clvm_header));
|
||||
if (status > 0)
|
||||
{
|
||||
int status2;
|
||||
|
||||
arglen = ntohl(header->arglen);
|
||||
|
||||
/* Get the rest */
|
||||
if (arglen && arglen < GULM_MAX_CLUSTER_MESSAGE)
|
||||
{
|
||||
status2 = read(client->fd, buf+status, arglen);
|
||||
if (status2 > 0)
|
||||
status += status2;
|
||||
else
|
||||
status = status2;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGLOG("read_from_tcpsock, status = %d(errno = %d)\n", status, errno);
|
||||
|
||||
@@ -245,27 +270,28 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
|
||||
if (status == 0 ||
|
||||
(status < 0 && errno != EAGAIN && errno != EINTR))
|
||||
{
|
||||
char remcsid[MAX_CSID_LEN];
|
||||
char remcsid[GULM_MAX_CSID_LEN];
|
||||
|
||||
memcpy(remcsid, csid, MAX_CSID_LEN);
|
||||
memcpy(remcsid, csid, GULM_MAX_CSID_LEN);
|
||||
close(client->fd);
|
||||
|
||||
/* If the csid was mangled, then make sure we remove the right entry */
|
||||
if (client->bits.net.flags)
|
||||
remcsid[0] ^= 0x80;
|
||||
hash_remove_binary(sock_hash, remcsid, MAX_CSID_LEN);
|
||||
hash_remove_binary(sock_hash, remcsid, GULM_MAX_CSID_LEN);
|
||||
|
||||
/* Tell cluster manager layer */
|
||||
add_down_node(remcsid);
|
||||
}
|
||||
else {
|
||||
gulm_add_up_node(csid);
|
||||
/* Send it back to clvmd */
|
||||
process_message(client, buf, len, csid);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int connect_csid(char *csid, struct local_client **newclient)
|
||||
int gulm_connect_csid(char *csid, struct local_client **newclient)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_in6 addr;
|
||||
@@ -281,18 +307,27 @@ static int connect_csid(char *csid, struct local_client **newclient)
|
||||
}
|
||||
|
||||
addr.sin6_family = AF_INET6;
|
||||
memcpy(&addr.sin6_addr, csid, MAX_CSID_LEN);
|
||||
memcpy(&addr.sin6_addr, csid, GULM_MAX_CSID_LEN);
|
||||
addr.sin6_port = htons(tcp_port);
|
||||
|
||||
DEBUGLOG("Connecting socket %d\n", fd);
|
||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Unable to connect to remote node: %m");
|
||||
/* "Connection refused" is "normal" because clvmd may not yet be running
|
||||
* on that node.
|
||||
*/
|
||||
if (errno != ECONNREFUSED)
|
||||
{
|
||||
syslog(LOG_ERR, "Unable to connect to remote node: %m");
|
||||
}
|
||||
DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set Close-on-exec */
|
||||
fcntl(fd, F_SETFD, 1);
|
||||
|
||||
status = alloc_client(fd, csid, newclient);
|
||||
if (status)
|
||||
close(fd);
|
||||
@@ -300,7 +335,7 @@ static int connect_csid(char *csid, struct local_client **newclient)
|
||||
add_client(*newclient);
|
||||
|
||||
/* If we can connect to it, it must be running a clvmd */
|
||||
add_up_node(csid);
|
||||
gulm_add_up_node(csid);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -309,21 +344,21 @@ static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const ch
|
||||
{
|
||||
int status;
|
||||
struct local_client *client;
|
||||
char ourcsid[MAX_CSID_LEN];
|
||||
char ourcsid[GULM_MAX_CSID_LEN];
|
||||
|
||||
assert(csid);
|
||||
|
||||
DEBUGLOG("tcp_send_message, csid = %s, msglen = %d\n", print_csid(csid), msglen);
|
||||
|
||||
/* Don't connect to ourself */
|
||||
get_our_csid(ourcsid);
|
||||
if (memcmp(csid, ourcsid, MAX_CSID_LEN) == 0)
|
||||
get_our_gulm_csid(ourcsid);
|
||||
if (memcmp(csid, ourcsid, GULM_MAX_CSID_LEN) == 0)
|
||||
return msglen;
|
||||
|
||||
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
client = hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (!client)
|
||||
{
|
||||
status = connect_csid(csid, &client);
|
||||
status = gulm_connect_csid(csid, &client);
|
||||
if (status)
|
||||
return -1;
|
||||
}
|
||||
@@ -333,7 +368,7 @@ static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const ch
|
||||
}
|
||||
|
||||
|
||||
int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
{
|
||||
int status=0;
|
||||
|
||||
@@ -343,7 +378,7 @@ int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
if (!csid)
|
||||
{
|
||||
void *context = NULL;
|
||||
char loop_csid[MAX_CSID_LEN];
|
||||
char loop_csid[GULM_MAX_CSID_LEN];
|
||||
|
||||
/* Loop round all gulm-known nodes */
|
||||
while (get_next_node_csid(&context, loop_csid))
|
||||
@@ -377,9 +412,9 @@ static int get_our_ip_address(char *addr, int *family)
|
||||
|
||||
/* Public version of above for those that don't care what protocol
|
||||
we're using */
|
||||
void get_our_csid(char *csid)
|
||||
void get_our_gulm_csid(char *csid)
|
||||
{
|
||||
static char our_csid[MAX_CSID_LEN];
|
||||
static char our_csid[GULM_MAX_CSID_LEN];
|
||||
static int got_csid = 0;
|
||||
|
||||
if (!got_csid)
|
||||
@@ -392,7 +427,7 @@ void get_our_csid(char *csid)
|
||||
got_csid = 1;
|
||||
}
|
||||
}
|
||||
memcpy(csid, our_csid, MAX_CSID_LEN);
|
||||
memcpy(csid, our_csid, GULM_MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
|
||||
@@ -408,7 +443,7 @@ int get_ip_address(char *node, char *addr)
|
||||
{
|
||||
struct hostent *he;
|
||||
|
||||
memset(addr, 0, MAX_CSID_LEN);
|
||||
memset(addr, 0, GULM_MAX_CSID_LEN);
|
||||
|
||||
// TODO: what do we do about multi-homed hosts ???
|
||||
// CCSs ip_interfaces solved this but some bugger removed it.
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define MAX_CLUSTER_MESSAGE 1600
|
||||
#define MAX_CSID_LEN sizeof(struct in6_addr)
|
||||
#define MAX_CLUSTER_MEMBER_NAME_LEN 128
|
||||
#define GULM_MAX_CLUSTER_MESSAGE 1600
|
||||
#define GULM_MAX_CSID_LEN sizeof(struct in6_addr)
|
||||
#define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128
|
||||
|
||||
extern int init_comms(unsigned short);
|
||||
extern char *print_csid(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);
|
||||
|
||||
@@ -258,11 +258,10 @@ activation {
|
||||
#
|
||||
# metadata {
|
||||
# Default number of copies of metadata to hold on each PV. 0, 1 or 2.
|
||||
# It's best to leave this at 2.
|
||||
# You might want to override it from the command line with 0 or 1
|
||||
# You might want to override it from the command line with 0
|
||||
# when running pvcreate on new PVs which are to be added to large VGs.
|
||||
|
||||
# pvmetadatacopies = 2
|
||||
# pvmetadatacopies = 1
|
||||
|
||||
# Approximate default size of on-disk metadata areas in sectors.
|
||||
# You should increase this if you have large volume groups or
|
||||
|
||||
@@ -78,12 +78,13 @@ int target_present(const char *target_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info,
|
||||
int with_open_count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info)
|
||||
struct lvinfo *info, int with_open_count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -333,7 +334,7 @@ int target_present(const char *target_name)
|
||||
* Returns 1 if info structure populated, else 0 on failure.
|
||||
*/
|
||||
static int _lv_info(const struct logical_volume *lv, int mknodes,
|
||||
struct lvinfo *info)
|
||||
struct lvinfo *info, int with_open_count)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -347,7 +348,7 @@ static int _lv_info(const struct logical_volume *lv, int mknodes,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(r = dev_manager_info(dm, lv, mknodes, &dminfo)))
|
||||
if (!(r = dev_manager_info(dm, lv, mknodes, with_open_count, &dminfo)))
|
||||
stack;
|
||||
|
||||
info->exists = dminfo.exists;
|
||||
@@ -361,20 +362,21 @@ static int _lv_info(const struct logical_volume *lv, int mknodes,
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info,
|
||||
int with_open_count)
|
||||
{
|
||||
return _lv_info(lv, 0, info);
|
||||
return _lv_info(lv, 0, info, with_open_count);
|
||||
}
|
||||
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info)
|
||||
struct lvinfo *info, int with_open_count)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
||||
return 0;
|
||||
|
||||
return _lv_info(lv, 0, info);
|
||||
return _lv_info(lv, 0, info, with_open_count);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -412,7 +414,7 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!lv_info(lv, &info)) {
|
||||
if (!lv_info(lv, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -437,7 +439,7 @@ static int _lv_active(struct logical_volume *lv)
|
||||
{
|
||||
struct lvinfo info;
|
||||
|
||||
if (!lv_info(lv, &info)) {
|
||||
if (!lv_info(lv, &info, 0)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
@@ -449,7 +451,7 @@ static int _lv_open_count(struct logical_volume *lv)
|
||||
{
|
||||
struct lvinfo info;
|
||||
|
||||
if (!lv_info(lv, &info)) {
|
||||
if (!lv_info(lv, &info, 1)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
@@ -566,7 +568,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_info(lv, &info)) {
|
||||
if (!lv_info(lv, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -612,7 +614,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_info(lv, &info)) {
|
||||
if (!lv_info(lv, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -657,7 +659,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_info(lv, &info)) {
|
||||
if (!lv_info(lv, &info, 1)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -726,7 +728,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_info(lv, &info)) {
|
||||
if (!lv_info(lv, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -765,7 +767,7 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!_lv_info(lv, 1, &info)) {
|
||||
if (!_lv_info(lv, 1, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -55,9 +55,10 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
||||
/*
|
||||
* Returns 1 if info structure has been populated, else 0.
|
||||
*/
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info);
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info,
|
||||
int with_open_count);
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info);
|
||||
struct lvinfo *info, int with_open_count);
|
||||
|
||||
/*
|
||||
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
|
||||
|
||||
@@ -211,7 +211,8 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
|
||||
}
|
||||
|
||||
static int _info_run(const char *name, const char *uuid, struct dm_info *info,
|
||||
int mknodes, struct pool *mem, char **uuid_out)
|
||||
int mknodes, int with_open_count, struct pool *mem,
|
||||
char **uuid_out)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
@@ -225,6 +226,10 @@ static int _info_run(const char *name, const char *uuid, struct dm_info *info,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!with_open_count)
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
stack;
|
||||
goto out;
|
||||
@@ -250,14 +255,17 @@ static int _info_run(const char *name, const char *uuid, struct dm_info *info,
|
||||
}
|
||||
|
||||
static int _info(const char *name, const char *uuid, int mknodes,
|
||||
struct dm_info *info, struct pool *mem, char **uuid_out)
|
||||
int with_open_count, struct dm_info *info,
|
||||
struct pool *mem, char **uuid_out)
|
||||
{
|
||||
if (!mknodes && uuid && *uuid &&
|
||||
_info_run(NULL, uuid, info, 0, mem, uuid_out) && info->exists)
|
||||
_info_run(NULL, uuid, info, 0, with_open_count, mem, uuid_out) &&
|
||||
info->exists)
|
||||
return 1;
|
||||
|
||||
if (name)
|
||||
return _info_run(name, NULL, info, mknodes, mem, uuid_out);
|
||||
return _info_run(name, NULL, info, mknodes, with_open_count,
|
||||
mem, uuid_out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -279,6 +287,9 @@ static int _status_run(const char *name, const char *uuid,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
stack;
|
||||
goto out;
|
||||
@@ -357,6 +368,9 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
stack;
|
||||
goto out;
|
||||
@@ -460,6 +474,9 @@ static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
|
||||
if (!(r = dm_task_run(dmt))) {
|
||||
log_error("Couldn't rename device '%s'.", dl->name);
|
||||
goto out;
|
||||
@@ -488,6 +505,9 @@ static int _suspend_or_resume(const char *name, action_t suspend)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
|
||||
if (!(r = dm_task_run(dmt)))
|
||||
log_error("Couldn't %s device '%s'", sus ? "suspend" : "resume",
|
||||
name);
|
||||
@@ -579,6 +599,9 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
|
||||
log_very_verbose("Activating %s read-only", dl->name);
|
||||
}
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
|
||||
if (!(r = dm_task_run(dmt))) {
|
||||
log_error("Couldn't load device '%s'.", dl->name);
|
||||
if ((dl->lv->minor >= 0 || dl->lv->major >= 0) &&
|
||||
@@ -635,6 +658,9 @@ static int _remove(struct dev_layer *dl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
|
||||
/* Suppress error message if it's still in use - we'll log it later */
|
||||
log_suppress(1);
|
||||
|
||||
@@ -852,6 +878,7 @@ static int _populate_snapshot(struct dev_manager *dm,
|
||||
struct snapshot *s;
|
||||
struct dev_layer *dlo, *dlc;
|
||||
char devbufo[10], devbufc[10];
|
||||
uint64_t size;
|
||||
|
||||
if (!(s = find_cow(dl->lv))) {
|
||||
log_error("Couldn't find snapshot for '%s'.", dl->lv->name);
|
||||
@@ -899,10 +926,10 @@ static int _populate_snapshot(struct dev_manager *dm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("Adding target: 0 %" PRIu64 " snapshot %s",
|
||||
s->origin->size, params);
|
||||
if (!dm_task_add_target
|
||||
(dmt, UINT64_C(0), s->origin->size, "snapshot", params)) {
|
||||
size = (uint64_t) s->le_count * s->origin->vg->extent_size;
|
||||
|
||||
log_debug("Adding target: 0 %" PRIu64 " snapshot %s", size, params);
|
||||
if (!dm_task_add_target(dmt, UINT64_C(0), size, "snapshot", params)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -970,7 +997,7 @@ void dev_manager_destroy(struct dev_manager *dm)
|
||||
}
|
||||
|
||||
int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
int mknodes, struct dm_info *info)
|
||||
int mknodes, int with_open_count, struct dm_info *info)
|
||||
{
|
||||
char *name;
|
||||
|
||||
@@ -986,7 +1013,8 @@ int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
* Try and get some info on this device.
|
||||
*/
|
||||
log_debug("Getting device info for %s", name);
|
||||
if (!_info(name, lv->lvid.s, mknodes, info, NULL, NULL)) {
|
||||
if (!_info(name, lv->lvid.s, mknodes, with_open_count, info, NULL,
|
||||
NULL)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1065,7 +1093,7 @@ static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
|
||||
dl->name = name;
|
||||
|
||||
log_debug("Getting device info for %s", dl->name);
|
||||
if (!_info(dl->name, dlid, 0, &dl->info, dm->mem, &uuid)) {
|
||||
if (!_info(dl->name, dlid, 0, 0, &dl->info, dm->mem, &uuid)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ void dev_manager_exit(void);
|
||||
* unsuspended until the snapshot is also created.)
|
||||
*/
|
||||
int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
int mknodes, struct dm_info *info);
|
||||
int mknodes, int with_open_count, struct dm_info *info);
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, float *percent);
|
||||
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
|
||||
@@ -65,7 +65,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_empty_dir(vg_path)) {
|
||||
if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
|
||||
log_very_verbose("Removing directory %s", vg_path);
|
||||
rmdir(vg_path);
|
||||
}
|
||||
|
||||
29
lib/cache/lvmcache.c
vendored
29
lib/cache/lvmcache.c
vendored
@@ -104,10 +104,30 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
|
||||
const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct label *label;
|
||||
struct list *ih, *devh, *tmp;
|
||||
struct list devs;
|
||||
struct device_list *devl;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(vgname)))
|
||||
return NULL;
|
||||
|
||||
/* This function is normally called before reading metadata so
|
||||
* we check cached labels here. Unfortunately vginfo is volatile. */
|
||||
list_init(&devs);
|
||||
list_iterate(ih, &vginfo->infos) {
|
||||
devl = malloc(sizeof(*devl));
|
||||
devl->dev = list_item(ih, struct lvmcache_info)->dev;
|
||||
list_add(&devs, &devl->list);
|
||||
}
|
||||
|
||||
list_iterate_safe(devh, tmp, &devs) {
|
||||
devl = list_item(devh, struct device_list);
|
||||
label_read(devl->dev, &label);
|
||||
list_del(&devl->list);
|
||||
free(devl);
|
||||
}
|
||||
|
||||
return vginfo->fmt;
|
||||
}
|
||||
|
||||
@@ -188,7 +208,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->filter))) {
|
||||
if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1: 0))) {
|
||||
log_error("dev_iter creation failed");
|
||||
goto out;
|
||||
}
|
||||
@@ -266,7 +286,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||
if (memlock())
|
||||
return NULL;
|
||||
|
||||
lvmcache_label_scan(cmd, 1);
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
|
||||
/* Try again */
|
||||
if ((info = info_from_pvid((char *) pvid))) {
|
||||
@@ -403,6 +423,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
/* FIXME Check consistency of list! */
|
||||
vginfo->fmt = info->fmt;
|
||||
|
||||
log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
|
||||
*vgname ? "in VG " : "orphaned", vgname);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -551,6 +574,8 @@ static void _lvmcache_destroy_lockname(int present)
|
||||
|
||||
void lvmcache_destroy(void)
|
||||
{
|
||||
log_verbose("Wiping internal VG cache");
|
||||
|
||||
_has_scanned = 0;
|
||||
|
||||
if (_vgid_hash) {
|
||||
|
||||
3
lib/cache/lvmcache.h
vendored
3
lib/cache/lvmcache.h
vendored
@@ -56,7 +56,8 @@ struct lvmcache_info {
|
||||
int lvmcache_init(void);
|
||||
void lvmcache_destroy(void);
|
||||
|
||||
/* Set full_scan to 1 to reread every filtered device label */
|
||||
/* Set full_scan to 1 to reread every filtered device label or
|
||||
* 2 to rescan /dev for new devices */
|
||||
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
/* Add/delete a device */
|
||||
|
||||
@@ -181,6 +181,12 @@ static int _process_config(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
|
||||
log_error("Warning: proc dir %s not found - some checks will be bypassed",
|
||||
cmd->proc_dir);
|
||||
cmd->proc_dir[0] = '\0';
|
||||
}
|
||||
|
||||
/* activation? */
|
||||
cmd->default_settings.activation = find_config_int(cmd->cft->root,
|
||||
"global/activation",
|
||||
@@ -825,8 +831,13 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
goto error;
|
||||
|
||||
/* Create system directory if it doesn't already exist */
|
||||
if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
|
||||
if (*cmd->sys_dir && !create_dir(cmd->sys_dir)) {
|
||||
log_error("Failed to create LVM2 system dir for metadata backups, config "
|
||||
"files and internal cache.");
|
||||
log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
|
||||
"or empty string.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(cmd->libmem = pool_create("library", 4 * 1024))) {
|
||||
log_error("Library memory pool creation failed");
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "lvm-types.h"
|
||||
#include "btree.h"
|
||||
#include "filter.h"
|
||||
#include "filter-persistent.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
@@ -186,7 +187,7 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
/* Is name already there? */
|
||||
list_iterate(ah, &dev->aliases) {
|
||||
if (!strcmp(list_item(ah, struct str_list)->str, path)) {
|
||||
stack;
|
||||
log_debug("%s: Already in device cache", path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -355,11 +356,11 @@ static int _insert(const char *path, int rec)
|
||||
return r;
|
||||
}
|
||||
|
||||
static void _full_scan(void)
|
||||
static void _full_scan(int dev_scan)
|
||||
{
|
||||
struct list *dh;
|
||||
|
||||
if (_cache.has_scanned)
|
||||
if (_cache.has_scanned && !dev_scan)
|
||||
return;
|
||||
|
||||
list_iterate(dh, &_cache.dirs) {
|
||||
@@ -368,6 +369,7 @@ static void _full_scan(void)
|
||||
};
|
||||
|
||||
_cache.has_scanned = 1;
|
||||
init_full_scan_done(1);
|
||||
}
|
||||
|
||||
int dev_cache_has_scanned(void)
|
||||
@@ -379,15 +381,14 @@ void dev_cache_scan(int do_scan)
|
||||
{
|
||||
if (!do_scan)
|
||||
_cache.has_scanned = 1;
|
||||
else {
|
||||
_cache.has_scanned = 0;
|
||||
_full_scan();
|
||||
}
|
||||
else
|
||||
_full_scan(1);
|
||||
}
|
||||
|
||||
int dev_cache_init(void)
|
||||
{
|
||||
_cache.names = NULL;
|
||||
_cache.has_scanned = 0;
|
||||
|
||||
if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) {
|
||||
stack;
|
||||
@@ -540,7 +541,7 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
||||
return (d && (!f || f->passes_filter(f, d))) ? d : NULL;
|
||||
}
|
||||
|
||||
struct dev_iter *dev_iter_create(struct dev_filter *f)
|
||||
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
|
||||
{
|
||||
struct dev_iter *di = dbg_malloc(sizeof(*di));
|
||||
|
||||
@@ -549,7 +550,14 @@ struct dev_iter *dev_iter_create(struct dev_filter *f)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_full_scan();
|
||||
|
||||
if (dev_scan) {
|
||||
/* Flag gets reset between each command */
|
||||
if (!full_scan_done())
|
||||
persistent_filter_wipe(f); /* Calls _full_scan(1) */
|
||||
} else
|
||||
_full_scan(0);
|
||||
|
||||
di->current = btree_first(_cache.devices);
|
||||
di->filter = f;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f);
|
||||
* Object for iterating through the cache.
|
||||
*/
|
||||
struct dev_iter;
|
||||
struct dev_iter *dev_iter_create(struct dev_filter *f);
|
||||
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
|
||||
void dev_iter_destroy(struct dev_iter *iter);
|
||||
struct device *dev_iter_get(struct dev_iter *iter);
|
||||
|
||||
|
||||
@@ -341,7 +341,10 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
#endif
|
||||
|
||||
if ((dev->fd = open(name, flags, 0777)) < 0) {
|
||||
log_sys_error("open", name);
|
||||
if (quiet)
|
||||
log_sys_debug("open", name);
|
||||
else
|
||||
log_sys_error("open", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
|
||||
size,
|
||||
display_size(cmd, (pv->size -
|
||||
pv->pe_count * pv->pe_size),
|
||||
(uint64_t) pv->pe_count * pv->pe_size),
|
||||
SIZE_SHORT));
|
||||
|
||||
} else
|
||||
@@ -317,7 +317,7 @@ void lvdisplay_colons(struct logical_volume *lv)
|
||||
{
|
||||
int inkernel;
|
||||
struct lvinfo info;
|
||||
inkernel = lv_info(lv, &info) && info.exists;
|
||||
inkernel = lv_info(lv, &info, 1) && info.exists;
|
||||
|
||||
log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
|
||||
lv->vg->cmd->dev_dir,
|
||||
@@ -348,7 +348,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
inkernel = lv_info(lv, &info) && info.exists;
|
||||
inkernel = lv_info(lv, &info, 1) && info.exists;
|
||||
|
||||
log_print("--- Logical volume ---");
|
||||
|
||||
|
||||
@@ -53,7 +53,9 @@ int persistent_filter_wipe(struct dev_filter *f)
|
||||
{
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
|
||||
log_verbose("Wiping cache of LVM-capable devices");
|
||||
hash_wipe(pf->devices);
|
||||
|
||||
/* Trigger complete device scan */
|
||||
dev_cache_scan(1);
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ static int _read_devs(struct dev_set *ds, const char *dir)
|
||||
unsigned char dtype;
|
||||
struct stat info;
|
||||
char path[PATH_MAX];
|
||||
dev_t dev;
|
||||
dev_t dev = { 0 };
|
||||
int r = 1;
|
||||
|
||||
if (!(dr = opendir(dir))) {
|
||||
|
||||
@@ -69,6 +69,7 @@ static const device_info_t device_info[] = {
|
||||
{"power2", 16}, /* EMC Powerpath */
|
||||
{"i2o_block", 16}, /* i2o Block Disk */
|
||||
{"iseries/vd", 8}, /* iSeries disks */
|
||||
{"gnbd", 1}, /* Network block device */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
@@ -87,7 +88,7 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
|
||||
}
|
||||
|
||||
/* Check it's accessible */
|
||||
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
|
||||
if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
|
||||
log_debug("%s: Skipping: open failed", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
||||
/* vgcache_del(vg_name); */
|
||||
}
|
||||
|
||||
if (!(iter = dev_iter_create(filter))) {
|
||||
if (!(iter = dev_iter_create(filter, 1))) {
|
||||
log_error("read_pvs_in_vg: dev_iter_create failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -646,7 +646,7 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
|
||||
continue;
|
||||
|
||||
/* insert the snapshot */
|
||||
if (!vg_add_snapshot(org, cow, 1, NULL,
|
||||
if (!vg_add_snapshot(org, cow, 1, NULL, org->le_count,
|
||||
lvd->lv_chunk_size)) {
|
||||
log_err("Couldn't add snapshot.");
|
||||
return 0;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "metadata.h"
|
||||
#include "pool.h"
|
||||
|
||||
#define MINOR_OFFSET 65536
|
||||
|
||||
/* From NSP.cf */
|
||||
#define NSPMajorVersion 4
|
||||
#define NSPMinorVersion 1
|
||||
@@ -66,29 +68,6 @@ struct pool_list;
|
||||
struct user_subpool;
|
||||
struct user_device;
|
||||
|
||||
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
|
||||
|
||||
/* Generic Labels */
|
||||
#define SPTYPE_DATA (0x00000000)
|
||||
|
||||
/* GFS specific labels */
|
||||
#define SPTYPE_GFS_DATA (0x68011670)
|
||||
#define SPTYPE_GFS_JOURNAL (0x69011670)
|
||||
|
||||
struct sptype_name {
|
||||
const char *name;
|
||||
uint32_t label;
|
||||
};
|
||||
|
||||
static const struct sptype_name sptype_names[] = {
|
||||
{"data", SPTYPE_DATA},
|
||||
|
||||
{"gfs_data", SPTYPE_GFS_DATA},
|
||||
{"gfs_journal", SPTYPE_GFS_JOURNAL},
|
||||
|
||||
{"", 0x0} /* This must be the last flag. */
|
||||
};
|
||||
|
||||
struct pool_disk {
|
||||
uint64_t pl_magic; /* Pool magic number */
|
||||
uint64_t pl_pool_id; /* Unique pool identifier */
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "metadata.h"
|
||||
#include "lvmcache.h"
|
||||
#include "disk_rep.h"
|
||||
#include "sptype_names.h"
|
||||
#include "lv_alloc.h"
|
||||
#include "str_list.h"
|
||||
#include "display.h"
|
||||
@@ -107,7 +108,7 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
|
||||
/* for pool a minor of 0 is dynamic */
|
||||
if (pl->pd.pl_minor) {
|
||||
lv->status |= FIXED_MINOR;
|
||||
lv->minor = pl->pd.pl_minor;
|
||||
lv->minor = pl->pd.pl_minor + MINOR_OFFSET;
|
||||
} else {
|
||||
lv->minor = -1;
|
||||
}
|
||||
|
||||
42
lib/format_pool/sptype_names.h
Normal file
42
lib/format_pool/sptype_names.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 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 SPTYPE_NAMES_H
|
||||
#define SPTYPE_NAMES_H
|
||||
|
||||
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
|
||||
|
||||
/* Generic Labels */
|
||||
#define SPTYPE_DATA (0x00000000)
|
||||
|
||||
/* GFS specific labels */
|
||||
#define SPTYPE_GFS_DATA (0x68011670)
|
||||
#define SPTYPE_GFS_JOURNAL (0x69011670)
|
||||
|
||||
struct sptype_name {
|
||||
const char *name;
|
||||
uint32_t label;
|
||||
};
|
||||
|
||||
static const struct sptype_name sptype_names[] = {
|
||||
{"data", SPTYPE_DATA},
|
||||
|
||||
{"gfs_data", SPTYPE_GFS_DATA},
|
||||
{"gfs_journal", SPTYPE_GFS_JOURNAL},
|
||||
|
||||
{"", 0x0} /* This must be the last flag. */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -53,7 +53,7 @@ struct archive_file {
|
||||
struct list list;
|
||||
|
||||
char *path;
|
||||
int index;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -132,7 +132,8 @@ static char *_join(struct pool *mem, const char *dir, const char *name)
|
||||
static struct list *_scan_archive(struct pool *mem,
|
||||
const char *vgname, const char *dir)
|
||||
{
|
||||
int i, count, ix;
|
||||
int i, count;
|
||||
uint32_t ix;
|
||||
char vgname_found[64], *path;
|
||||
struct dirent **dirent;
|
||||
struct archive_file *af;
|
||||
@@ -240,7 +241,7 @@ int archive_vg(struct volume_group *vg,
|
||||
uint32_t retain_days, uint32_t min_archive)
|
||||
{
|
||||
int i, fd, renamed = 0;
|
||||
unsigned int ix = 0;
|
||||
uint32_t ix = 0;
|
||||
struct archive_file *last;
|
||||
FILE *fp = NULL;
|
||||
char temp_file[PATH_MAX], archive_name[PATH_MAX];
|
||||
@@ -285,7 +286,7 @@ int archive_vg(struct volume_group *vg,
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (lvm_snprintf(archive_name, sizeof(archive_name),
|
||||
"%s/%s_%05d.vg", dir, vg->name, ix) < 0) {
|
||||
"%s/%s_%05u.vg", dir, vg->name, ix) < 0) {
|
||||
log_error("Archive file name too long.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -513,7 +513,7 @@ static int _print_snapshot(struct formatter *f, struct snapshot *snap,
|
||||
}
|
||||
|
||||
seg.le = 0;
|
||||
seg.len = snap->origin->le_count;
|
||||
seg.len = snap->le_count;
|
||||
seg.origin = snap->origin;
|
||||
seg.cow = snap->cow;
|
||||
seg.chunk_size = snap->chunk_size;
|
||||
|
||||
@@ -88,8 +88,11 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
}
|
||||
*/
|
||||
|
||||
if (!*lv->lvid.s)
|
||||
lvid_create(&lv->lvid, &lv->vg->id);
|
||||
if (!*lv->lvid.s && !lvid_create(&lv->lvid, &lv->vg->id)) {
|
||||
log_error("Random lvid creation failed for %s/%s.",
|
||||
lv->vg->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -185,6 +188,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
size_t len;
|
||||
char vgnamebuf[NAME_LEN + 2];
|
||||
struct raw_locn *rlocn;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
rlocn = mdah->raw_locns;
|
||||
|
||||
@@ -193,7 +197,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
sizeof(vgnamebuf), vgnamebuf)) {
|
||||
stack;
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
|
||||
(isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
|
||||
@@ -202,6 +206,10 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
rlocn++;
|
||||
}
|
||||
|
||||
error:
|
||||
if ((info = info_from_pvid(dev_area->dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -261,7 +269,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
|
||||
}
|
||||
|
||||
if (!(rlocn = _vg_posn(fid, area, vgname))) {
|
||||
stack;
|
||||
log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1180,9 +1188,9 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Perform full scan and try again */
|
||||
if (!memlock()) {
|
||||
lvmcache_label_scan(fmt->cmd, 1);
|
||||
/* Perform full scan (just the first time) and try again */
|
||||
if (!memlock() && !full_scan_done()) {
|
||||
lvmcache_label_scan(fmt->cmd, 2);
|
||||
|
||||
if (info->vginfo && info->vginfo->vgname &&
|
||||
*info->vginfo->vgname &&
|
||||
|
||||
@@ -31,7 +31,7 @@ typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
|
||||
struct hash_table * pv_hash);
|
||||
|
||||
#define _read_int32(root, path, result) \
|
||||
get_config_uint32(root, path, result)
|
||||
get_config_uint32(root, path, (uint32_t *) result)
|
||||
|
||||
#define _read_uint32(root, path, result) \
|
||||
get_config_uint32(root, path, result)
|
||||
|
||||
@@ -117,12 +117,17 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
struct labeller_i *li;
|
||||
struct labeller *r = NULL;
|
||||
struct label_header *lh;
|
||||
struct lvmcache_info *info;
|
||||
uint64_t sector;
|
||||
int found = 0;
|
||||
char readbuf[LABEL_SCAN_SIZE];
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -182,10 +187,13 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
log_very_verbose("%s: No label detected", dev_name(dev));
|
||||
|
||||
out:
|
||||
if (!found) {
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
log_very_verbose("%s: No label detected", dev_name(dev));
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
@@ -279,7 +287,7 @@ int label_read(struct device *dev, struct label **result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((r = l->ops->read(l, dev, buf, result)) && result && *result)
|
||||
if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
|
||||
(*result)->sector = sector;
|
||||
|
||||
return r;
|
||||
@@ -309,7 +317,7 @@ int label_write(struct device *dev, struct label *label)
|
||||
lh->sector_xl = xlate64(label->sector);
|
||||
lh->offset_xl = xlate32(sizeof(*lh));
|
||||
|
||||
if (!label->labeller->ops->write(label, buf)) {
|
||||
if (!(label->labeller->ops->write)(label, buf)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -139,8 +139,7 @@ static int _send_request(char *inbuf, int inlen, char **retbuf)
|
||||
|
||||
/* Read the returned values */
|
||||
off = 1; /* we've already read the first byte */
|
||||
|
||||
while (off < outheader->arglen && len > 0) {
|
||||
while (off <= outheader->arglen && len > 0) {
|
||||
len = read(_clvmd_sock, outheader->args + off,
|
||||
buflen - off - offsetof(struct clvm_header, args));
|
||||
if (len > 0)
|
||||
@@ -148,10 +147,16 @@ static int _send_request(char *inbuf, int inlen, char **retbuf)
|
||||
}
|
||||
|
||||
/* Was it an error ? */
|
||||
if (outheader->status < 0) {
|
||||
errno = -outheader->status;
|
||||
log_error("cluster send request failed: %s", strerror(errno));
|
||||
return 0;
|
||||
if (outheader->status != 0) {
|
||||
errno = outheader->status;
|
||||
|
||||
/* Only return an error here if there are no node-specific
|
||||
errors present in the message that might have more detail */
|
||||
if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
|
||||
log_error("cluster request failed: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -329,7 +334,7 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
* VG locks are just that: locks, and have no side effects
|
||||
* so we only need to do them on the local node because all
|
||||
* locks are cluster-wide.
|
||||
* Also, if the lock is exclusive it makes no sense to try to
|
||||
* Also, if the lock is exclusive it makes no sense to try to
|
||||
* acquire it on all nodes, so just do that on the local node too.
|
||||
*/
|
||||
if (cmd == CLVMD_CMD_LOCK_VG ||
|
||||
@@ -342,10 +347,11 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
|
||||
/* If any nodes were down then display them and return an error */
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status == -EHOSTDOWN) {
|
||||
if (response[i].status == EHOSTDOWN) {
|
||||
log_error("clvmd not running on node %s",
|
||||
response[i].node);
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
} else if (response[i].status) {
|
||||
log_error("Error locking on node %s: %s",
|
||||
response[i].node,
|
||||
@@ -353,6 +359,7 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
response[i].response :
|
||||
strerror(response[i].status));
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,7 +446,7 @@ int init_cluster_locking(struct locking_type *locking, struct config_tree *cft)
|
||||
locking->lock_resource = _lock_resource;
|
||||
locking->fin_locking = _locking_end;
|
||||
locking->reset_locking = _reset_locking;
|
||||
locking->flags = LCK_PRE_MEMLOCK;
|
||||
locking->flags = LCK_PRE_MEMLOCK | LCK_CLUSTERED;
|
||||
|
||||
_clvmd_sock = _open_local_sock();
|
||||
if (_clvmd_sock == -1)
|
||||
@@ -456,6 +463,7 @@ int locking_init(int type, struct config_tree *cf, uint32_t *flags)
|
||||
|
||||
/* Ask LVM to lock memory before calling us */
|
||||
*flags |= LCK_PRE_MEMLOCK;
|
||||
*flags |= LCK_CLUSTERED;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ static char _lock_dir[NAME_LEN];
|
||||
|
||||
static sig_t _oldhandler;
|
||||
static sigset_t _fullsigset, _intsigset;
|
||||
static int _handler_installed;
|
||||
static volatile sig_atomic_t _handler_installed;
|
||||
|
||||
static int _release_lock(const char *file, int unlock)
|
||||
{
|
||||
@@ -95,38 +95,40 @@ static void _reset_file_locking(void)
|
||||
static void _remove_ctrl_c_handler()
|
||||
{
|
||||
siginterrupt(SIGINT, 0);
|
||||
if (!_handler_installed || _oldhandler == SIG_ERR)
|
||||
if (!_handler_installed)
|
||||
return;
|
||||
|
||||
_handler_installed = 0;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &_fullsigset, NULL);
|
||||
if (signal(SIGINT, _oldhandler) == SIG_ERR)
|
||||
log_sys_error("signal", "_remove_ctrl_c_handler");
|
||||
|
||||
_handler_installed = 0;
|
||||
}
|
||||
|
||||
static void _trap_ctrl_c(int sig)
|
||||
{
|
||||
_remove_ctrl_c_handler();
|
||||
log_error("CTRL-c detected: giving up waiting for lock");
|
||||
return;
|
||||
}
|
||||
|
||||
static void _install_ctrl_c_handler()
|
||||
{
|
||||
if ((_oldhandler = signal(SIGINT, _trap_ctrl_c)) == SIG_ERR)
|
||||
_handler_installed = 1;
|
||||
|
||||
if ((_oldhandler = signal(SIGINT, _trap_ctrl_c)) == SIG_ERR) {
|
||||
_handler_installed = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
sigprocmask(SIG_SETMASK, &_intsigset, NULL);
|
||||
siginterrupt(SIGINT, 1);
|
||||
|
||||
_handler_installed = 1;
|
||||
}
|
||||
|
||||
static int _lock_file(const char *file, int flags)
|
||||
{
|
||||
int operation;
|
||||
int r = 1;
|
||||
int old_errno;
|
||||
|
||||
struct lock_list *ll;
|
||||
struct stat buf1, buf2;
|
||||
@@ -176,10 +178,12 @@ static int _lock_file(const char *file, int flags)
|
||||
_install_ctrl_c_handler();
|
||||
|
||||
r = flock(ll->lf, operation);
|
||||
old_errno = errno;
|
||||
if (!(flags & LCK_NONBLOCK))
|
||||
_remove_ctrl_c_handler();
|
||||
|
||||
if (r) {
|
||||
errno = old_errno;
|
||||
log_sys_error("flock", ll->res);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -124,6 +124,8 @@ static inline void _update_vg_lock_count(int flags)
|
||||
*/
|
||||
int init_locking(int type, struct config_tree *cft)
|
||||
{
|
||||
init_lockingfailed(0);
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
init_no_locking(&_locking, cft);
|
||||
@@ -165,6 +167,7 @@ int init_locking(int type, struct config_tree *cft)
|
||||
log_verbose("Locking disabled - only read operations permitted.");
|
||||
|
||||
init_no_locking(&_locking, cft);
|
||||
init_lockingfailed(1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -321,3 +324,9 @@ int vg_write_lock_held(void)
|
||||
{
|
||||
return _vg_write_lock_held;
|
||||
}
|
||||
|
||||
int locking_is_clustered(void)
|
||||
{
|
||||
return (_locking.flags & LCK_CLUSTERED) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ int init_locking(int type, struct config_tree *cf);
|
||||
void fin_locking(void);
|
||||
void reset_locking(void);
|
||||
int vg_write_lock_held(void);
|
||||
int locking_is_clustered(void);
|
||||
|
||||
/*
|
||||
* LCK_VG:
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef void (*fin_lock_fn) (void);
|
||||
typedef void (*reset_lock_fn) (void);
|
||||
|
||||
#define LCK_PRE_MEMLOCK 0x00000001 /* Is memlock() needed before calls? */
|
||||
#define LCK_CLUSTERED 0x00000002
|
||||
|
||||
struct locking_type {
|
||||
uint32_t flags;
|
||||
|
||||
@@ -30,6 +30,7 @@ static int _test = 0;
|
||||
static int _partial = 0;
|
||||
static int _md_filtering = 0;
|
||||
static int _pvmove = 0;
|
||||
static int _full_scan_done = 0; /* Restrict to one full scan during each cmd */
|
||||
static int _debug_level = 0;
|
||||
static int _syslog = 0;
|
||||
static int _log_to_file = 0;
|
||||
@@ -39,6 +40,7 @@ static int _indent = 1;
|
||||
static int _log_cmd_name = 0;
|
||||
static int _log_suppress = 0;
|
||||
static int _ignorelockingfailure = 0;
|
||||
static int _lockingfailed = 0;
|
||||
static int _security_level = SECURITY_LEVEL;
|
||||
static char _cmd_name[30] = "";
|
||||
static char _msg_prefix[30] = " ";
|
||||
@@ -149,11 +151,21 @@ void init_pvmove(int level)
|
||||
_pvmove = level;
|
||||
}
|
||||
|
||||
void init_full_scan_done(int level)
|
||||
{
|
||||
_full_scan_done = level;
|
||||
}
|
||||
|
||||
void init_ignorelockingfailure(int level)
|
||||
{
|
||||
_ignorelockingfailure = level;
|
||||
}
|
||||
|
||||
void init_lockingfailed(int level)
|
||||
{
|
||||
_lockingfailed = level;
|
||||
}
|
||||
|
||||
void init_security_level(int level)
|
||||
{
|
||||
_security_level = level;
|
||||
@@ -203,6 +215,16 @@ int pvmove_mode()
|
||||
return _pvmove;
|
||||
}
|
||||
|
||||
int full_scan_done()
|
||||
{
|
||||
return _full_scan_done;
|
||||
}
|
||||
|
||||
int lockingfailed()
|
||||
{
|
||||
return _lockingfailed;
|
||||
}
|
||||
|
||||
int ignorelockingfailure()
|
||||
{
|
||||
return _ignorelockingfailure;
|
||||
|
||||
@@ -65,11 +65,13 @@ void init_test(int level);
|
||||
void init_partial(int level);
|
||||
void init_md_filtering(int level);
|
||||
void init_pvmove(int level);
|
||||
void init_full_scan_done(int level);
|
||||
void init_debug(int level);
|
||||
void init_cmd_name(int status);
|
||||
void init_msg_prefix(const char *prefix);
|
||||
void init_indent(int indent);
|
||||
void init_ignorelockingfailure(int level);
|
||||
void init_lockingfailed(int level);
|
||||
void init_security_level(int level);
|
||||
|
||||
void set_cmd_name(const char *cmd_name);
|
||||
@@ -78,8 +80,10 @@ int test_mode(void);
|
||||
int partial_mode(void);
|
||||
int md_filtering(void);
|
||||
int pvmove_mode(void);
|
||||
int full_scan_done(void);
|
||||
int debug_level(void);
|
||||
int ignorelockingfailure(void);
|
||||
int lockingfailed(void);
|
||||
int security_level(void);
|
||||
|
||||
/* Suppress messages to stdout/stderr */
|
||||
|
||||
@@ -267,10 +267,13 @@ struct physical_volume *pv_create(const struct format_type *fmt,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!id)
|
||||
id_create(&pv->id);
|
||||
else
|
||||
if (id)
|
||||
memcpy(&pv->id, id, sizeof(*id));
|
||||
else if (!id_create(&pv->id)) {
|
||||
log_error("Failed to create random uuid for %s.",
|
||||
dev_name(dev));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pv->dev = dev;
|
||||
|
||||
@@ -651,7 +654,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
lvmcache_label_scan(cmd, 1);
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
stack;
|
||||
return NULL;
|
||||
@@ -684,10 +687,46 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
}
|
||||
}
|
||||
|
||||
/* Failed to find VG */
|
||||
/* Failed to find VG where we expected it - full scan and retry */
|
||||
if (!correct_vg) {
|
||||
stack;
|
||||
return NULL;
|
||||
inconsistent = 0;
|
||||
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create format instance with appropriate metadata area */
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Ensure contents of all metadata areas match - else recover */
|
||||
list_iterate(mdah, &fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
if (!(vg = mda->ops->vg_read(fid, vgname, mda))) {
|
||||
inconsistent = 1;
|
||||
continue;
|
||||
}
|
||||
if (!correct_vg) {
|
||||
correct_vg = vg;
|
||||
continue;
|
||||
}
|
||||
/* FIXME Also ensure contents same - checksums same? */
|
||||
if (correct_vg->seqno != vg->seqno) {
|
||||
inconsistent = 1;
|
||||
if (vg->seqno > correct_vg->seqno)
|
||||
correct_vg = vg;
|
||||
}
|
||||
}
|
||||
|
||||
/* Give up looking */
|
||||
if (!correct_vg) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lvmcache_update_vg(correct_vg);
|
||||
@@ -711,6 +750,11 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
log_error("Automatic metadata correction failed");
|
||||
return NULL;
|
||||
}
|
||||
if (!vg_commit(correct_vg)) {
|
||||
log_error("Automatic metadata correction commit "
|
||||
"failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
|
||||
@@ -760,7 +804,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
|
||||
* allowed to do a full scan here any more. */
|
||||
|
||||
// The slow way - full scan required to cope with vgrename
|
||||
if (!(vgnames = get_vgs(cmd, 1))) {
|
||||
if (!(vgnames = get_vgs(cmd, 2))) {
|
||||
log_error("vg_read_by_vgid: get_vgs failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -255,6 +255,7 @@ struct snapshot {
|
||||
|
||||
int persistent; /* boolean */
|
||||
uint32_t chunk_size; /* in 512 byte sectors */
|
||||
uint32_t le_count;
|
||||
|
||||
struct logical_volume *origin;
|
||||
struct logical_volume *cow;
|
||||
@@ -496,9 +497,9 @@ struct snapshot *find_cow(const struct logical_volume *lv);
|
||||
struct snapshot *find_origin(const struct logical_volume *lv);
|
||||
struct list *find_snapshots(const struct logical_volume *lv);
|
||||
|
||||
int vg_add_snapshot(struct logical_volume *origin,
|
||||
struct logical_volume *cow,
|
||||
int persistent, struct id *id, uint32_t chunk_size);
|
||||
int vg_add_snapshot(struct logical_volume *origin, struct logical_volume *cow,
|
||||
int persistent, struct id *id, uint32_t extent_count,
|
||||
uint32_t chunk_size);
|
||||
|
||||
int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow);
|
||||
|
||||
|
||||
@@ -104,9 +104,9 @@ struct list *find_snapshots(const struct logical_volume *lv)
|
||||
return snaplist;
|
||||
}
|
||||
|
||||
int vg_add_snapshot(struct logical_volume *origin,
|
||||
struct logical_volume *cow,
|
||||
int persistent, struct id *id, uint32_t chunk_size)
|
||||
int vg_add_snapshot(struct logical_volume *origin, struct logical_volume *cow,
|
||||
int persistent, struct id *id, uint32_t extent_count,
|
||||
uint32_t chunk_size)
|
||||
{
|
||||
struct snapshot *s;
|
||||
struct snapshot_list *sl;
|
||||
@@ -127,13 +127,15 @@ int vg_add_snapshot(struct logical_volume *origin,
|
||||
|
||||
s->persistent = persistent;
|
||||
s->chunk_size = chunk_size;
|
||||
s->le_count = extent_count;
|
||||
s->origin = origin;
|
||||
s->cow = cow;
|
||||
|
||||
if (id)
|
||||
s->id = *id;
|
||||
else if (!id_create(&s->id)) {
|
||||
log_error("Snapshot UUID creation failed");
|
||||
log_error("Random UUID creation failed for snapshot %s.",
|
||||
cow->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,11 @@ int lvm_rename(const char *old, const char *new)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
link(old, new);
|
||||
if (link(old, new)) {
|
||||
log_error("%s: rename to %s failed: %s", old, new,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stat(old, &buf)) {
|
||||
log_sys_error("stat", old);
|
||||
|
||||
@@ -48,13 +48,14 @@ void *malloc_aux(size_t s, const char *file, int line)
|
||||
size_t tsize = s + sizeof(*nb) + sizeof(unsigned long);
|
||||
|
||||
if (s > 50000000) {
|
||||
log_error("Huge memory allocation (size %" PRIuPTR
|
||||
log_error("Huge memory allocation (size %" PRIsize_t
|
||||
") rejected - metadata corruption?", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(nb = malloc(tsize))) {
|
||||
log_error("couldn't allocate any memory, size = %" PRIuPTR, s);
|
||||
log_error("couldn't allocate any memory, size = %" PRIsize_t,
|
||||
s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -190,7 +191,7 @@ int dump_memory(void)
|
||||
str[sizeof(str) - 1] = '\0';
|
||||
|
||||
print_log(_LOG_INFO, mb->file, mb->line,
|
||||
"block %d at %p, size %" PRIdPTR "\t [%s]",
|
||||
"block %d at %p, size %" PRIsize_t "\t [%s]",
|
||||
mb->id, mb->magic, mb->length, str);
|
||||
tot += mb->length;
|
||||
}
|
||||
@@ -220,7 +221,7 @@ void bounds_check(void)
|
||||
void *malloc_aux(size_t s, const char *file, int line)
|
||||
{
|
||||
if (s > 50000000) {
|
||||
log_error("Huge memory allocation (size %" PRIuPTR
|
||||
log_error("Huge memory allocation (size %" PRIsize_t
|
||||
") rejected - metadata corruption?", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@
|
||||
((x) & 0xff000000U) >> 24 | \
|
||||
((x) & 0x0000ff00U) << 8 | \
|
||||
((x) & 0x00ff0000U) >> 8)
|
||||
# define bswap_64(x) (((x) & 0x00000000000000ffU) << 56 | \
|
||||
((x) & 0xff00000000000000U) >> 56 | \
|
||||
((x) & 0x000000000000ff00U) << 40 | \
|
||||
((x) & 0x00ff000000000000U) >> 40 | \
|
||||
((x) & 0x0000000000ff0000U) << 24 | \
|
||||
((x) & 0x0000ff0000000000U) >> 24 | \
|
||||
((x) & 0x00000000ff000000U) << 8 | \
|
||||
((x) & 0x000000ff00000000U) >> 8)
|
||||
# define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \
|
||||
((x) & 0xff00000000000000ULL) >> 56 | \
|
||||
((x) & 0x000000000000ff00ULL) << 40 | \
|
||||
((x) & 0x00ff000000000000ULL) >> 40 | \
|
||||
((x) & 0x0000000000ff0000ULL) << 24 | \
|
||||
((x) & 0x0000ff0000000000ULL) >> 24 | \
|
||||
((x) & 0x00000000ff000000ULL) << 8 | \
|
||||
((x) & 0x000000ff00000000ULL) >> 8)
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
|
||||
@@ -295,7 +295,7 @@ static int _lvkmaj_disp(struct report_handle *rh, struct field *field,
|
||||
struct lvinfo info;
|
||||
uint64_t minusone = UINT64_C(-1);
|
||||
|
||||
if (lv_info(lv, &info) && info.exists)
|
||||
if (lv_info(lv, &info, 0) && info.exists)
|
||||
return _int_disp(rh, field, &info.major);
|
||||
else
|
||||
return _int_disp(rh, field, &minusone);
|
||||
@@ -310,7 +310,7 @@ static int _lvkmin_disp(struct report_handle *rh, struct field *field,
|
||||
struct lvinfo info;
|
||||
uint64_t minusone = UINT64_C(-1);
|
||||
|
||||
if (lv_info(lv, &info) && info.exists)
|
||||
if (lv_info(lv, &info, 0) && info.exists)
|
||||
return _int_disp(rh, field, &info.minor);
|
||||
else
|
||||
return _int_disp(rh, field, &minusone);
|
||||
@@ -362,7 +362,7 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
else
|
||||
repstr[3] = '-';
|
||||
|
||||
if (lv_info(lv, &info) && info.exists) {
|
||||
if (lv_info(lv, &info, 1) && info.exists) {
|
||||
if (info.suspended)
|
||||
repstr[4] = 's'; /* Suspended */
|
||||
else
|
||||
@@ -573,7 +573,7 @@ static int _vgsize_disp(struct report_handle *rh, struct field *field,
|
||||
const struct volume_group *vg = (const struct volume_group *) data;
|
||||
uint64_t size;
|
||||
|
||||
size = vg->extent_count * vg->extent_size;
|
||||
size = (uint64_t) vg->extent_count * vg->extent_size;
|
||||
|
||||
return _size64_disp(rh, field, &size);
|
||||
}
|
||||
@@ -584,7 +584,7 @@ static int _segstart_disp(struct report_handle *rh, struct field *field,
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
uint64_t start;
|
||||
|
||||
start = seg->le * seg->lv->vg->extent_size;
|
||||
start = (uint64_t) seg->le * seg->lv->vg->extent_size;
|
||||
|
||||
return _size64_disp(rh, field, &start);
|
||||
}
|
||||
@@ -595,7 +595,7 @@ static int _segsize_disp(struct report_handle *rh, struct field *field,
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
uint64_t size;
|
||||
|
||||
size = seg->len * seg->lv->vg->extent_size;
|
||||
size = (uint64_t) seg->len * seg->lv->vg->extent_size;
|
||||
|
||||
return _size64_disp(rh, field, &size);
|
||||
}
|
||||
@@ -610,7 +610,7 @@ static int _pvused_disp(struct report_handle *rh, struct field *field,
|
||||
if (!pv->pe_count)
|
||||
used = 0LL;
|
||||
else
|
||||
used = pv->pe_alloc_count * pv->pe_size;
|
||||
used = (uint64_t) pv->pe_alloc_count * pv->pe_size;
|
||||
|
||||
return _size64_disp(rh, field, &used);
|
||||
}
|
||||
@@ -625,7 +625,7 @@ static int _pvfree_disp(struct report_handle *rh, struct field *field,
|
||||
if (!pv->pe_count)
|
||||
freespace = pv->size;
|
||||
else
|
||||
freespace = (pv->pe_count - pv->pe_alloc_count) * pv->pe_size;
|
||||
freespace = (uint64_t) (pv->pe_count - pv->pe_alloc_count) * pv->pe_size;
|
||||
|
||||
return _size64_disp(rh, field, &freespace);
|
||||
}
|
||||
@@ -640,7 +640,7 @@ static int _pvsize_disp(struct report_handle *rh, struct field *field,
|
||||
if (!pv->pe_count)
|
||||
size = pv->size;
|
||||
else
|
||||
size = pv->pe_count * pv->pe_size;
|
||||
size = (uint64_t) pv->pe_count * pv->pe_size;
|
||||
|
||||
return _size64_disp(rh, field, &size);
|
||||
}
|
||||
@@ -663,7 +663,7 @@ static int _vgfree_disp(struct report_handle *rh, struct field *field,
|
||||
const struct volume_group *vg = (const struct volume_group *) data;
|
||||
uint64_t freespace;
|
||||
|
||||
freespace = vg->free_count * vg->extent_size;
|
||||
freespace = (uint64_t) vg->free_count * vg->extent_size;
|
||||
|
||||
return _size64_disp(rh, field, &freespace);
|
||||
}
|
||||
@@ -774,7 +774,7 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
|
||||
}
|
||||
|
||||
if (!(snap = find_cow(lv)) ||
|
||||
(lv_info(snap->cow, &info) && !info.exists)) {
|
||||
(lv_info(snap->cow, &info, 0) && !info.exists)) {
|
||||
field->report_string = "";
|
||||
*sortval = UINT64_C(0);
|
||||
field->sort_value = sortval;
|
||||
|
||||
@@ -70,7 +70,8 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_add_snapshot(org, cow, 1, &seg->lv->lvid.id[1], chunk_size)) {
|
||||
if (!vg_add_snapshot(org, cow, 1, &seg->lv->lvid.id[1], seg->len,
|
||||
chunk_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,7 @@ static unsigned char _inverse_c[256];
|
||||
int lvid_create(union lvid *lvid, struct id *vgid)
|
||||
{
|
||||
memcpy(lvid->id, vgid, sizeof(*lvid->id));
|
||||
id_create(&lvid->id[1]);
|
||||
|
||||
return 1;
|
||||
return id_create(&lvid->id[1]);
|
||||
}
|
||||
|
||||
void uuid_from_num(char *uuid, uint32_t num)
|
||||
@@ -83,16 +81,18 @@ int id_create(struct id *id)
|
||||
|
||||
memset(id->uuid, 0, len);
|
||||
if ((randomfile = open("/dev/urandom", O_RDONLY)) < 0) {
|
||||
log_sys_error("open", "id_create");
|
||||
log_sys_error("open", "id_create: /dev/urandom");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (read(randomfile, id->uuid, len) != len) {
|
||||
log_sys_error("read", "id_create");
|
||||
close(randomfile);
|
||||
log_sys_error("read", "id_create: /dev/urandom");
|
||||
if (close(randomfile))
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
close(randomfile);
|
||||
if (close(randomfile))
|
||||
stack;
|
||||
|
||||
/*
|
||||
* Skip out the last 2 chars in randomized creation for LVM1
|
||||
|
||||
@@ -20,6 +20,7 @@ dm_task_set_minor
|
||||
dm_task_set_sector
|
||||
dm_task_set_message
|
||||
dm_task_add_target
|
||||
dm_task_no_open_count
|
||||
dm_get_next_target
|
||||
dm_task_run
|
||||
dm_set_dev_dir
|
||||
|
||||
@@ -22,7 +22,12 @@ SOURCES = libdm-common.c libdm-file.c $(interface)/libdm-iface.c
|
||||
INCLUDES = -I$(interface)
|
||||
|
||||
LIB_STATIC = $(interface)/libdevmapper.a
|
||||
LIB_SHARED = $(interface)/libdevmapper.so
|
||||
|
||||
ifeq ("@LIB_SUFFIX@","dylib")
|
||||
LIB_SHARED = $(interface)/libdevmapper.dylib
|
||||
else
|
||||
LIB_SHARED = $(interface)/libdevmapper.so
|
||||
endif
|
||||
|
||||
CFLAGS += -DDEVICE_UID=@DEVICE_UID@ -DDEVICE_GID=@DEVICE_GID@ \
|
||||
-DDEVICE_MODE=@DEVICE_MODE@
|
||||
@@ -41,7 +46,8 @@ endif
|
||||
install: $(INSTALL_TYPE)
|
||||
|
||||
install_dynamic: install_@interface@
|
||||
$(LN_S) -f libdevmapper.so.$(LIB_VERSION) $(libdir)/libdevmapper.so
|
||||
$(LN_S) -f libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION) \
|
||||
$(libdir)/libdevmapper.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper.h \
|
||||
$(includedir)/libdevmapper.h
|
||||
|
||||
@@ -50,13 +56,13 @@ install_static: install_@interface@_static
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper.h \
|
||||
$(includedir)/libdevmapper.h
|
||||
|
||||
install_fs: fs/libdevmapper.so
|
||||
install_fs: fs/libdevmapper.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper.so.$(LIB_VERSION)
|
||||
$(libdir)/libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION)
|
||||
|
||||
install_ioctl: ioctl/libdevmapper.so
|
||||
install_ioctl: ioctl/libdevmapper.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper.so.$(LIB_VERSION)
|
||||
$(libdir)/libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION)
|
||||
|
||||
install_ioctl_static: ioctl/libdevmapper.a
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
|
||||
@@ -30,13 +30,14 @@
|
||||
#ifdef linux
|
||||
# include "kdev_t.h"
|
||||
# include <linux/limits.h>
|
||||
# include <linux/dm-ioctl.h>
|
||||
#else
|
||||
# define MAJOR(x) major((x))
|
||||
# define MINOR(x) minor((x))
|
||||
# define MKDEV(x,y) makedev((x),(y))
|
||||
#endif
|
||||
|
||||
#include <linux/dm-ioctl.h>
|
||||
|
||||
/*
|
||||
* Ensure build compatibility.
|
||||
* The hard-coded versions here are the highest present
|
||||
@@ -134,8 +135,7 @@ static int _get_proc_number(const char *file, const char *name,
|
||||
fclose(fl);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
do {
|
||||
} else do {
|
||||
c = fgetc(fl);
|
||||
} while (c != EOF && c != '\n');
|
||||
}
|
||||
@@ -229,6 +229,7 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
|
||||
|
||||
static int _open_control(void)
|
||||
{
|
||||
#ifdef DM_IOCTLS
|
||||
char control[PATH_MAX];
|
||||
uint32_t major = 0, minor;
|
||||
|
||||
@@ -254,6 +255,9 @@ static int _open_control(void)
|
||||
error:
|
||||
log_error("Failure to communicate with kernel device-mapper driver.");
|
||||
return 0;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void dm_task_destroy(struct dm_task *dmt)
|
||||
@@ -609,7 +613,9 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
||||
if (dmt->type == DM_DEVICE_LIST) {
|
||||
if (!_dm_names_v1(dmi))
|
||||
goto bad;
|
||||
} else if (ioctl(_control_fd, command, dmi) < 0) {
|
||||
}
|
||||
#ifdef DM_IOCTLS
|
||||
else if (ioctl(_control_fd, command, dmi) < 0) {
|
||||
if (_log_suppress)
|
||||
log_verbose("device-mapper ioctl cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
@@ -618,6 +624,8 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
||||
_IOC_NR(command), strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
#else /* Userspace alternative for testing */
|
||||
#endif
|
||||
|
||||
if (dmi->flags & DM_BUFFER_FULL_FLAG)
|
||||
/* FIXME Increase buffer size and retry operation (if query) */
|
||||
@@ -930,6 +938,13 @@ int dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_no_open_count(struct dm_task *dmt)
|
||||
{
|
||||
dmt->no_open_count = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr)
|
||||
{
|
||||
dmt->event_nr = event_nr;
|
||||
@@ -1299,25 +1314,34 @@ int dm_task_run(struct dm_task *dmt)
|
||||
dmi->flags |= DM_STATUS_TABLE_FLAG;
|
||||
|
||||
dmi->flags |= DM_EXISTS_FLAG; /* FIXME */
|
||||
log_debug("dm %s %s %s %s%.0llu %s", _cmd_data_v4[dmt->type].name,
|
||||
|
||||
if (dmt->no_open_count)
|
||||
dmi->flags |= DM_SKIP_BDGET_FLAG;
|
||||
|
||||
log_debug("dm %s %s %s %s%c %.0llu %s", _cmd_data_v4[dmt->type].name,
|
||||
dmi->name, dmi->uuid, dmt->newname ? dmt->newname : "",
|
||||
dmt->no_open_count ? 'N' : 'O',
|
||||
dmt->sector, dmt->message ? dmt->message : "");
|
||||
#ifdef DM_IOCTLS
|
||||
if (ioctl(_control_fd, command, dmi) < 0) {
|
||||
if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
|
||||
(dmt->type == DM_DEVICE_MKNODES))) {
|
||||
(dmt->type == DM_DEVICE_MKNODES)))
|
||||
dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */
|
||||
goto ignore_error;
|
||||
else {
|
||||
if (_log_suppress)
|
||||
log_verbose("device-mapper ioctl "
|
||||
"cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
else
|
||||
log_error("device-mapper ioctl "
|
||||
"cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
if (_log_suppress)
|
||||
log_verbose("device-mapper ioctl cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
else
|
||||
log_error("device-mapper ioctl cmd %d failed: %s",
|
||||
_IOC_NR(command), strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
#else /* Userspace alternative for testing */
|
||||
#endif
|
||||
|
||||
ignore_error:
|
||||
switch (dmt->type) {
|
||||
case DM_DEVICE_CREATE:
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
|
||||
|
||||
@@ -51,6 +51,7 @@ struct dm_task {
|
||||
char *newname;
|
||||
char *message;
|
||||
uint64_t sector;
|
||||
int no_open_count;
|
||||
|
||||
char *uuid;
|
||||
};
|
||||
|
||||
@@ -134,6 +134,7 @@ int dm_task_set_major(struct dm_task *dmt, int major);
|
||||
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
|
||||
int dm_task_set_message(struct dm_task *dmt, const char *message);
|
||||
int dm_task_set_sector(struct dm_task *dmt, uint64_t sector);
|
||||
int dm_task_no_open_count(struct dm_task *dmt);
|
||||
|
||||
/*
|
||||
* Use these to prepare for a create or reload.
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <linux/dm-ioctl.h>
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
#include <sys/file.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#ifdef linux
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
static int _create_dir_recursive(const char *dir)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,10 @@ dmsetup \- low level logical volume management
|
||||
.br
|
||||
.B dmsetup ls
|
||||
.br
|
||||
.B dmsetup info
|
||||
.B dmsetup info
|
||||
.I [device_name]
|
||||
.br
|
||||
.B dmsetup info -c|-C|--columns [--noheadings] [-o name]
|
||||
.I [device_name]
|
||||
.br
|
||||
.B dmsetup deps
|
||||
@@ -53,6 +56,13 @@ dmsetup \- low level logical volume management
|
||||
.B dmsetup targets
|
||||
.br
|
||||
.B dmsetup version
|
||||
.br
|
||||
|
||||
.B devmap_name
|
||||
.I major minor
|
||||
.br
|
||||
.B devmap_name
|
||||
.I major:minor
|
||||
.ad b
|
||||
.SH DESCRIPTION
|
||||
dmsetup manages logical devices that use the device-mapper driver.
|
||||
@@ -61,16 +71,38 @@ each sector (512 bytes) in the logical device.
|
||||
|
||||
The first argument to dmsetup is a command.
|
||||
The second argument is the logical device name or uuid.
|
||||
|
||||
Invoking the command as \fBdevmap_name\fP is equivalent to
|
||||
.br
|
||||
\fBdmsetup info -c --noheadings -j \fImajor\fB -m \fIminor\fP.
|
||||
.SH OPTIONS
|
||||
.IP \fB-c|-C|--columns
|
||||
.br
|
||||
Display output in columns rather than as Field: Value lines.
|
||||
.IP \fB-j|--major\ \fImajor
|
||||
.br
|
||||
Specify the major number to use on creation.
|
||||
.IP \fB-j|--minor\ \fIminor
|
||||
Specify the major number.
|
||||
.IP \fB-m|--minor\ \fIminor
|
||||
.br
|
||||
Specify the minor number to use on creation.
|
||||
Specify the minor number.
|
||||
.IP \fB-n|--noheadings
|
||||
.br
|
||||
Suppress the headings line when using columnar output.
|
||||
.IP \fB--noopencount
|
||||
.br
|
||||
Tell the kernel not to supply the open reference count for the device.
|
||||
.IP \fB--notable
|
||||
.br
|
||||
When creating a device, don't load any table.
|
||||
.IP \fB-o|--options
|
||||
.br
|
||||
Specify which fields to display. Only \fB-o\ name\fP is supported.
|
||||
.IP \fB-r|--readonly
|
||||
.br
|
||||
Set the table being loaded read-only.
|
||||
.IP \fB-u|--uuid
|
||||
.br
|
||||
Specify the uuid.
|
||||
.IP \fB-v|--verbose [-v|--verbose]
|
||||
.br
|
||||
Produce additional output.
|
||||
|
||||
@@ -91,10 +91,10 @@ The approximate amount of space to be set aside for each metadata area.
|
||||
.BR \-\-metadatacopies " copies"
|
||||
The number of metadata areas to set aside on each PV. Currently
|
||||
this can be 0, 1 or 2.
|
||||
If set to 2 (the default), two copies of the volume group metadata
|
||||
If set to 2, two copies of the volume group metadata
|
||||
are held on the PV, one at the front of the PV and one at the end.
|
||||
If set to 1, one copy is kept at the front of the PV (starting in the
|
||||
5th sector).
|
||||
If set to 1 (the default), one copy is kept at the front of the PV
|
||||
(starting in the 5th sector).
|
||||
If set to 0, no copies are kept on this PV - you might wish to use this
|
||||
with VGs containing large numbers of PVs. But if you do this and
|
||||
then later use \fBvgsplit\fP you must ensure that each VG is still going
|
||||
|
||||
@@ -33,29 +33,44 @@ previously configured for LVM with
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
.BR \-A ", " \-\-autobackup " {" y | n }
|
||||
Controls automatic backup of VG metadata after the change (see
|
||||
.BR vgcfgbackup (8)).
|
||||
Default is yes.
|
||||
.TP
|
||||
.BR \-l ", " \-\-maxlogicalvolumes " " \fIMaxLogicalVolumes\fR
|
||||
Sets the maximum possible logical volume count.
|
||||
More logical volumes can't be created in this volume group.
|
||||
Absolute maximum is 256.
|
||||
Sets the maximum number of logical volumes allowed in this
|
||||
volume group.
|
||||
The setting can be changed with \fBvgchange\fP.
|
||||
For volume groups with metadata in lvm1 format, the limit
|
||||
and default value is 255.
|
||||
If the metadata uses lvm2 format, the default value is 0
|
||||
which removes this restriction: there is then no limit.
|
||||
.TP
|
||||
.BR \-p ", " \-\-maxphysicalvolumes " " \fIMaxPhysicalVolumes\fR
|
||||
Sets the maximum possible physical volume count.
|
||||
More physical volumes can't be included in this volume group.
|
||||
Absolute maximum is 256.
|
||||
Sets the maximum number of physical volumes that can belong
|
||||
to this volume group.
|
||||
The setting can be changed with \fBvgchange\fP.
|
||||
For volume groups with metadata in lvm1 format, the limit
|
||||
and default value is 255.
|
||||
If the metadata uses lvm2 format, the default value is 0
|
||||
which removes this restriction: there is then no limit.
|
||||
If you have a large number of physical volumes in
|
||||
a volume group with metadata in lvm2 format,
|
||||
for tool performance reasons, you should consider
|
||||
some use of \fB--metadatacopies 0\fP
|
||||
as described in \fBpvcreate(8)\fP.
|
||||
.TP
|
||||
.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
|
||||
Sets the physical extent size on physical volumes of this volume group.
|
||||
A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
|
||||
is the default if no suffix is present. Values can be from 8 KB to 16 GB in
|
||||
powers of 2. The default of 4 MB causes maximum LV sizes of ~256GB because as
|
||||
many as ~64k extents are supported per LV. In case larger maximum LV sizes are
|
||||
needed (later), you need to set the PE size to a larger value as well. Later
|
||||
changes of the PE size in an existing VG are not supported.
|
||||
powers of 2. The default is 4 MB.
|
||||
Once this value has been set, it is difficult to change it without recreating
|
||||
the volume group which would involve backing up and restoring data on any
|
||||
logical volumes.
|
||||
If the volume group metadata uses lvm1 format, there is a limit of 65534
|
||||
extents in each logical volume, so the default of 4 MB leads to a maximum
|
||||
logical volume size of around 256GB.
|
||||
If the volume group metadata uses lvm2 format there is no such restriction,
|
||||
although having a large number of extents will slow down
|
||||
the tools but have no impact on I/O performance to the logical volume.
|
||||
The 2.4 kernel has a limitation of 2TB per block device.
|
||||
.SH EXAMPLES
|
||||
To create a volume group named
|
||||
.B test_vg
|
||||
@@ -67,11 +82,6 @@ with default physical extent size of 4MB:
|
||||
\ vgcreate test_vg /dev/sdk1 /dev/sdl1
|
||||
|
||||
.fi
|
||||
To limit kernel memory usage, there is a limit of 65536 physical extents
|
||||
(PE) per logical volume, so the PE size determines the maximum logical volume
|
||||
size. The default PE size of 4MB limits a single logical volume to 256GB (see
|
||||
the -s option to raise that limit).
|
||||
There is also (as of Linux 2.4) a kernel limitation of 2TB per block device.
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR pvdisplay (8),
|
||||
|
||||
1651
po/lvm2.po
1651
po/lvm2.po
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# chkconfig: 345 23 77
|
||||
# chkconfig: 345 24 76
|
||||
# description: Starts and stops clvmd
|
||||
#
|
||||
#
|
||||
@@ -9,19 +9,17 @@
|
||||
### END INIT INFO
|
||||
|
||||
. /etc/init.d/functions
|
||||
|
||||
LVDISPLAY="/usr/sbin/lvdisplay"
|
||||
VGCHANGE="/usr/sbin/vgchange"
|
||||
VGSCAN="/usr/sbin/vgscan"
|
||||
|
||||
[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
|
||||
|
||||
LOCK_FILE="/var/lock/subsys/clvmd"
|
||||
|
||||
#
|
||||
# FIXME -- the lvm2-cluster rpms put the lvm tools in a different location
|
||||
#
|
||||
lvdisplay=/usr/sbin/cluster/lvdisplay
|
||||
vgchange=/usr/sbin/cluster/vgchange
|
||||
|
||||
start()
|
||||
{
|
||||
modprobe dlm
|
||||
for rtrn in 0
|
||||
do
|
||||
if ! pidof clvmd > /dev/null
|
||||
@@ -40,12 +38,15 @@ start()
|
||||
fi
|
||||
fi
|
||||
|
||||
# refresh cache
|
||||
$VGSCAN > /dev/null 2>&1
|
||||
|
||||
if [ -n "$LVM_VGS" ]
|
||||
then
|
||||
for vg in $LVM_VGS
|
||||
do
|
||||
echo -n "Activating lvm $vg:"
|
||||
if $vgchange -ayl $vg > /dev/null 2>&1
|
||||
if $VGCHANGE -ayl $vg > /dev/null 2>&1
|
||||
then
|
||||
success
|
||||
echo
|
||||
@@ -57,7 +58,7 @@ start()
|
||||
done
|
||||
else
|
||||
echo -n "Activating lvms:"
|
||||
if $vgchange -ayl > /dev/null 2>&1
|
||||
if $VGCHANGE -ayl > /dev/null 2>&1
|
||||
then
|
||||
success
|
||||
echo
|
||||
@@ -81,7 +82,7 @@ stop()
|
||||
for vg in $LVM_VGS
|
||||
do
|
||||
echo -n "Deactivating lvm $vg:"
|
||||
if $vgchange -anl $vg > /dev/null 2>&1
|
||||
if $VGCHANGE -anl $vg > /dev/null 2>&1
|
||||
then
|
||||
success
|
||||
echo
|
||||
@@ -93,7 +94,7 @@ stop()
|
||||
done
|
||||
else
|
||||
echo -n "Deactivating lvms:"
|
||||
if $vgchange -anl > /dev/null 2>&1
|
||||
if $VGCHANGE -anl > /dev/null 2>&1
|
||||
then
|
||||
success
|
||||
echo
|
||||
@@ -124,7 +125,6 @@ stop()
|
||||
echo
|
||||
fi
|
||||
done
|
||||
modprobe -r dlm > /dev/null 2>&1
|
||||
|
||||
return $rtrn
|
||||
}
|
||||
@@ -153,7 +153,7 @@ case "$1" in
|
||||
|
||||
status)
|
||||
status clvmd
|
||||
vols=$( $lvdisplay -C --nohead 2> /dev/null | awk '($3 ~ /....a./) {print $1}' )
|
||||
vols=$( $LVDISPLAY -C --nohead 2> /dev/null | awk '($3 ~ /....a./) {print $1}' )
|
||||
echo active volumes: ${vols:-"(none)"}
|
||||
rtrn=0
|
||||
;;
|
||||
|
||||
@@ -90,14 +90,16 @@ ifeq ("@DEVMAPPER@", "yes")
|
||||
LVMLIBS += -ldevmapper
|
||||
endif
|
||||
|
||||
CFLAGS += -DLVM_SHARED_PATH=\"$(exec_prefix)/sbin/lvm\"
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
lvm: $(OBJECTS) lvm.o $(top_srcdir)/lib/liblvm.a
|
||||
$(CC) -o $@ $(OBJECTS) lvm.o $(LDFLAGS) $(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
lvm.static: $(OBJECTS) lvm.o $(top_srcdir)/lib/liblvm.a
|
||||
$(CC) -o $@ $(OBJECTS) lvm.o -static $(LDFLAGS) $(LVMLIBS) $(LIBS) \
|
||||
-rdynamic
|
||||
lvm.static: $(OBJECTS) lvm-static.o $(top_srcdir)/lib/liblvm.a
|
||||
$(CC) -o $@ $(OBJECTS) lvm-static.o -static $(LDFLAGS) $(LVMLIBS) \
|
||||
$(LIBS) -rdynamic
|
||||
|
||||
liblvm2cmd.a: $(top_srcdir)/lib/liblvm.a $(OBJECTS)
|
||||
cat $(top_srcdir)/lib/liblvm.a > $@
|
||||
|
||||
@@ -59,6 +59,7 @@ arg(activevolumegroups_ARG, 'A', "activevolumegroups", NULL)
|
||||
arg(background_ARG, 'b', "background", NULL)
|
||||
arg(blockdevice_ARG, 'b', "blockdevice", NULL)
|
||||
arg(chunksize_ARG, 'c', "chunksize", size_kb_arg)
|
||||
arg(clustered_ARG, 'c', "clustered", yes_no_arg)
|
||||
arg(colon_ARG, 'c', "colon", NULL)
|
||||
arg(columns_ARG, 'C', "columns", NULL)
|
||||
arg(contiguous_ARG, 'C', "contiguous", yes_no_arg)
|
||||
|
||||
@@ -410,6 +410,7 @@ xx(pvdisplay,
|
||||
"\n"
|
||||
"pvdisplay --columns|-C\n"
|
||||
"\t[--aligned]\n"
|
||||
"\t[-a|--all]\n"
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|--help]\n"
|
||||
"\t[--ignorelockingfailure]\n"
|
||||
@@ -424,9 +425,9 @@ xx(pvdisplay,
|
||||
"\t[--version]" "\n"
|
||||
"\t[PhysicalVolumePath [PhysicalVolumePath...]]\n",
|
||||
|
||||
aligned_ARG, colon_ARG, columns_ARG, ignorelockingfailure_ARG, maps_ARG,
|
||||
noheadings_ARG, nosuffix_ARG, options_ARG, separator_ARG, short_ARG,
|
||||
sort_ARG, unbuffered_ARG, units_ARG)
|
||||
aligned_ARG, all_ARG, colon_ARG, columns_ARG, ignorelockingfailure_ARG,
|
||||
maps_ARG, noheadings_ARG, nosuffix_ARG, options_ARG, separator_ARG,
|
||||
short_ARG, sort_ARG, unbuffered_ARG, units_ARG)
|
||||
|
||||
xx(pvmove,
|
||||
"Move extents from one physical volume to another",
|
||||
@@ -436,7 +437,6 @@ xx(pvmove,
|
||||
"\t[--alloc AllocationPolicy]\n"
|
||||
"\t[-b|--background]\n"
|
||||
"\t[-d|--debug]\n "
|
||||
"\t[-f|--force]\n"
|
||||
"\t[-h|-?|--help]\n"
|
||||
"\t[-i|--interval seconds]\n"
|
||||
"\t[-t|--test]\n "
|
||||
@@ -447,7 +447,7 @@ xx(pvmove,
|
||||
"\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n"
|
||||
"\t[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n",
|
||||
|
||||
abort_ARG, alloc_ARG, autobackup_ARG, background_ARG, force_ARG,
|
||||
abort_ARG, alloc_ARG, autobackup_ARG, background_ARG,
|
||||
interval_ARG, name_ARG, test_ARG)
|
||||
|
||||
xx(pvremove,
|
||||
@@ -566,6 +566,7 @@ xx(vgchange,
|
||||
"\t[-v|--verbose] " "\n"
|
||||
"\t[--version]" "\n"
|
||||
"\t{-a|--available [e|l]{y|n} |" "\n"
|
||||
"\t -c|--clustered {y|n} |" "\n"
|
||||
"\t -x|--resizeable {y|n} |" "\n"
|
||||
"\t -l|--logicalvolume MaxLogicalVolumes |" "\n"
|
||||
"\t --addtag Tag |\n"
|
||||
@@ -573,8 +574,8 @@ xx(vgchange,
|
||||
"\t[VolumeGroupName...]\n",
|
||||
|
||||
addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, available_ARG,
|
||||
deltag_ARG, ignorelockingfailure_ARG, logicalvolume_ARG, partial_ARG,
|
||||
resizeable_ARG, resizable_ARG, test_ARG, uuid_ARG)
|
||||
clustered_ARG, deltag_ARG, ignorelockingfailure_ARG, logicalvolume_ARG,
|
||||
partial_ARG, resizeable_ARG, resizable_ARG, test_ARG, uuid_ARG)
|
||||
|
||||
xx(vgck,
|
||||
"Check the consistency of volume group(s)",
|
||||
@@ -608,6 +609,7 @@ xx(vgcreate,
|
||||
"\t[-A|--autobackup {y|n}] " "\n"
|
||||
"\t[--addtag Tag] " "\n"
|
||||
"\t[--alloc AllocationPolicy] " "\n"
|
||||
"\t[-c|--clustered] " "\n"
|
||||
"\t[-d|--debug]" "\n"
|
||||
"\t[-h|--help]" "\n"
|
||||
"\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
|
||||
@@ -619,7 +621,7 @@ xx(vgcreate,
|
||||
"\t[--version] " "\n"
|
||||
"\tVolumeGroupName PhysicalVolume [PhysicalVolume...]\n",
|
||||
|
||||
addtag_ARG, alloc_ARG, autobackup_ARG, maxlogicalvolumes_ARG,
|
||||
addtag_ARG, alloc_ARG, autobackup_ARG, clustered_ARG, maxlogicalvolumes_ARG,
|
||||
maxphysicalvolumes_ARG, metadatatype_ARG, physicalextentsize_ARG, test_ARG)
|
||||
|
||||
xx(vgdisplay,
|
||||
|
||||
155
tools/dmsetup.c
155
tools/dmsetup.c
@@ -23,6 +23,7 @@
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#ifdef HAVE_GETOPTLONG
|
||||
# include <getopt.h>
|
||||
@@ -58,7 +59,9 @@ enum {
|
||||
MAJOR_ARG,
|
||||
MINOR_ARG,
|
||||
NOHEADINGS_ARG,
|
||||
NOOPENCOUNT_ARG,
|
||||
NOTABLE_ARG,
|
||||
OPTIONS_ARG,
|
||||
UUID_ARG,
|
||||
VERBOSE_ARG,
|
||||
VERSION_ARG,
|
||||
@@ -68,6 +71,7 @@ enum {
|
||||
static int _switches[NUM_SWITCHES];
|
||||
static int _values[NUM_SWITCHES];
|
||||
static char *_uuid;
|
||||
static char *_fields;
|
||||
|
||||
/*
|
||||
* Commands
|
||||
@@ -136,15 +140,18 @@ static void _display_info_cols_noheadings(struct dm_task *dmt,
|
||||
|
||||
uuid = dm_task_get_uuid(dmt);
|
||||
|
||||
printf("%s:%d:%d:%s%s%s%s:%d:%d:%" PRIu32 ":%s\n",
|
||||
dm_task_get_name(dmt),
|
||||
info->major, info->minor,
|
||||
info->live_table ? "L" : "-",
|
||||
info->inactive_table ? "I" : "-",
|
||||
info->suspended ? "s" : "-",
|
||||
info->read_only ? "r" : "w",
|
||||
info->open_count, info->target_count, info->event_nr,
|
||||
uuid && *uuid ? uuid : "");
|
||||
if (_switches[OPTIONS_ARG])
|
||||
printf("%s\n", dm_task_get_name(dmt));
|
||||
else
|
||||
printf("%s:%d:%d:%s%s%s%s:%d:%d:%" PRIu32 ":%s\n",
|
||||
dm_task_get_name(dmt),
|
||||
info->major, info->minor,
|
||||
info->live_table ? "L" : "-",
|
||||
info->inactive_table ? "I" : "-",
|
||||
info->suspended ? "s" : "-",
|
||||
info->read_only ? "r" : "w",
|
||||
info->open_count, info->target_count, info->event_nr,
|
||||
uuid && *uuid ? uuid : "");
|
||||
}
|
||||
|
||||
static void _display_info_cols(struct dm_task *dmt, struct dm_info *info)
|
||||
@@ -158,24 +165,31 @@ static void _display_info_cols(struct dm_task *dmt, struct dm_info *info)
|
||||
}
|
||||
|
||||
if (!_headings) {
|
||||
printf("Name Maj Min Stat Open Targ Event UUID\n");
|
||||
if (_switches[OPTIONS_ARG])
|
||||
printf("Name\n");
|
||||
else
|
||||
printf("Name Maj Min Stat Open Targ "
|
||||
"Event UUID\n");
|
||||
_headings = 1;
|
||||
}
|
||||
|
||||
printf("%-16s ", dm_task_get_name(dmt));
|
||||
if (_switches[OPTIONS_ARG])
|
||||
printf("%s\n", dm_task_get_name(dmt));
|
||||
else {
|
||||
printf("%-16s %3d %3d %s%s%s%s %4d %4d %6" PRIu32 " ",
|
||||
dm_task_get_name(dmt),
|
||||
info->major, info->minor,
|
||||
info->live_table ? "L" : "-",
|
||||
info->inactive_table ? "I" : "-",
|
||||
info->suspended ? "s" : "-",
|
||||
info->read_only ? "r" : "w",
|
||||
info->open_count, info->target_count, info->event_nr);
|
||||
|
||||
printf("%3d %3d %s%s%s%s %4d %4d %6" PRIu32 " ",
|
||||
info->major, info->minor,
|
||||
info->live_table ? "L" : "-",
|
||||
info->inactive_table ? "I" : "-",
|
||||
info->suspended ? "s" : "-",
|
||||
info->read_only ? "r" : "w",
|
||||
info->open_count, info->target_count, info->event_nr);
|
||||
if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
|
||||
printf("%s", uuid);
|
||||
|
||||
if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
|
||||
printf("%s", uuid);
|
||||
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void _display_info_long(struct dm_task *dmt, struct dm_info *info)
|
||||
@@ -216,12 +230,12 @@ static void _display_info_long(struct dm_task *dmt, struct dm_info *info)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void _display_info(struct dm_task *dmt)
|
||||
static int _display_info(struct dm_task *dmt)
|
||||
{
|
||||
struct dm_info info;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (!_switches[COLS_ARG])
|
||||
_display_info_long(dmt, &info);
|
||||
@@ -229,6 +243,8 @@ static void _display_info(struct dm_task *dmt)
|
||||
_display_info_cols_noheadings(dmt, &info);
|
||||
else
|
||||
_display_info_cols(dmt, &info);
|
||||
|
||||
return info.exists ? 1 : 0;
|
||||
}
|
||||
|
||||
static int _set_task_device(struct dm_task *dmt, const char *name, int optional)
|
||||
@@ -291,13 +307,16 @@ static int _load(int argc, char **argv, void *data)
|
||||
if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
r = 1;
|
||||
|
||||
if (_switches[VERBOSE_ARG])
|
||||
_display_info(dmt);
|
||||
r = _display_info(dmt);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
@@ -335,13 +354,16 @@ static int _create(int argc, char **argv, void *data)
|
||||
if (_switches[MINOR_ARG] && !dm_task_set_minor(dmt, _values[MINOR_ARG]))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
r = 1;
|
||||
|
||||
if (_switches[VERBOSE_ARG])
|
||||
_display_info(dmt);
|
||||
r = _display_info(dmt);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
@@ -364,6 +386,9 @@ static int _rename(int argc, char **argv, void *data)
|
||||
if (!dm_task_set_newname(dmt, argv[argc - 1]))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
@@ -420,6 +445,9 @@ static int _message(int argc, char **argv, void *data)
|
||||
|
||||
free(str);
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
@@ -476,10 +504,13 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)
|
||||
if (event_nr && !dm_task_set_event_nr(dmt, event_nr))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
r = dm_task_run(dmt);
|
||||
|
||||
if (r && display && _switches[VERBOSE_ARG])
|
||||
_display_info(dmt);
|
||||
r = _display_info(dmt);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
@@ -599,6 +630,9 @@ static int _status(int argc, char **argv, void *data)
|
||||
if (!_set_task_device(dmt, name, 0))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
@@ -674,6 +708,9 @@ static int _mknodes(int argc, char **argv, void *data)
|
||||
if (!_set_task_device(dmt, argc > 1 ? argv[1] : NULL, 1))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
@@ -707,12 +744,13 @@ static int _info(int argc, char **argv, void *data)
|
||||
if (!_set_task_device(dmt, name, 0))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
_display_info(dmt);
|
||||
|
||||
r = 1;
|
||||
r = _display_info(dmt);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
@@ -744,6 +782,9 @@ static int _deps(int argc, char **argv, void *data)
|
||||
if (!_set_task_device(dmt, name, 0))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
@@ -841,7 +882,7 @@ static void _usage(FILE *out)
|
||||
|
||||
fprintf(out, "Usage:\n\n");
|
||||
fprintf(out, "dmsetup [--version] [-v|--verbose [-v|--verbose ...]]\n"
|
||||
" [-r|--readonly]\n\n");
|
||||
" [-r|--readonly] [--noopencount]\n\n");
|
||||
for (i = 0; _commands[i].name; i++)
|
||||
fprintf(out, "\t%s %s\n", _commands[i].name, _commands[i].help);
|
||||
fprintf(out, "\n<device> may be device name or -u <uuid> or "
|
||||
@@ -863,6 +904,7 @@ static struct command *_find_command(const char *name)
|
||||
|
||||
static int _process_switches(int *argc, char ***argv)
|
||||
{
|
||||
char *base, *namebase;
|
||||
int ind;
|
||||
int c;
|
||||
|
||||
@@ -873,7 +915,9 @@ static int _process_switches(int *argc, char ***argv)
|
||||
{"major", 1, NULL, MAJOR_ARG},
|
||||
{"minor", 1, NULL, MINOR_ARG},
|
||||
{"noheadings", 0, NULL, NOHEADINGS_ARG},
|
||||
{"noopencount", 0, NULL, NOOPENCOUNT_ARG},
|
||||
{"notable", 0, NULL, NOTABLE_ARG},
|
||||
{"options", 1, NULL, OPTIONS_ARG},
|
||||
{"uuid", 1, NULL, UUID_ARG},
|
||||
{"verbose", 1, NULL, VERBOSE_ARG},
|
||||
{"version", 0, NULL, VERSION_ARG},
|
||||
@@ -889,9 +933,43 @@ static int _process_switches(int *argc, char ***argv)
|
||||
memset(&_switches, 0, sizeof(_switches));
|
||||
memset(&_values, 0, sizeof(_values));
|
||||
|
||||
namebase = strdup((*argv)[0]);
|
||||
base = basename(namebase);
|
||||
|
||||
if (!strcmp(base, "devmap_name")) {
|
||||
free(namebase);
|
||||
_switches[COLS_ARG]++;
|
||||
_switches[NOHEADINGS_ARG]++;
|
||||
_switches[OPTIONS_ARG]++;
|
||||
_switches[MAJOR_ARG]++;
|
||||
_switches[MINOR_ARG]++;
|
||||
_fields = (char *) "name";
|
||||
|
||||
if (*argc == 3) {
|
||||
_values[MAJOR_ARG] = atoi((*argv)[1]);
|
||||
_values[MINOR_ARG] = atoi((*argv)[2]);
|
||||
*argc -= 2;
|
||||
*argv += 2;
|
||||
} else if ((*argc == 2) &&
|
||||
(2 == sscanf((*argv)[1], "%i:%i",
|
||||
&_values[MAJOR_ARG],
|
||||
&_values[MINOR_ARG]))) {
|
||||
*argc -= 1;
|
||||
*argv += 1;
|
||||
} else {
|
||||
fprintf(stderr, "Usage: devmap_name <major> <minor>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*argv)[0] = (char *) "info";
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(namebase);
|
||||
|
||||
optarg = 0;
|
||||
optind = OPTIND_INIT;
|
||||
while ((c = GETOPTLONG_FN(*argc, *argv, "cCj:m:nru:v",
|
||||
while ((c = GETOPTLONG_FN(*argc, *argv, "cCj:m:no:ru:v",
|
||||
long_options, &ind)) != -1) {
|
||||
if (c == 'c' || c == 'C' || ind == COLS_ARG)
|
||||
_switches[COLS_ARG]++;
|
||||
@@ -907,6 +985,10 @@ static int _process_switches(int *argc, char ***argv)
|
||||
}
|
||||
if (c == 'n' || ind == NOTABLE_ARG)
|
||||
_switches[NOTABLE_ARG]++;
|
||||
if (c == 'o' || ind == OPTIONS_ARG) {
|
||||
_switches[OPTIONS_ARG]++;
|
||||
_fields = optarg;
|
||||
}
|
||||
if (c == 'v' || ind == VERBOSE_ARG)
|
||||
_switches[VERBOSE_ARG]++;
|
||||
if (c == 'u' || ind == UUID_ARG) {
|
||||
@@ -915,6 +997,8 @@ static int _process_switches(int *argc, char ***argv)
|
||||
}
|
||||
if ((ind == NOHEADINGS_ARG))
|
||||
_switches[NOHEADINGS_ARG]++;
|
||||
if ((ind == NOOPENCOUNT_ARG))
|
||||
_switches[NOOPENCOUNT_ARG]++;
|
||||
if ((ind == VERSION_ARG))
|
||||
_switches[VERSION_ARG]++;
|
||||
}
|
||||
@@ -929,6 +1013,11 @@ static int _process_switches(int *argc, char ***argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_switches[OPTIONS_ARG] && strcmp(_fields, "name")) {
|
||||
fprintf(stderr, "Only -o name is supported so far.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*argv += optind;
|
||||
*argc -= optind;
|
||||
return 1;
|
||||
@@ -939,7 +1028,7 @@ int main(int argc, char **argv)
|
||||
struct command *c;
|
||||
|
||||
if (!_process_switches(&argc, &argv)) {
|
||||
fprintf(stderr, "Couldn't process command line switches.\n");
|
||||
fprintf(stderr, "Couldn't process command line.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,12 @@ static int lvchange_availability(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (lockingfailed() && (lv->vg->status & CLUSTERED)) {
|
||||
log_verbose("Locking failed: ignoring clustered "
|
||||
"logical volume %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
|
||||
log_verbose("Activating logical volume \"%s\" "
|
||||
"exclusively", lv->name);
|
||||
@@ -256,7 +262,7 @@ static int lvchange_persistent(struct cmd_context *cmd,
|
||||
log_error("Major number must be specified with -My");
|
||||
return 0;
|
||||
}
|
||||
if (lv_info(lv, &info) && info.exists &&
|
||||
if (lv_info(lv, &info, 0) && info.exists &&
|
||||
!arg_count(cmd, force_ARG)) {
|
||||
if (yes_no_prompt("Logical volume %s will be "
|
||||
"deactivated temporarily. "
|
||||
@@ -361,6 +367,7 @@ static int lvchange_tag(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
void *handle)
|
||||
{
|
||||
|
||||
@@ -609,7 +609,8 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vg_add_snapshot(org, lv, 1, NULL, lp->chunk_size)) {
|
||||
if (!vg_add_snapshot(org, lv, 1, NULL, org->le_count,
|
||||
lp->chunk_size)) {
|
||||
log_err("Couldn't create snapshot.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
21
tools/lvm-static.c
Normal file
21
tools/lvm-static.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lvm2cmdline.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return lvm2_main(argc, argv, 1);
|
||||
}
|
||||
@@ -17,5 +17,5 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return lvm2_main(argc, argv);
|
||||
return lvm2_main(argc, argv, 0);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
#ifndef _LVM_CMDLINE_H
|
||||
#define _LVM_CMDLINE_H
|
||||
|
||||
int lvm2_main(int argc, char **argv);
|
||||
int lvm2_main(int argc, char **argv, int is_static);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -753,6 +753,7 @@ static void _apply_settings(struct cmd_context *cmd)
|
||||
init_debug(cmd->current_settings.debug);
|
||||
init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
|
||||
init_test(cmd->current_settings.test);
|
||||
init_full_scan_done(0);
|
||||
|
||||
init_msg_prefix(cmd->default_settings.msg_prefix);
|
||||
init_cmd_name(cmd->default_settings.cmd_name);
|
||||
@@ -978,6 +979,7 @@ static void _close_stray_fds(void)
|
||||
{
|
||||
struct rlimit rlim;
|
||||
int fd;
|
||||
int suppress_warnings = 0;
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
||||
fprintf(stderr, "getrlimit(RLIMIT_NOFILE) failed: %s\n",
|
||||
@@ -985,8 +987,13 @@ static void _close_stray_fds(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (getenv("LVM_SUPPRESS_FD_WARNINGS"))
|
||||
suppress_warnings = 1;
|
||||
|
||||
for (fd = 3; fd < rlim.rlim_cur; fd++) {
|
||||
if (!close(fd))
|
||||
if (suppress_warnings)
|
||||
close(fd);
|
||||
else if (!close(fd))
|
||||
fprintf(stderr, "File descriptor %d left open\n", fd);
|
||||
else if (errno != EBADF)
|
||||
fprintf(stderr, "Close failed on stray file "
|
||||
@@ -998,8 +1005,6 @@ static struct cmd_context *_init_lvm(void)
|
||||
{
|
||||
struct cmd_context *cmd;
|
||||
|
||||
_close_stray_fds();
|
||||
|
||||
if (!(cmd = create_toolcontext(&the_args[0]))) {
|
||||
stack;
|
||||
return NULL;
|
||||
@@ -1411,16 +1416,14 @@ static void _exec_lvm1_command(struct cmd_context *cmd, int argc, char **argv)
|
||||
log_sys_error("execvp", path);
|
||||
}
|
||||
|
||||
int lvm2_main(int argc, char **argv)
|
||||
int lvm2_main(int argc, char **argv, int is_static)
|
||||
{
|
||||
char *namebase, *base;
|
||||
int ret, alias = 0;
|
||||
struct cmd_context *cmd;
|
||||
|
||||
if (!(cmd = _init_lvm()))
|
||||
return -1;
|
||||
_close_stray_fds();
|
||||
|
||||
cmd->argv = argv;
|
||||
namebase = strdup(argv[0]);
|
||||
base = basename(namebase);
|
||||
while (*base == '/')
|
||||
@@ -1428,8 +1431,21 @@ int lvm2_main(int argc, char **argv)
|
||||
if (strcmp(base, "lvm") && strcmp(base, "lvm.static") &&
|
||||
strcmp(base, "initrd-lvm"))
|
||||
alias = 1;
|
||||
|
||||
if (is_static && strcmp(base, "lvm.static") &&
|
||||
path_exists(LVM_SHARED_PATH) &&
|
||||
!getenv("LVM_DID_EXEC")) {
|
||||
setenv("LVM_DID_EXEC", base, 1);
|
||||
execvp(LVM_SHARED_PATH, argv);
|
||||
unsetenv("LVM_DID_EXEC");
|
||||
}
|
||||
|
||||
free(namebase);
|
||||
|
||||
if (!(cmd = _init_lvm()))
|
||||
return -1;
|
||||
|
||||
cmd->argv = argv;
|
||||
_register_commands();
|
||||
|
||||
if (_lvm1_fallback(cmd)) {
|
||||
|
||||
@@ -34,7 +34,7 @@ static int _get_max_dev_name_len(struct dev_filter *filter)
|
||||
struct dev_iter *iter;
|
||||
struct device *dev;
|
||||
|
||||
if (!(iter = dev_iter_create(filter))) {
|
||||
if (!(iter = dev_iter_create(filter, 1))) {
|
||||
log_error("dev_iter_create failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ int lvmdiskscan(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
max_len = _get_max_dev_name_len(cmd->filter);
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->filter))) {
|
||||
if (!(iter = dev_iter_create(cmd->filter, 0))) {
|
||||
log_error("dev_iter_create failed");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
/* FIXME Ensure not referred to by another existing LVs */
|
||||
|
||||
if (lv_info(lv, &info)) {
|
||||
if (lv_info(lv, &info, 1)) {
|
||||
if (info.open_count) {
|
||||
log_error("Can't remove open logical volume \"%s\"",
|
||||
lv->name);
|
||||
|
||||
@@ -364,7 +364,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
|
||||
if (lp->resize == LV_REDUCE || lp->resizefs) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
if (!lv_info(lv, &info) && driver_version(NULL, 0)) {
|
||||
if (!lv_info(lv, &info, 1) && driver_version(NULL, 0)) {
|
||||
log_error("lv_info failed: aborting");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
const char *active_str, *snapshot_str;
|
||||
|
||||
/* FIXME Add -D arg to skip this! */
|
||||
if (lv_info(lv, &info) && info.exists)
|
||||
if (lv_info(lv, &info, 0) && info.exists)
|
||||
active_str = "ACTIVE ";
|
||||
else
|
||||
active_str = "inactive ";
|
||||
|
||||
@@ -138,8 +138,11 @@ static int _wait_for_single_mirror(struct cmd_context *cmd, const char *name,
|
||||
while (!finished) {
|
||||
/* FIXME Also needed in vg/lvchange -ay? */
|
||||
/* FIXME Use alarm for regular intervals instead */
|
||||
if (parms->interval && !parms->aborting)
|
||||
if (parms->interval && !parms->aborting) {
|
||||
sleep(parms->interval);
|
||||
/* Devices might have changed while we slept */
|
||||
init_full_scan_done(0);
|
||||
}
|
||||
|
||||
/* Locks the (possibly renamed) VG again */
|
||||
if (!(vg = parms->poll_fns->get_copy_vg(cmd, name))) {
|
||||
|
||||
@@ -173,7 +173,11 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
}
|
||||
} else {
|
||||
/* --uuid: Change PV ID randomly */
|
||||
id_create(&pv->id);
|
||||
if (!id_create(&pv->id)) {
|
||||
log_error("Failed to generate new random UUID for %s.",
|
||||
pv_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
log_verbose("Updating physical volume \"%s\"", pv_name);
|
||||
|
||||
@@ -63,10 +63,10 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
|
||||
/* Is there an md superblock here? */
|
||||
if (!dev && md_filtering()) {
|
||||
unlock_vg(cmd, "");
|
||||
log_verbose("Wiping cache of LVM-capable devices");
|
||||
|
||||
persistent_filter_wipe(cmd->filter);
|
||||
log_verbose("Wiping internal cache");
|
||||
lvmcache_destroy();
|
||||
|
||||
init_md_filtering(0);
|
||||
if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
|
||||
log_error("Can't get lock for orphan PVs");
|
||||
|
||||
@@ -64,6 +64,7 @@ int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
return pvs(cmd, argc, argv);
|
||||
} else if (arg_count(cmd, aligned_ARG) ||
|
||||
arg_count(cmd, all_ARG) ||
|
||||
arg_count(cmd, noheadings_ARG) ||
|
||||
arg_count(cmd, options_ARG) ||
|
||||
arg_count(cmd, separator_ARG) ||
|
||||
|
||||
@@ -123,10 +123,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
|
||||
arg_count(cmd, exported_ARG) ?
|
||||
"of exported volume group(s)" : "in no volume group");
|
||||
|
||||
log_verbose("Wiping cache of LVM-capable devices");
|
||||
persistent_filter_wipe(cmd->filter);
|
||||
|
||||
log_verbose("Wiping internal cache");
|
||||
lvmcache_destroy();
|
||||
|
||||
log_verbose("Walking through all physical volumes");
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
/*
|
||||
* Metadata iteration functions
|
||||
*/
|
||||
int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct list *arg_lvnames, struct list *tags,
|
||||
void *handle,
|
||||
@@ -93,23 +96,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return ret_max;
|
||||
}
|
||||
|
||||
struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname,
|
||||
int lock_type)
|
||||
{
|
||||
int consistent = 1;
|
||||
|
||||
lock_type &= ~LCK_TYPE_MASK;
|
||||
lock_type |= LCK_WRITE;
|
||||
|
||||
if (!lock_vol(cmd, vgname, lock_type)) {
|
||||
log_error("Can't lock %s for metadata recovery: skipping",
|
||||
vgname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vg_read(cmd, vgname, &consistent);
|
||||
}
|
||||
|
||||
int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
|
||||
int lock_type, void *handle,
|
||||
int (*process_single) (struct cmd_context * cmd,
|
||||
@@ -477,7 +463,7 @@ static int _process_all_devs(struct cmd_context *cmd, void *handle,
|
||||
int ret_max = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->filter))) {
|
||||
if (!(iter = dev_iter_create(cmd->filter, 1))) {
|
||||
log_error("dev_iter creation failed");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
@@ -608,6 +594,9 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
|
||||
return ret_max;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine volume group name from a logical volume name
|
||||
*/
|
||||
const char *extract_vgname(struct cmd_context *cmd, const char *lv_name)
|
||||
{
|
||||
const char *vg_name = lv_name;
|
||||
@@ -666,6 +655,9 @@ const char *extract_vgname(struct cmd_context *cmd, const char *lv_name)
|
||||
return vg_name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract default volume group name from environment
|
||||
*/
|
||||
char *default_vgname(struct cmd_context *cmd)
|
||||
{
|
||||
char *vg_path;
|
||||
@@ -694,6 +686,9 @@ char *default_vgname(struct cmd_context *cmd)
|
||||
return pool_strdup(cmd->mem, vg_path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process physical extent range specifiers
|
||||
*/
|
||||
static int _add_pe_range(struct pool *mem, struct list *pe_ranges,
|
||||
uint32_t start, uint32_t count)
|
||||
{
|
||||
@@ -928,6 +923,29 @@ struct list *clone_pv_list(struct pool *mem, struct list *pvsl)
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt metadata recovery
|
||||
*/
|
||||
struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname,
|
||||
int lock_type)
|
||||
{
|
||||
int consistent = 1;
|
||||
|
||||
lock_type &= ~LCK_TYPE_MASK;
|
||||
lock_type |= LCK_WRITE;
|
||||
|
||||
if (!lock_vol(cmd, vgname, lock_type)) {
|
||||
log_error("Can't lock %s for metadata recovery: skipping",
|
||||
vgname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vg_read(cmd, vgname, &consistent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute and wait for external command
|
||||
*/
|
||||
int exec_cmd(const char *command, const char *fscmd, const char *lv_path,
|
||||
const char *size)
|
||||
{
|
||||
|
||||
@@ -135,7 +135,7 @@ int alloc_arg(struct cmd_context *cmd, struct arg *a);
|
||||
char yes_no_prompt(const char *prompt, ...);
|
||||
|
||||
/* we use the enums to access the switches */
|
||||
static inline const unsigned int arg_count(struct cmd_context *cmd, int a)
|
||||
static inline unsigned int arg_count(struct cmd_context *cmd, int a)
|
||||
{
|
||||
return cmd->args[a].count;
|
||||
}
|
||||
@@ -151,25 +151,25 @@ static inline const char *arg_str_value(struct cmd_context *cmd, int a,
|
||||
return arg_count(cmd, a) ? cmd->args[a].value : def;
|
||||
}
|
||||
|
||||
static inline const int32_t arg_int_value(struct cmd_context *cmd, int a,
|
||||
static inline int32_t arg_int_value(struct cmd_context *cmd, int a,
|
||||
const int32_t def)
|
||||
{
|
||||
return arg_count(cmd, a) ? cmd->args[a].i_value : def;
|
||||
}
|
||||
|
||||
static inline const uint32_t arg_uint_value(struct cmd_context *cmd, int a,
|
||||
static inline uint32_t arg_uint_value(struct cmd_context *cmd, int a,
|
||||
const uint32_t def)
|
||||
{
|
||||
return arg_count(cmd, a) ? cmd->args[a].ui_value : def;
|
||||
}
|
||||
|
||||
static inline const int64_t arg_int64_value(struct cmd_context *cmd, int a,
|
||||
static inline int64_t arg_int64_value(struct cmd_context *cmd, int a,
|
||||
const uint64_t def)
|
||||
{
|
||||
return arg_count(cmd, a) ? cmd->args[a].i64_value : def;
|
||||
}
|
||||
|
||||
static inline const uint64_t arg_uint64_value(struct cmd_context *cmd, int a,
|
||||
static inline uint64_t arg_uint64_value(struct cmd_context *cmd, int a,
|
||||
const uint64_t def)
|
||||
{
|
||||
return arg_count(cmd, a) ? cmd->args[a].ui64_value : def;
|
||||
@@ -181,13 +181,13 @@ static inline const void *arg_ptr_value(struct cmd_context *cmd, int a,
|
||||
return arg_count(cmd, a) ? cmd->args[a].ptr : def;
|
||||
}
|
||||
|
||||
static inline const sign_t arg_sign_value(struct cmd_context *cmd, int a,
|
||||
static inline sign_t arg_sign_value(struct cmd_context *cmd, int a,
|
||||
const sign_t def)
|
||||
{
|
||||
return arg_count(cmd, a) ? cmd->args[a].sign : def;
|
||||
}
|
||||
|
||||
static inline const int arg_count_increment(struct cmd_context *cmd, int a)
|
||||
static inline int arg_count_increment(struct cmd_context *cmd, int a)
|
||||
{
|
||||
return cmd->args[a].count++;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,12 @@ static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (activate && lockingfailed() && (vg->status & CLUSTERED)) {
|
||||
log_error("Locking inactive: ignoring clustered "
|
||||
"volume group %s", vg->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (activate && (active = lvs_in_vg_activated(vg)))
|
||||
log_verbose("%d logical volume(s) in volume group \"%s\" "
|
||||
"already active", active, vg->name);
|
||||
@@ -168,6 +174,41 @@ static int _vgchange_resizeable(struct cmd_context *cmd,
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static int _vgchange_clustered(struct cmd_context *cmd,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
int clustered = !strcmp(arg_str_value(cmd, clustered_ARG, "n"), "y");
|
||||
|
||||
if (clustered && (vg->status & CLUSTERED)) {
|
||||
log_error("Volume group \"%s\" is already clustered",
|
||||
vg->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!clustered && !(vg->status & CLUSTERED)) {
|
||||
log_error("Volume group \"%s\" is already not clustered",
|
||||
vg->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!archive(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
if (clustered)
|
||||
vg->status |= CLUSTERED;
|
||||
else
|
||||
vg->status &= ~CLUSTERED;
|
||||
|
||||
if (!vg_write(vg) || !vg_commit(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
backup(vg);
|
||||
|
||||
log_print("Volume group \"%s\" successfully changed", vg->name);
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static int _vgchange_logicalvolume(struct cmd_context *cmd,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
@@ -264,7 +305,11 @@ static int _vgchange_uuid(struct cmd_context *cmd, struct volume_group *vg)
|
||||
if (!archive(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
id_create(&vg->id);
|
||||
if (!id_create(&vg->id)) {
|
||||
log_error("Failed to generate new random UUID for VG %s.",
|
||||
vg->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
memcpy(&lvl->lv->lvid, &vg->id, sizeof(vg->id));
|
||||
@@ -330,6 +375,9 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
|
||||
else if (arg_count(cmd, alloc_ARG))
|
||||
r = _vgchange_alloc(cmd, vg);
|
||||
|
||||
else if (arg_count(cmd, clustered_ARG))
|
||||
r = _vgchange_clustered(cmd, vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -339,8 +387,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
(arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
|
||||
arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
|
||||
arg_count(cmd, addtag_ARG) + arg_count(cmd, uuid_ARG) +
|
||||
arg_count(cmd, alloc_ARG))) {
|
||||
log_error("One of -a, -l, -x, --alloc, --addtag, --deltag "
|
||||
arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG))) {
|
||||
log_error("One of -a, -c, -l, -x, --alloc, --addtag, --deltag "
|
||||
"or --uuid required");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
@@ -349,9 +397,9 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
if (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
|
||||
arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
|
||||
arg_count(cmd, addtag_ARG) + arg_count(cmd, alloc_ARG) +
|
||||
arg_count(cmd, uuid_ARG) > 1) {
|
||||
log_error("Only one of -a, -l, -x, --alloc, --addtag, --deltag "
|
||||
"or --uuid allowed");
|
||||
arg_count(cmd, uuid_ARG) + arg_count(cmd, clustered_ARG) > 1) {
|
||||
log_error("Only one of -a, -c, -l, -x, --uuid, --alloc, "
|
||||
"--addtag or --deltag allowed");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
|
||||
lv = lvl->lv;
|
||||
if (lvnum_from_lvid(&lv->lvid) < MAX_RESTRICTED_LVS)
|
||||
continue;
|
||||
if (lv_info(lv, &info) && info.exists) {
|
||||
if (lv_info(lv, &info, 0) && info.exists) {
|
||||
log_error("Logical volume %s must be "
|
||||
"deactivated before conversion.",
|
||||
lv->name);
|
||||
|
||||
@@ -26,6 +26,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
struct volume_group *vg;
|
||||
const char *tag;
|
||||
alloc_policy_t alloc;
|
||||
int clustered;
|
||||
|
||||
if (!argc) {
|
||||
log_error("Please provide volume group name and "
|
||||
@@ -130,6 +131,17 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_count(cmd, clustered_ARG))
|
||||
clustered = !strcmp(arg_str_value(cmd, clustered_ARG, "n"), "y");
|
||||
else
|
||||
/* Default depends on current locking type */
|
||||
clustered = locking_is_clustered();
|
||||
|
||||
if (clustered)
|
||||
vg->status |= CLUSTERED;
|
||||
else
|
||||
vg->status &= ~CLUSTERED;
|
||||
|
||||
if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
|
||||
log_error("Can't get lock for orphan PVs");
|
||||
return ECMD_FAILED;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user