mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-04 05:44:18 +03:00
Compare commits
111 Commits
old-v2_00_
...
v2_01_01
Author | SHA1 | Date | |
---|---|---|---|
|
fdc49402ec | ||
|
5457c133e1 | ||
|
292e588ee3 | ||
|
243494c25e | ||
|
e4365f3706 | ||
|
310f3038d3 | ||
|
4e6033273d | ||
|
73718586d3 | ||
|
011abe61e8 | ||
|
fe3a37f89d | ||
|
8aea44e77b | ||
|
5529aec0d6 | ||
|
369549d23f | ||
|
181ea9a381 | ||
|
76b8f2854e | ||
|
320e5198f9 | ||
|
e522539e2d | ||
|
7c996b83d2 | ||
|
3dd354d7aa | ||
|
f4ad6e2157 | ||
|
8b170dc2bf | ||
|
dcb9d779bf | ||
|
80f736d670 | ||
|
8502c6da3c | ||
|
b131449422 | ||
|
6eebc4a620 | ||
|
4661ab1179 | ||
|
86046445ed | ||
|
baea9bf944 | ||
|
0951ee9e63 | ||
|
5492528287 | ||
|
14dbd220c2 | ||
|
babc890c59 | ||
|
6f7b47ff40 | ||
|
3991f03202 | ||
|
27271d5da7 | ||
|
627312e1de | ||
|
bfc9550e4e | ||
|
2b9c21268b | ||
|
3dce4ed6f1 | ||
|
0f16c2ea87 | ||
|
9a635f0686 | ||
|
6a0d4b2baa | ||
|
ac017098ad | ||
|
98fef2640d | ||
|
8bb66e133a | ||
|
68a582901d | ||
|
c094f4c06e | ||
|
f7ca545544 | ||
|
69b4716894 | ||
|
7e44dcc5bf | ||
|
ab9843e183 | ||
|
01af706ade | ||
|
9ebdb08e99 | ||
|
a74ffe25d9 | ||
|
7f95e27707 | ||
|
1facf5bba3 | ||
|
03d77009eb | ||
|
8afd6812b5 | ||
|
ec9ad78fcf | ||
|
6f4e93dc90 | ||
|
a38e43862d | ||
|
39294bb037 | ||
|
edc5e59b78 | ||
|
c00fd9fd37 | ||
|
b3e621dd9f | ||
|
6e8c49b978 | ||
|
398d57133d | ||
|
16521a6feb | ||
|
3ca0b37a3e | ||
|
cf2ec1229d | ||
|
fe9b1e5f9b | ||
|
f5b96ddf01 | ||
|
2fe076fb27 | ||
|
99249cff04 | ||
|
0cdf7b0613 | ||
|
90bcf4f157 | ||
|
03c3ec4e12 | ||
|
ca9bb20d64 | ||
|
c6bc078fd9 | ||
|
2f4bd6e52c | ||
|
2affe53727 | ||
|
09654d7dd8 | ||
|
90a4e37815 | ||
|
60889c0c79 | ||
|
20f3408d96 | ||
|
e9d86789db | ||
|
5152b7c66c | ||
|
c494c4e12c | ||
|
54d58ccb7e | ||
|
714a77bfbe | ||
|
d48f8bf5cc | ||
|
99d97754a6 | ||
|
b9d437de2a | ||
|
11403f2019 | ||
|
1ca102d639 | ||
|
339ba55111 | ||
|
14ae59885a | ||
|
e3ef54f99b | ||
|
001901f9a9 | ||
|
6a98f60e2e | ||
|
6f2e24c47d | ||
|
aafa368923 | ||
|
eb783cab4c | ||
|
6533aa865a | ||
|
f1a1e1bc07 | ||
|
953f4838dd | ||
|
130b892d34 | ||
|
6ad525c77e | ||
|
d0ca74ad27 | ||
|
9806f69b4d |
0
CONTRIBUTORS
Normal file
0
CONTRIBUTORS
Normal file
98
WHATS_NEW
98
WHATS_NEW
@@ -1,3 +1,101 @@
|
||||
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
|
||||
====================================
|
||||
Drop static/dl restriction for now.
|
||||
Fix an error fprintf.
|
||||
Fix vgdisplay -s. Breaks (undocumented) lvs/pvs/vgs -s instead for now.
|
||||
Fix device reference counting on re-opens.
|
||||
Ignore sysfs symlinks when DT_UNKNOWN.
|
||||
Add clvmd init script for RHEL4.
|
||||
Skip devices that are too small to be PVs.
|
||||
Fix pvchange -x segfault with lvm2-format orphan.
|
||||
Cope with empty msdos partition tables.
|
||||
Add CONTRIBUTORS file.
|
||||
|
||||
Version 2.00.31 - 12th December 2004
|
||||
====================================
|
||||
Reopen RO file descriptors RW if necessary.
|
||||
|
||||
Version 2.00.30 - 10th December 2004
|
||||
====================================
|
||||
Additional device-handling debug messages.
|
||||
Additional verbosity level -vvvv includes line numbers and backtraces.
|
||||
Verbose messages now go to stderr not stdout.
|
||||
Close any stray file descriptors before starting.
|
||||
Refine partitionable checks for certain device types.
|
||||
Allow devices/types to override built-ins.
|
||||
Fix lvreduce man page .i->.I
|
||||
Fix vgsplit man page title.
|
||||
Fix clvmd man makefile.
|
||||
Extend dev_open logging.
|
||||
Make clvmd_fix_conf.sh UNDOable.
|
||||
|
||||
Version 2.00.29 - 27th November 2004
|
||||
====================================
|
||||
xlate compilation fix.
|
||||
|
||||
Version 2.00.28 - 27th November 2004
|
||||
====================================
|
||||
Fix partition table & md signature detection.
|
||||
Minor configure/makefile tidy.
|
||||
Export version.h from tools for clvmd.
|
||||
|
||||
Version 2.00.27 - 24th November 2004
|
||||
====================================
|
||||
Trap large memory allocation requests.
|
||||
Fix to partition table detection code.
|
||||
Improve filter debug mesgs.
|
||||
Make clvmd_fix_conf.sh UNDOable
|
||||
|
||||
Version 2.00.26 - 23rd November 2004
|
||||
====================================
|
||||
Improve pool debugging stats.
|
||||
Detect partition table signature.
|
||||
pvcreate wipes md superblocks. (With --uuid or --restorefile it prompts.)
|
||||
Separate out md superblock detection code.
|
||||
Prevent snapshot origin resizing.
|
||||
Improve a vgremove error message.
|
||||
Update some man pages.
|
||||
Allow y/n with -ae args (exclusive activation).
|
||||
Fixes to lvcreate vgname parsing.
|
||||
Fix dm_name string size calculation.
|
||||
Improve clvmd error reporting during startup.
|
||||
Make clvmd cope with large gaps in node numbers IDs.
|
||||
Make clvmd initialisation cope better with debugging output.
|
||||
Tidy clvmd socket callbacks so all work happens outside main loop.
|
||||
clvmd -V now displays lvm version too.
|
||||
Add optional gulm build for clvmd
|
||||
|
||||
Version 2.00.25 - 29th September 2004
|
||||
=====================================
|
||||
Fix return code from rm_link for vgmknodes.
|
||||
Make clvmd LV hash table thread-safe.
|
||||
Fix clvmd locking so it will lock out multiple users on the same node.
|
||||
Fix clvmd VG locking to it can cope with multiple VG locks.
|
||||
Remove spurious trailing dot in lvreduce man page.
|
||||
Fix vgremove locking.
|
||||
|
||||
Version 2.00.24 - 16th September 2004
|
||||
=====================================
|
||||
Fix pool_empty so it really does empty the memory pool.
|
||||
|
20
WHATS_NEW_DM
20
WHATS_NEW_DM
@@ -1,6 +1,24 @@
|
||||
Version 1.00.20 -
|
||||
Version 1.01.01 -
|
||||
=============================
|
||||
|
||||
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.
|
||||
Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
|
||||
Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
|
||||
Add --noheadings columns option for colon-separated dmsetup output.
|
||||
Support device referencing by uuid or major/minor.
|
||||
Warn if kernel data didn't fit in buffer.
|
||||
Fix a printf.
|
||||
|
||||
Version 1.00.19 - 3 July 2004
|
||||
=============================
|
||||
More autoconf fixes.
|
||||
|
16
configure.in
16
configure.in
@@ -280,12 +280,18 @@ AC_MSG_RESULT($SELINUX)
|
||||
################################################################################
|
||||
dnl -- Build cluster LVM daemon
|
||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
|
||||
AC_ARG_WITH(clvmd, [ --with-clvmd Build cluster LVM Daemon],
|
||||
CLVMD=$withval, CLVMD=no)
|
||||
AC_ARG_WITH(clvmd,
|
||||
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/none/all
|
||||
[TYPE=none] ],
|
||||
[ CLVMD="$withval" ],
|
||||
[ CLVMD="none" ])
|
||||
if test x$CLVMD = xyes; then
|
||||
CLVMD=all
|
||||
fi
|
||||
AC_MSG_RESULT($CLVMD)
|
||||
|
||||
dnl -- If clvmd enabled without cluster locking, automagically include it
|
||||
if test x$CLVMD = xyes && test x$CLUSTER = xnone; then
|
||||
if test x$CLVMD != xnone && test x$CLUSTER = xnone; then
|
||||
CLUSTER=internal
|
||||
fi
|
||||
|
||||
@@ -383,7 +389,7 @@ fi
|
||||
dnl -- Check for dlopen
|
||||
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
|
||||
|
||||
if [[ "x$HAVE_LIBDL" = xyes -a "x$STATIC_LINK" = xno ]]; then
|
||||
if [[ "x$HAVE_LIBDL" = xyes ]]; then
|
||||
CFLAGS="$CFLAGS -DHAVE_LIBDL"
|
||||
LIBS="-ldl $LIBS"
|
||||
else
|
||||
@@ -475,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
|
||||
|
@@ -15,7 +15,7 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
ifeq ("@CLVMD@", "yes")
|
||||
ifneq ("@CLVMD@", "none")
|
||||
SUBDIRS = clvmd
|
||||
endif
|
||||
|
||||
|
@@ -16,26 +16,50 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SOURCES = \
|
||||
clvmd-cman.c \
|
||||
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 ("$(GULM)", "yes")
|
||||
SOURCES += clvmd-gulm.c tcp-comms.c
|
||||
LMLIBS += -lccs -lgulm
|
||||
CFLAGS += -DUSE_GULM
|
||||
endif
|
||||
|
||||
ifeq ("$(CMAN)", "yes")
|
||||
SOURCES += clvmd-cman.c
|
||||
LMLIBS += -ldlm
|
||||
CFLAGS += -DUSE_CMAN
|
||||
endif
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
CFLAGS += -D_REENTRANT -fno-strict-aliasing
|
||||
LIBS += -ldevmapper -ldlm -llvm -lpthread
|
||||
LIBS += -ldevmapper -llvm -lpthread
|
||||
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
|
||||
$(CC) -o clvmd $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(LIBS)
|
||||
$(CC) -o clvmd $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
.PHONY: install_clvmd
|
||||
|
||||
|
@@ -55,7 +55,6 @@ static int max_updown_nodes = 50; /* Current size of the allocated array */
|
||||
static int *node_updown = NULL;
|
||||
static dlm_lshandle_t *lockspace;
|
||||
|
||||
static void sigusr1_handler(int sig);
|
||||
static void count_clvmds_running(void);
|
||||
static void get_members(void);
|
||||
static int nodeid_from_csid(char *csid);
|
||||
@@ -67,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;
|
||||
@@ -75,7 +74,7 @@ int init_cluster()
|
||||
/* Open the cluster communication socket */
|
||||
cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT);
|
||||
if (cluster_sock == -1) {
|
||||
perror("Can't open cluster socket");
|
||||
syslog(LOG_ERR, "Can't open cman cluster manager socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -87,7 +86,7 @@ int init_cluster()
|
||||
if (bind
|
||||
(cluster_sock, (struct sockaddr *) &saddr,
|
||||
sizeof(struct sockaddr_cl))) {
|
||||
log_error("Can't bind cluster socket: %m");
|
||||
syslog(LOG_ERR, "Can't bind cluster socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -98,25 +97,25 @@ int init_cluster()
|
||||
/* Create a lockspace for LV & VG locks to live in */
|
||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
||||
if (!lockspace) {
|
||||
log_error("Unable to create lockspace for CLVM\n");
|
||||
syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m");
|
||||
return -1;
|
||||
}
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_main_cluster_fd()
|
||||
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;
|
||||
@@ -136,7 +135,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;
|
||||
@@ -152,26 +151,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;
|
||||
@@ -203,7 +202,7 @@ static void process_oob_msg(char *buf, int len, int nodeid)
|
||||
}
|
||||
}
|
||||
|
||||
int cluster_fd_callback(struct local_client *fd, 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];
|
||||
@@ -247,34 +246,39 @@ int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
len = -1;
|
||||
errno = EAGAIN;
|
||||
}
|
||||
memcpy(csid, &saddr.scl_nodeid, sizeof(saddr.scl_nodeid));
|
||||
else {
|
||||
memcpy(csid, &saddr.scl_nodeid, sizeof(saddr.scl_nodeid));
|
||||
/* Send it back to clvmd */
|
||||
process_message(client, buf, len, csid);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void add_up_node(char *csid)
|
||||
static void _add_up_node(char *csid)
|
||||
{
|
||||
/* It's up ! */
|
||||
int nodeid = nodeid_from_csid(csid);
|
||||
|
||||
if (nodeid >= max_updown_nodes) {
|
||||
int *new_updown = realloc(node_updown, max_updown_nodes + 10);
|
||||
int new_size = nodeid + 10;
|
||||
int *new_updown = realloc(node_updown, new_size);
|
||||
|
||||
if (new_updown) {
|
||||
node_updown = new_updown;
|
||||
max_updown_nodes += 10;
|
||||
max_updown_nodes = new_size;
|
||||
DEBUGLOG("realloced more space for nodes. now %d\n",
|
||||
max_updown_nodes);
|
||||
} else {
|
||||
log_error
|
||||
("Realloc failed. Node status for clvmd will be wrong\n");
|
||||
return;
|
||||
("Realloc failed. Node status for clvmd will be wrong. quitting\n");
|
||||
exit(999);
|
||||
}
|
||||
}
|
||||
node_updown[nodeid] = 1;
|
||||
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);
|
||||
@@ -303,7 +307,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;
|
||||
|
||||
@@ -319,7 +323,7 @@ static void get_members()
|
||||
|
||||
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
|
||||
if (num_nodes == -1) {
|
||||
perror("get nodes");
|
||||
log_error("Unable to get node count");
|
||||
} else {
|
||||
/* Not enough room for new nodes list ? */
|
||||
if (num_nodes > count_nodes && nodes) {
|
||||
@@ -331,16 +335,16 @@ static void get_members()
|
||||
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||
nodes = malloc(count_nodes * sizeof(struct cl_cluster_node));
|
||||
if (!nodes) {
|
||||
perror("Unable to allocate nodes array\n");
|
||||
log_error("Unable to allocate nodes array\n");
|
||||
exit(5);
|
||||
}
|
||||
}
|
||||
nodelist.max_members = count_nodes;
|
||||
nodelist.nodes = nodes;
|
||||
|
||||
|
||||
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
|
||||
if (num_nodes <= 0) {
|
||||
perror("get node details");
|
||||
log_error("Unable to get node details");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
@@ -362,13 +366,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;
|
||||
}
|
||||
}
|
||||
@@ -376,12 +380,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;
|
||||
}
|
||||
@@ -392,7 +396,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;
|
||||
|
||||
@@ -412,12 +416,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);
|
||||
}
|
||||
@@ -431,7 +435,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;
|
||||
@@ -441,6 +445,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
|
||||
/* Conversions need the lockid in the LKSB */
|
||||
if (flags & LKF_CONVERT)
|
||||
lwait.lksb.sb_lkid = *lockid;
|
||||
@@ -466,17 +471,20 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
*lockid = lwait.lksb.sb_lkid;
|
||||
|
||||
errno = lwait.lksb.sb_status;
|
||||
DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
|
||||
if (lwait.lksb.sb_status)
|
||||
return -1;
|
||||
else
|
||||
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;
|
||||
|
||||
DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
@@ -497,3 +505,28 @@ int sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_cman_ops = {
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.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;
|
||||
}
|
||||
|
@@ -66,6 +66,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "hash.h"
|
||||
#include "locking.h"
|
||||
#include "log.h"
|
||||
#include "lvm-functions.h"
|
||||
@@ -135,6 +136,61 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
|
||||
}
|
||||
|
||||
static int lock_vg(struct local_client *client)
|
||||
{
|
||||
struct hash_table *lock_hash;
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
int lkid;
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
|
||||
/* Keep a track of VG locks in our own hash table. In current
|
||||
practice there should only ever be more than two VGs locked
|
||||
if a user tries to merge lots of them at once */
|
||||
if (client->bits.localsock.private) {
|
||||
lock_hash = (struct hash_table *)client->bits.localsock.private;
|
||||
}
|
||||
else {
|
||||
lock_hash = hash_create(3);
|
||||
if (!lock_hash)
|
||||
return ENOMEM;
|
||||
client->bits.localsock.private = (void *)lock_hash;
|
||||
}
|
||||
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||
|
||||
if (lock_cmd == LCK_UNLOCK) {
|
||||
|
||||
lkid = (int)(long)hash_lookup(lock_hash, lockname);
|
||||
if (lkid == 0)
|
||||
return EINVAL;
|
||||
|
||||
status = sync_unlock(lockname, lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
hash_remove(lock_hash, lockname);
|
||||
}
|
||||
else {
|
||||
|
||||
status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
hash_insert(lock_hash, lockname, (void *)lkid);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Pre-command is a good place to get locks that are needed only for the duration
|
||||
of the commands around the cluster (don't forget to free them in post-command),
|
||||
and to sanity check the command arguments */
|
||||
@@ -156,20 +212,7 @@ int do_pre_command(struct local_client *client)
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
DEBUGLOG("doing PRE command LOCK_VG %s at %x\n", lockname,
|
||||
lock_cmd);
|
||||
if (lock_cmd == LCK_UNLOCK) {
|
||||
hold_unlock(lockname);
|
||||
} else {
|
||||
status =
|
||||
hold_lock(lockname, (int) lock_cmd,
|
||||
(int) lock_flags);
|
||||
if (status)
|
||||
status = errno;
|
||||
}
|
||||
status = lock_vg(client);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
@@ -202,6 +245,7 @@ int do_post_command(struct local_client *client)
|
||||
case CLVMD_CMD_TEST:
|
||||
status =
|
||||
sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
||||
client->bits.localsock.private = 0;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
@@ -217,3 +261,25 @@ int do_post_command(struct local_client *client)
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Called when the client is about to be deleted */
|
||||
void cmd_client_cleanup(struct local_client *client)
|
||||
{
|
||||
if (client->bits.localsock.private) {
|
||||
|
||||
struct hash_node *v;
|
||||
struct hash_table *lock_hash =
|
||||
(struct hash_table *)client->bits.localsock.private;
|
||||
|
||||
hash_iterate(v, lock_hash) {
|
||||
int lkid = (int)(long)hash_get_data(lock_hash, v);
|
||||
|
||||
DEBUGLOG("cleanup: Unlocking lkid %x\n", lkid);
|
||||
sync_unlock("DUMMY", lkid);
|
||||
}
|
||||
|
||||
hash_destroy(lock_hash);
|
||||
client->bits.localsock.private = 0;
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
@@ -72,7 +72,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 +88,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;
|
||||
@@ -123,7 +125,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,15 +137,34 @@ static void sighup_handler(int sig)
|
||||
get_all_cluster_nodes();
|
||||
}
|
||||
|
||||
int init_cluster()
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
int status;
|
||||
int ccs_h;
|
||||
int port = 0;
|
||||
char *portstr;
|
||||
|
||||
/* Get cluster name from CCS */
|
||||
/* TODO: is this right? */
|
||||
ccs_h = ccs_connect();
|
||||
ccs_h = ccs_force_connect(NULL, 0);
|
||||
if (ccs_h < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Cannot login in to CCSD server\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ccs_get(ccs_h, "//cluster/@name", &cluster_name);
|
||||
DEBUGLOG("got cluster name %s\n", cluster_name);
|
||||
|
||||
if (!ccs_get(ccs_h, "//cluster/clvm/@port", &portstr))
|
||||
{
|
||||
port = atoi(portstr);
|
||||
free(portstr);
|
||||
DEBUGLOG("got port number %d\n", port);
|
||||
|
||||
if (port <= 0 && port >= 65536)
|
||||
port = 0;
|
||||
}
|
||||
|
||||
ccs_disconnect(ccs_h);
|
||||
|
||||
/* Block locking until we are logged in */
|
||||
@@ -155,7 +176,8 @@ int init_cluster()
|
||||
lock_hash = hash_create(10);
|
||||
|
||||
/* Get all nodes from CCS */
|
||||
get_all_cluster_nodes();
|
||||
if (get_all_cluster_nodes())
|
||||
return -1;
|
||||
|
||||
/* Initialise GULM library */
|
||||
status = lg_initialize(&gulm_if, cluster_name, "clvmd");
|
||||
@@ -174,7 +196,7 @@ int init_cluster()
|
||||
}
|
||||
|
||||
/* Initialise the inter-node comms */
|
||||
status = init_comms();
|
||||
status = init_comms(port);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@@ -221,12 +243,11 @@ int init_cluster()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cluster_closedown()
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
lg_lock_logout(gulm_if);
|
||||
lg_core_logout(gulm_if);
|
||||
lg_core_shutdown(gulm_if);
|
||||
lg_release(gulm_if);
|
||||
}
|
||||
|
||||
@@ -316,11 +337,11 @@ static void set_node_state(struct node_info *ninfo, char *csid, uint8_t nodestat
|
||||
ninfo->name, ninfo->state, num_nodes);
|
||||
}
|
||||
|
||||
static struct node_info *add_or_set_node(char *name, uint32_t ip, uint8_t state)
|
||||
static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_t state)
|
||||
{
|
||||
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
|
||||
@@ -329,7 +350,7 @@ static struct node_info *add_or_set_node(char *name, uint32_t ip, uint8_t state)
|
||||
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);
|
||||
@@ -342,7 +363,12 @@ static struct node_info *add_or_set_node(char *name, uint32_t ip, uint8_t state)
|
||||
return ninfo;
|
||||
}
|
||||
|
||||
static int core_nodelist(void *misc, lglcb_t type, char *name, uint32_t ip, uint8_t state)
|
||||
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");
|
||||
|
||||
@@ -354,7 +380,7 @@ static int core_nodelist(void *misc, lglcb_t type, char *name, uint32_t ip, uint
|
||||
{
|
||||
if (type == lglcb_item)
|
||||
{
|
||||
DEBUGLOG("Got nodelist, item: %s, %#x, %#x\n", name, ip, state);
|
||||
DEBUGLOG("Got nodelist, item: %s, %#x\n", name, state);
|
||||
|
||||
add_or_set_node(name, ip, state);
|
||||
}
|
||||
@@ -362,14 +388,14 @@ static int core_nodelist(void *misc, lglcb_t type, char *name, uint32_t ip, uint
|
||||
{
|
||||
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
|
||||
{
|
||||
@@ -381,24 +407,24 @@ static int core_nodelist(void *misc, lglcb_t type, char *name, uint32_t ip, uint
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int core_statechange(void *misc, uint8_t corestate, uint32_t masterip, char *mastername)
|
||||
static int core_statechange(void *misc, uint8_t corestate, uint8_t quorate, struct in6_addr *masterip, char *mastername)
|
||||
{
|
||||
DEBUGLOG("CORE Got statechange corestate:%#x masterip:%#x mastername:%s\n",
|
||||
corestate, masterip, mastername);
|
||||
DEBUGLOG("CORE Got statechange corestate:%#x mastername:%s\n",
|
||||
corestate, mastername);
|
||||
|
||||
current_corestate = corestate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int core_nodechange(void *misc, char *nodename, uint32_t nodeip, uint8_t nodestate)
|
||||
static int core_nodechange(void *misc, char *nodename, struct in6_addr *nodeip, uint8_t nodestate)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
DEBUGLOG("CORE node change, name=%s, ip=%x, state = %d\n", nodename, nodeip, nodestate);
|
||||
DEBUGLOG("CORE node change, name=%s, state = %d\n", nodename, nodestate);
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -443,7 +469,9 @@ static int lock_login_reply(void *misc, uint32_t error, uint8_t which)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lock_lock_state(void *misc, uint8_t *key, uint16_t keylen, uint8_t state, uint32_t flags, uint32_t error,
|
||||
static int lock_lock_state(void *misc, uint8_t *key, uint16_t keylen,
|
||||
uint64_t subid, uint64_t start, uint64_t stop,
|
||||
uint8_t state, uint32_t flags, uint32_t error,
|
||||
uint8_t *LVB, uint16_t LVBlen)
|
||||
{
|
||||
struct lock_wait *lwait;
|
||||
@@ -519,19 +547,18 @@ 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 [%d.%d.%d.%d]",
|
||||
csid[0], csid[1], csid[2], csid[3]);
|
||||
sprintf(name, "UNKNOWN %s", print_csid(csid));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -540,7 +567,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;
|
||||
@@ -550,25 +577,25 @@ 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);
|
||||
ninfo = hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
return;
|
||||
|
||||
@@ -581,7 +608,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;
|
||||
|
||||
@@ -594,7 +621,7 @@ void add_down_node(char *csid)
|
||||
}
|
||||
|
||||
/* 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,
|
||||
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;
|
||||
@@ -602,15 +629,15 @@ int cluster_do_node_callback(struct local_client *master_client,
|
||||
|
||||
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);
|
||||
client = hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
if (client)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
}
|
||||
@@ -661,6 +688,7 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
||||
|
||||
status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
|
||||
0, 0, 0,
|
||||
mode, flags, NULL, 0);
|
||||
if (status)
|
||||
{
|
||||
@@ -692,6 +720,7 @@ static int _unlock_resource(char *resource, int lockid)
|
||||
|
||||
DEBUGLOG("unlock_resource %s\n", resource);
|
||||
status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
|
||||
0, 0, 0,
|
||||
lg_lock_state_Unlock, 0, NULL, 0);
|
||||
|
||||
if (status)
|
||||
@@ -720,7 +749,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];
|
||||
@@ -764,7 +793,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,7 +829,7 @@ int sync_unlock(const char *resource, int lockid)
|
||||
return status;
|
||||
}
|
||||
|
||||
int is_quorate()
|
||||
static int _is_quorate()
|
||||
{
|
||||
if (current_corestate == lg_core_Slave ||
|
||||
current_corestate == lg_core_Master ||
|
||||
@@ -819,31 +848,43 @@ static int get_all_cluster_nodes()
|
||||
int ctree;
|
||||
char *nodename;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
/* Open the config file */
|
||||
ctree = ccs_connect();
|
||||
if (ctree <= 0)
|
||||
ctree = ccs_force_connect(NULL, 1);
|
||||
if (ctree < 0)
|
||||
{
|
||||
log_error("Error connecting to CCS");
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = ccs_get(ctree, "//nodes/node/@name", &nodename);
|
||||
while (nodename)
|
||||
for (i=1;;i++)
|
||||
{
|
||||
char nodeip[MAX_CSID_LEN];
|
||||
char *clvmflag;
|
||||
char nodekey[256];
|
||||
char nodeip[GULM_MAX_CSID_LEN];
|
||||
int clvmflag = 1;
|
||||
char *clvmflagstr;
|
||||
char key[256];
|
||||
|
||||
sprintf(key, "//nodes/node[@name=\"%s\"]/clvm", nodename);
|
||||
ccs_get(ctree, key, &clvmflag);
|
||||
sprintf(nodekey, "//cluster/clusternodes/clusternode[%d]/@name", i);
|
||||
error = ccs_get(ctree, nodekey, &nodename);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
if ((get_ip_address(nodename, nodeip) == 0) && atoi(clvmflag))
|
||||
sprintf(key, "//cluster/clusternodes/clusternode[@name=\"%s\"]/clvm", nodename);
|
||||
if (!ccs_get(ctree, key, &clvmflagstr))
|
||||
{
|
||||
clvmflag = atoi(clvmflagstr);
|
||||
free(clvmflagstr);
|
||||
}
|
||||
|
||||
DEBUGLOG("Got node %s from ccs(clvmflag = %d)\n", nodename, clvmflag);
|
||||
if ((get_ip_address(nodename, nodeip) == 0) && clvmflag)
|
||||
{
|
||||
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));
|
||||
@@ -856,16 +897,14 @@ 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
|
||||
{
|
||||
DEBUGLOG("node %s has clvm disabled\n", nodename);
|
||||
}
|
||||
if (clvmflag) free(clvmflag);
|
||||
free(nodename);
|
||||
error = ccs_get(ctree, "//nodes/node/@name", &nodename);
|
||||
}
|
||||
|
||||
/* Finished with config file */
|
||||
@@ -874,7 +913,47 @@ static int get_all_cluster_nodes()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gulm_fd(void)
|
||||
static void _cluster_init_completed(void)
|
||||
{
|
||||
return lg_core_selector(gulm_if);
|
||||
clvmd_cluster_init_completed();
|
||||
}
|
||||
|
||||
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 = _cluster_init_completed,
|
||||
.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);
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvm.h"
|
||||
#include "version.h"
|
||||
#include "clvmd.h"
|
||||
#include "libdlm.h"
|
||||
#include "system-lv.h"
|
||||
@@ -54,9 +55,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 */
|
||||
@@ -64,7 +65,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,6 +88,14 @@ 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 int child_pipe[2];
|
||||
|
||||
/* Reasons the daemon failed initialisation */
|
||||
#define DFAIL_INIT 1
|
||||
#define DFAIL_LOCAL_SOCK 2
|
||||
#define DFAIL_CLUSTER_IF 3
|
||||
#define DFAIL_MALLOC 4
|
||||
#define SUCCESS 0
|
||||
|
||||
/* Prototypes for code further down */
|
||||
static void sigusr2_handler(int sig);
|
||||
@@ -129,6 +143,18 @@ static void usage(char *prog, FILE *file)
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
/* Called to signal the parent how well we got on during initialisation */
|
||||
static void child_init_signal(int status)
|
||||
{
|
||||
if (child_pipe[1]) {
|
||||
write(child_pipe[1], &status, sizeof(status));
|
||||
close(child_pipe[1]);
|
||||
}
|
||||
if (status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int local_sock;
|
||||
@@ -166,7 +192,8 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
printf("\nCluster LVM Daemon version %d.%d.%d\n\n",
|
||||
printf("Cluster LVM daemon version: %s\n", LVM_VERSION);
|
||||
printf("Protocol version: %d.%d.%d\n",
|
||||
CLVMD_MAJOR_VERSION, CLVMD_MINOR_VERSION,
|
||||
CLVMD_PATCH_VERSION);
|
||||
exit(1);
|
||||
@@ -188,14 +215,12 @@ int main(int argc, char *argv[])
|
||||
but the cluster is not ready yet */
|
||||
local_sock = open_local_sock();
|
||||
if (local_sock < 0)
|
||||
exit(2);
|
||||
child_init_signal(DFAIL_LOCAL_SOCK);
|
||||
|
||||
/* Set up signal handlers, USR1 is for cluster change notifications (in cman)
|
||||
USR2 causes child threads to exit.
|
||||
PIPE should be ignored */
|
||||
signal(SIGUSR2, sigusr2_handler);
|
||||
signal(SIGTERM, sigterm_handler);
|
||||
signal(SIGINT, sigterm_handler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/* Block SIGUSR2 in the main process */
|
||||
@@ -210,26 +235,42 @@ 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;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!clops) {
|
||||
DEBUGLOG("Can't initialise cluster interface\n");
|
||||
log_error("Can't initialise cluster interface\n");
|
||||
exit(5);
|
||||
child_init_signal(DFAIL_CLUSTER_IF);
|
||||
}
|
||||
DEBUGLOG("Cluster ready, doing some more initialisation\n");
|
||||
|
||||
/* 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));
|
||||
if (!newfd)
|
||||
exit(2);
|
||||
child_init_signal(DFAIL_MALLOC);
|
||||
|
||||
newfd->fd = local_sock;
|
||||
newfd->type = LOCAL_RENDEZVOUS;
|
||||
@@ -242,15 +283,19 @@ int main(int argc, char *argv[])
|
||||
DEBUGLOG("starting LVM thread\n");
|
||||
pthread_create(&lvm_thread, NULL, lvm_thread_fn, nodeinfo.nodename);
|
||||
|
||||
#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);
|
||||
|
||||
/* Try to shutdown neatly */
|
||||
signal(SIGTERM, sigterm_handler);
|
||||
signal(SIGINT, sigterm_handler);
|
||||
|
||||
/* Do some work */
|
||||
main_loop(local_sock, cmd_timeout);
|
||||
@@ -303,6 +348,7 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
|
||||
newfd->bits.localsock.threadid = 0;
|
||||
newfd->bits.localsock.finished = 0;
|
||||
newfd->bits.localsock.pipe_client = NULL;
|
||||
newfd->bits.localsock.private = NULL;
|
||||
newfd->bits.localsock.all_success = 1;
|
||||
DEBUGLOG("Got new connection on fd %d\n", newfd->fd);
|
||||
*new_client = newfd;
|
||||
@@ -391,9 +437,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);
|
||||
|
||||
@@ -422,7 +468,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) {
|
||||
@@ -447,7 +493,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);
|
||||
@@ -461,9 +507,8 @@ 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;
|
||||
struct clvm_header *inheader;
|
||||
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) {
|
||||
@@ -490,12 +535,12 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
type == CLUSTER_INTERNAL)
|
||||
goto closedown;
|
||||
|
||||
DEBUGLOG
|
||||
("ret == %d, errno = %d. removing client\n",
|
||||
ret, errno);
|
||||
DEBUGLOG("ret == %d, errno = %d. removing client\n",
|
||||
ret, errno);
|
||||
lastfd->next = thisfd->next;
|
||||
free_fd = thisfd;
|
||||
thisfd = lastfd;
|
||||
cmd_client_cleanup(free_fd);
|
||||
free(free_fd);
|
||||
break;
|
||||
}
|
||||
@@ -506,33 +551,6 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
thisfd->next = newfd;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (thisfd->type) {
|
||||
case CLUSTER_MAIN_SOCK:
|
||||
case CLUSTER_DATA_SOCK:
|
||||
inheader =
|
||||
(struct clvm_header *) buf;
|
||||
ntoh_clvm(inheader); /* Byteswap fields */
|
||||
if (inheader->cmd ==
|
||||
CLVMD_CMD_REPLY)
|
||||
process_reply
|
||||
(inheader, ret,
|
||||
csid);
|
||||
else
|
||||
add_to_lvmqueue(thisfd,
|
||||
inheader,
|
||||
ret,
|
||||
csid);
|
||||
break;
|
||||
|
||||
/* All the work for these is done in the callback
|
||||
rightly or wrongly... */
|
||||
case LOCAL_RENDEZVOUS:
|
||||
case LOCAL_SOCK:
|
||||
case THREAD_PIPE:
|
||||
case CLUSTER_INTERNAL:
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastfd = thisfd;
|
||||
}
|
||||
@@ -575,30 +593,69 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
}
|
||||
|
||||
closedown:
|
||||
cluster_closedown();
|
||||
clops->cluster_closedown();
|
||||
close(local_sock);
|
||||
}
|
||||
|
||||
/* Fork into the background and detach from our parent process */
|
||||
/*
|
||||
* Fork into the background and detach from our parent process.
|
||||
* In the interests of user-friendliness we wait for the daemon
|
||||
* to complete initialisation before returning its status
|
||||
* the the user.
|
||||
*/
|
||||
static void be_daemon()
|
||||
{
|
||||
pid_t pid;
|
||||
pid_t pid;
|
||||
int child_status;
|
||||
int devnull = open("/dev/null", O_RDWR);
|
||||
if (devnull == -1) {
|
||||
perror("Can't open /dev/null");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
pipe(child_pipe);
|
||||
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
perror("clvmd: can't fork");
|
||||
exit(2);
|
||||
|
||||
case 0: /* child */
|
||||
case 0: /* Child */
|
||||
close(child_pipe[0]);
|
||||
break;
|
||||
|
||||
default: /* Parent */
|
||||
exit(0);
|
||||
default: /* Parent */
|
||||
close(child_pipe[1]);
|
||||
if (read(child_pipe[0], &child_status, sizeof(child_status)) !=
|
||||
sizeof(child_status)) {
|
||||
|
||||
fprintf(stderr, "clvmd failed in initialisation\n");
|
||||
exit(DFAIL_INIT);
|
||||
}
|
||||
else {
|
||||
switch (child_status) {
|
||||
case SUCCESS:
|
||||
break;
|
||||
case DFAIL_INIT:
|
||||
fprintf(stderr, "clvmd failed in initialisation\n");
|
||||
break;
|
||||
case DFAIL_LOCAL_SOCK:
|
||||
fprintf(stderr, "clvmd could not create local socket\n");
|
||||
fprintf(stderr, "Another clvmd is probably already running\n");
|
||||
break;
|
||||
case DFAIL_CLUSTER_IF:
|
||||
fprintf(stderr, "clvmd could not connect to cluster manager\n");
|
||||
fprintf(stderr, "Consult syslog for more information\n");
|
||||
break;
|
||||
case DFAIL_MALLOC:
|
||||
fprintf(stderr, "clvmd failed, not enough memory\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "clvmd failed, error was %d\n", child_status);
|
||||
break;
|
||||
}
|
||||
exit(child_status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Detach ourself from the calling environment */
|
||||
@@ -717,6 +774,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
struct local_client *newfd;
|
||||
char csid[MAX_CSID_LEN];
|
||||
struct clvm_header *inheader;
|
||||
int status;
|
||||
|
||||
inheader = (struct clvm_header *) buffer;
|
||||
|
||||
@@ -791,7 +849,7 @@ 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);
|
||||
@@ -863,8 +921,10 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
/* Run the pre routine */
|
||||
thisfd->bits.localsock.in_progress = TRUE;
|
||||
thisfd->bits.localsock.state = PRE_COMMAND;
|
||||
pthread_create(&thisfd->bits.localsock.threadid, NULL,
|
||||
DEBUGLOG("Creating pre&post thread\n");
|
||||
status = pthread_create(&thisfd->bits.localsock.threadid, NULL,
|
||||
pre_and_post_thread, thisfd);
|
||||
DEBUGLOG("Created pre&post thread, state = %d\n", status);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@@ -921,7 +981,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;
|
||||
@@ -942,7 +1002,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 {
|
||||
@@ -952,7 +1012,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 {
|
||||
@@ -984,14 +1044,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);
|
||||
@@ -1057,7 +1117,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]),
|
||||
@@ -1078,17 +1138,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 */
|
||||
@@ -1188,7 +1248,7 @@ 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) {
|
||||
@@ -1273,6 +1333,7 @@ static void *pre_and_post_thread(void *arg)
|
||||
|
||||
DEBUGLOG("Got post command condition...\n");
|
||||
|
||||
status = 0;
|
||||
do_post_command(client);
|
||||
|
||||
write(pipe_fd, &status, sizeof(int));
|
||||
@@ -1292,7 +1353,8 @@ static void *pre_and_post_thread(void *arg)
|
||||
DEBUGLOG("Got pre command condition...\n");
|
||||
}
|
||||
DEBUGLOG("Subthread finished\n");
|
||||
return (void *) 0;
|
||||
pthread_exit((void *) 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Process a command on the local node and store the result */
|
||||
@@ -1300,8 +1362,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;
|
||||
|
||||
@@ -1465,7 +1527,7 @@ 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,
|
||||
clops->cluster_send_message(message, sizeof(message), NULL,
|
||||
"Error Sending version number");
|
||||
}
|
||||
|
||||
@@ -1478,7 +1540,7 @@ 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);
|
||||
return clops->cluster_send_message(buf, msglen, csid, errtext);
|
||||
} else {
|
||||
int ptr = 0;
|
||||
|
||||
@@ -1579,7 +1641,7 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
|
||||
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;
|
||||
@@ -1630,6 +1692,19 @@ static int open_local_sock()
|
||||
return local_socket;
|
||||
}
|
||||
|
||||
void process_message(struct local_client *client, char *buf, int len, char *csid)
|
||||
{
|
||||
struct clvm_header *inheader;
|
||||
|
||||
inheader = (struct clvm_header *) buf;
|
||||
ntoh_clvm(inheader); /* Byteswap fields */
|
||||
if (inheader->cmd == CLVMD_CMD_REPLY)
|
||||
process_reply(inheader, len, csid);
|
||||
else
|
||||
add_to_lvmqueue(client, inheader, len, csid);
|
||||
}
|
||||
|
||||
|
||||
static void check_all_callback(struct local_client *client, char *csid,
|
||||
int node_up)
|
||||
{
|
||||
@@ -1644,7 +1719,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.
|
||||
@@ -1681,7 +1756,6 @@ static void ntoh_clvm(struct clvm_header *hdr)
|
||||
static void sigusr2_handler(int sig)
|
||||
{
|
||||
DEBUGLOG("SIGUSR2 received\n");
|
||||
pthread_exit((void *) -1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1691,3 +1765,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);
|
||||
}
|
||||
|
||||
|
@@ -93,7 +93,7 @@ struct local_client {
|
||||
struct netsock_bits net;
|
||||
} bits;
|
||||
};
|
||||
|
||||
#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DEBUGLOG(fmt, args...) fprintf(stderr, "CLVMD[%d]: %ld ", getpid(), time(NULL) ); fprintf(stderr, fmt, ## args)
|
||||
#else
|
||||
@@ -111,9 +111,13 @@ extern int do_command(struct local_client *client, struct clvm_header *msg,
|
||||
/* Pre and post command routines are called only on the local node */
|
||||
extern int do_pre_command(struct local_client *client);
|
||||
extern int do_post_command(struct local_client *client);
|
||||
|
||||
extern void cmd_client_cleanup(struct local_client *client);
|
||||
extern int add_client(struct local_client *new_client);
|
||||
|
||||
extern void clvmd_cluster_init_completed(void);
|
||||
extern void process_message(struct local_client *client, char *buf, int len, char *csid);
|
||||
|
||||
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
|
||||
@@ -105,6 +105,7 @@
|
||||
#define MSG_MULTICAST 0x080000 /* Message was sent to all nodes in the cluster
|
||||
*/
|
||||
#define MSG_ALLINT 0x100000 /* Send out of all interfaces */
|
||||
#define MSG_REPLYEXP 0x200000 /* Reply is expected */
|
||||
|
||||
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
|
||||
NODESTATE_DEAD } nodestate_t;
|
||||
@@ -146,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;
|
||||
};
|
||||
|
||||
|
@@ -46,6 +46,7 @@
|
||||
|
||||
static struct cmd_context *cmd = NULL;
|
||||
static struct hash_table *lv_hash = NULL;
|
||||
static pthread_mutex_t lv_hash_lock;
|
||||
|
||||
struct lv_info {
|
||||
int lock_id;
|
||||
@@ -57,7 +58,9 @@ static int get_current_lock(char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (lvi) {
|
||||
return lvi->lock_mode;
|
||||
} else {
|
||||
@@ -69,11 +72,14 @@ static int get_current_lock(char *resource)
|
||||
void unlock_all()
|
||||
{
|
||||
struct hash_node *v;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
hash_iterate(v, lv_hash) {
|
||||
struct lv_info *lvi = hash_get_data(lv_hash, v);
|
||||
|
||||
sync_unlock(hash_get_key(lv_hash, v), lvi->lock_id);
|
||||
}
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
/* Gets a real lock and keeps the info in the hash table */
|
||||
@@ -85,7 +91,9 @@ int hold_lock(char *resource, int mode, int flags)
|
||||
|
||||
flags &= LKF_NOQUEUE; /* Only LKF_NOQUEUE is valid here */
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (lvi) {
|
||||
/* Already exists - convert it */
|
||||
status =
|
||||
@@ -113,7 +121,9 @@ int hold_lock(char *resource, int mode, int flags)
|
||||
DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
|
||||
strerror(errno));
|
||||
} else {
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
hash_insert(lv_hash, resource, lvi);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
errno = saved_errno;
|
||||
}
|
||||
@@ -127,8 +137,9 @@ int hold_unlock(char *resource)
|
||||
int status;
|
||||
int saved_errno;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = hash_lookup(lv_hash, resource);
|
||||
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (!lvi) {
|
||||
DEBUGLOG("hold_unlock, lock not already held\n");
|
||||
return 0;
|
||||
@@ -137,7 +148,9 @@ int hold_unlock(char *resource)
|
||||
status = sync_unlock(resource, lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status) {
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
hash_remove(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
free(lvi);
|
||||
} else {
|
||||
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
|
||||
@@ -185,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)
|
||||
@@ -231,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) {
|
||||
@@ -350,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) {
|
||||
@@ -394,9 +407,11 @@ static void *get_initial_state()
|
||||
return NULL;
|
||||
|
||||
while (fgets(line, sizeof(line), lvs)) {
|
||||
if (sscanf(line, "%s %s %s\n", vg, lv, flags) == 3) {
|
||||
if (sscanf(line, "%s %s %s\n", vg, lv, flags) == 3) {
|
||||
|
||||
/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
|
||||
if (flags[4] == 'a' || flags[4] == 's') { /* is it active or suspended? */
|
||||
if (strlen(vg) == 38 && /* is is a valid UUID ? */
|
||||
(flags[4] == 'a' || flags[4] == 's')) { /* is it active or suspended? */
|
||||
/* Convert hyphen-separated UUIDs into one */
|
||||
memcpy(&uuid[0], &vg[0], 6);
|
||||
memcpy(&uuid[6], &vg[7], 4);
|
||||
@@ -427,6 +442,7 @@ void init_lvhash()
|
||||
{
|
||||
/* Create hash table for keeping LV locks & status */
|
||||
lv_hash = hash_create(100);
|
||||
pthread_mutex_init(&lv_hash_lock, NULL);
|
||||
}
|
||||
|
||||
/* Called to initialise the LVM context of the daemon */
|
||||
|
@@ -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
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#include <netdb.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ccs.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvmd.h"
|
||||
@@ -47,43 +46,19 @@ static int listen_fd = -1;
|
||||
static int tcp_port;
|
||||
struct hash_table *sock_hash;
|
||||
|
||||
static int get_tcp_port(int default_port);
|
||||
static int get_our_ip_address(char *addr, int *family);
|
||||
static int read_from_tcpsock(struct local_client *fd, char *buf, int len, char *csid,
|
||||
struct local_client **new_client);
|
||||
|
||||
/* Called by init_cluster() to open up the listening socket */
|
||||
// TODO: IPv6 compat.
|
||||
int init_comms()
|
||||
int init_comms(unsigned short port)
|
||||
{
|
||||
struct sockaddr *addr = NULL;
|
||||
struct sockaddr_in addr4;
|
||||
struct sockaddr_in6 addr6;
|
||||
int addr_len;
|
||||
int family;
|
||||
char address[MAX_CSID_LEN];
|
||||
struct sockaddr_in6 addr;
|
||||
|
||||
sock_hash = hash_create(100);
|
||||
tcp_port = get_tcp_port(DEFAULT_TCP_PORT);
|
||||
tcp_port = port ? port : DEFAULT_TCP_PORT;
|
||||
|
||||
/* Get IP address and IP type */
|
||||
get_our_ip_address(address, &family);
|
||||
if (family == AF_INET)
|
||||
{
|
||||
memcpy(&addr4.sin_addr, addr, sizeof(struct in_addr));
|
||||
addr = (struct sockaddr *)&addr4;
|
||||
addr4.sin_port = htons(tcp_port);
|
||||
addr_len = sizeof(addr4);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&addr6.sin6_addr, addr, sizeof(struct in6_addr));
|
||||
addr = (struct sockaddr *)&addr6;
|
||||
addr6.sin6_port = htons(tcp_port);
|
||||
addr_len = sizeof(addr6);
|
||||
}
|
||||
|
||||
listen_fd = socket(family, SOCK_STREAM, 0);
|
||||
listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
|
||||
if (listen_fd < 0)
|
||||
{
|
||||
@@ -95,11 +70,13 @@ int init_comms()
|
||||
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
|
||||
}
|
||||
|
||||
addr->sa_family = family;
|
||||
memset(&addr, 0, sizeof(addr)); // Bind to INADDR_ANY
|
||||
addr.sin6_family = AF_INET6;
|
||||
addr.sin6_port = htons(tcp_port);
|
||||
|
||||
if (bind(listen_fd, addr, addr_len) < 0)
|
||||
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
DEBUGLOG("Can't bind to port\n");
|
||||
DEBUGLOG("Can't bind to port: %s\n", strerror(errno));
|
||||
syslog(LOG_ERR, "Can't bind to port %d, is clvmd already running ?", tcp_port);
|
||||
close(listen_fd);
|
||||
return -1;
|
||||
@@ -119,19 +96,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 */
|
||||
@@ -142,7 +119,7 @@ int alloc_client(int fd, char *csid, struct local_client **new_client)
|
||||
{
|
||||
struct local_client *client;
|
||||
|
||||
DEBUGLOG("alloc_client %d csid = [%d.%d.%d.%d]\n", fd,csid[0],csid[1],csid[2],csid[3]);
|
||||
DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid));
|
||||
|
||||
/* Create a local_client and return it */
|
||||
client = malloc(sizeof(struct local_client));
|
||||
@@ -160,7 +137,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
|
||||
@@ -173,7 +150,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]);
|
||||
@@ -183,26 +160,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_in addr;
|
||||
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;
|
||||
@@ -218,22 +195,20 @@ 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.
|
||||
// FIXME: IPv4 specific
|
||||
*/
|
||||
if (name_from_csid((char *)&addr.sin_addr.s_addr, name) < 0)
|
||||
if (gulm_name_from_csid((char *)&addr.sin6_addr, name) < 0)
|
||||
{
|
||||
char *ip = (char *)&addr.sin_addr.s_addr;
|
||||
syslog(LOG_ERR, "Got connect from non-cluster node %d.%d.%d.%d\n",
|
||||
ip[0], ip[1], ip[2], ip[3]);
|
||||
DEBUGLOG("Got connect from non-cluster node %d.%d.%d.%d\n",
|
||||
ip[0], ip[1], ip[2], ip[3]);
|
||||
syslog(LOG_ERR, "Got connect from non-cluster node %s\n",
|
||||
print_csid((char *)&addr.sin6_addr));
|
||||
DEBUGLOG("Got connect from non-cluster node %s\n",
|
||||
print_csid((char *)&addr.sin6_addr));
|
||||
close(newfd);
|
||||
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = alloc_client(newfd, (char *)&addr.sin_addr.s_addr, new_client);
|
||||
status = alloc_client(newfd, (char *)&addr.sin6_addr, new_client);
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("cluster_fd_callback, alloc_client failed, status = %d\n", status);
|
||||
@@ -250,7 +225,7 @@ int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
static int read_from_tcpsock(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr_in6 addr;
|
||||
socklen_t slen = sizeof(addr);
|
||||
int status;
|
||||
|
||||
@@ -259,7 +234,7 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
|
||||
|
||||
/* Get "csid" */
|
||||
getpeername(client->fd, (struct sockaddr *)&addr, &slen);
|
||||
memcpy(csid, &addr.sin_addr.s_addr, MAX_CSID_LEN);
|
||||
memcpy(csid, &addr.sin6_addr, GULM_MAX_CSID_LEN);
|
||||
|
||||
status = read(client->fd, buf, len);
|
||||
|
||||
@@ -270,30 +245,34 @@ 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 {
|
||||
/* Send it back to clvmd */
|
||||
process_message(client, buf, len, csid);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int connect_csid(char *csid, struct local_client **newclient)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr_in6 addr;
|
||||
int status;
|
||||
|
||||
DEBUGLOG("Connecting socket\n");
|
||||
fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
fd = socket(PF_INET6, SOCK_STREAM, 0);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
@@ -301,12 +280,12 @@ static int connect_csid(char *csid, struct local_client **newclient)
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
memcpy(&addr.sin_addr.s_addr, csid, MAX_CSID_LEN);
|
||||
addr.sin_port = htons(tcp_port);
|
||||
addr.sin6_family = AF_INET6;
|
||||
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_in)) < 0)
|
||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Unable to connect to remote node: %m");
|
||||
DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno));
|
||||
@@ -321,7 +300,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;
|
||||
}
|
||||
|
||||
@@ -330,18 +309,18 @@ 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 = [%d.%d.%d.%d], msglen = %d\n", csid[0],csid[1],csid[2],csid[3], msglen);
|
||||
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);
|
||||
@@ -354,7 +333,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;
|
||||
|
||||
@@ -364,7 +343,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))
|
||||
@@ -383,62 +362,24 @@ int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
return status;
|
||||
}
|
||||
|
||||
static int get_tcp_port(int default_port)
|
||||
{
|
||||
int ccs_handle;
|
||||
int port = default_port;
|
||||
char *portstr;
|
||||
|
||||
ccs_handle = ccs_connect();
|
||||
if (ccs_handle)
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
if (!ccs_get(ccs_handle, "//clvm/@port", &portstr))
|
||||
{
|
||||
port = atoi(portstr);
|
||||
free(portstr);
|
||||
|
||||
if (port <= 0 && port >= 65536)
|
||||
port = default_port;
|
||||
}
|
||||
ccs_disconnect(ccs_handle);
|
||||
|
||||
DEBUGLOG("Using port %d for communications\n", port);
|
||||
return port;
|
||||
}
|
||||
|
||||
/* To get our own IP address we get the locally bound address of the
|
||||
socket that's talking to GULM in the assumption(eek) that it will
|
||||
be on the "right" network in a multi-homed system */
|
||||
static int get_our_ip_address(char *addr, int *family)
|
||||
{
|
||||
/* Use a sockaddr_in6 to make sure it's big enough */
|
||||
struct sockaddr_in6 saddr;
|
||||
int socklen = sizeof(saddr);
|
||||
struct utsname info;
|
||||
|
||||
uname(&info);
|
||||
get_ip_address(info.nodename, addr);
|
||||
|
||||
if (!getsockname(gulm_fd(), (struct sockaddr *)&saddr, &socklen))
|
||||
{
|
||||
if (saddr.sin6_family == AF_INET6)
|
||||
{
|
||||
memcpy(addr, &saddr.sin6_addr, sizeof(saddr.sin6_addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in *sin4 = (struct sockaddr_in *)&saddr;
|
||||
memcpy(addr, &sin4->sin_addr, sizeof(sin4->sin_addr));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
@@ -451,7 +392,15 @@ 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)
|
||||
{
|
||||
ip6->s6_addr32[0] = 0;
|
||||
ip6->s6_addr32[1] = 0;
|
||||
ip6->s6_addr32[2] = htonl(0xffff);
|
||||
ip6->s6_addr32[3] = ip4->s_addr;
|
||||
}
|
||||
|
||||
/* Get someone else's IP address from DNS */
|
||||
@@ -459,7 +408,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.
|
||||
@@ -467,14 +416,29 @@ int get_ip_address(char *node, char *addr)
|
||||
/* Try IPv6 first. The man page for gethostbyname implies that
|
||||
it will lookup ip6 & ip4 names, but it seems not to */
|
||||
he = gethostbyname2(node, AF_INET6);
|
||||
if (!he)
|
||||
if (he)
|
||||
{
|
||||
memcpy(addr, he->h_addr_list[0],
|
||||
he->h_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
he = gethostbyname2(node, AF_INET);
|
||||
if (!he)
|
||||
return -1;
|
||||
|
||||
/* For IPv4 address just use the lower 4 bytes */
|
||||
memcpy(&addr, he->h_addr_list[0],
|
||||
he->h_length);
|
||||
if (!he)
|
||||
return -1;
|
||||
map_v4_to_v6((struct in_addr *)he->h_addr_list[0], (struct in6_addr *)addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *print_csid(char *csid)
|
||||
{
|
||||
static char buf[128];
|
||||
int *icsid = (int *)csid;
|
||||
|
||||
sprintf(buf, "[%x.%x.%x.%x]",
|
||||
icsid[0],icsid[1],icsid[2],icsid[3]);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@@ -1,7 +1,12 @@
|
||||
#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(void);
|
||||
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);
|
||||
|
@@ -27,6 +27,12 @@ devices {
|
||||
# the device will be accepted or rejected (ignored). Devices that
|
||||
# don't match any patterns are accepted.
|
||||
|
||||
# Be careful if there there are symbolic links or multiple filesystem
|
||||
# entries for the same device as each name is checked separately against
|
||||
# the list of patterns. The effect is that if any name matches any 'a'
|
||||
# pattern, the device is accepted; otherwise if any name matches any 'r'
|
||||
# pattern it is rejected; otherwise it is accepted.
|
||||
|
||||
# Remember to run vgscan after you change this parameter to ensure
|
||||
# that the cache file gets regenerated (see below).
|
||||
|
||||
|
165
doc/tagging.txt
Normal file
165
doc/tagging.txt
Normal file
@@ -0,0 +1,165 @@
|
||||
Tagging aims
|
||||
============
|
||||
1) Ability to attach an unordered list of tags to LVM metadata objects.
|
||||
2) Ability to add or remove tags easily.
|
||||
3) Ability to select LVM objects for processing according to presence/absence
|
||||
of specific tags.
|
||||
4) Ability to control through the config file which VGs/LVs are activated
|
||||
on different machines using names or tags.
|
||||
5) Ability to overlay settings from different config files e.g. override
|
||||
some settings in a global config file locally.
|
||||
|
||||
Clarifications
|
||||
==============
|
||||
1) Tag character set: A-Za-z0-9_+.-
|
||||
Can't start with hyphen & max length is 128 (NAME_LEN).
|
||||
2) LVM object types that can be tagged:
|
||||
VG, LV, LV segment
|
||||
PV - tags are stored in VG metadata so disappear when PV becomes orphaned
|
||||
Snapshots can't be tagged, but their origin may be.
|
||||
3) A tag can be used in place of any command line LVM object reference that
|
||||
accepts (a) a list of objects; or (b) a single object as long as the
|
||||
tag expands to a single object. This is not supported everywhere yet.
|
||||
Duplicate arguments in a list after argument expansion may get removed
|
||||
retaining the first copy of each argument.
|
||||
4) Wherever there may be ambiguity of argument type, a tag must be prefixed
|
||||
by '@'; elsewhere an '@' prefix is optional.
|
||||
5) LVM1 objects cannot be tagged, as the disk format doesn't support it.
|
||||
6) Tags can be added or removed with --addtag or --deltag.
|
||||
|
||||
Config file Extensions
|
||||
======================
|
||||
To define host tags in config file:
|
||||
|
||||
tags {
|
||||
# Set a tag with the hostname
|
||||
hosttags = 1
|
||||
|
||||
tag1 { }
|
||||
|
||||
tag2 {
|
||||
# If no exact match, tag is not set.
|
||||
host_list = [ "hostname", "dbase" ]
|
||||
}
|
||||
}
|
||||
|
||||
Activation config file example
|
||||
==============================
|
||||
activation {
|
||||
volume_list = [ "vg1/lvol0", "@database" ]
|
||||
}
|
||||
|
||||
Matches against vgname, vgname/lvname or @tag set in *metadata*.
|
||||
@* matches exactly against *any* tag set on the host.
|
||||
The VG or LV only gets activated if a metadata tag matches.
|
||||
The default if there is no match is not to activate.
|
||||
If volume_list is not present and any tags are defined on the host
|
||||
then it only activates if a host tag matches a metadata tag.
|
||||
If volume_list is not present and no tags are defined on the host
|
||||
then it does activate.
|
||||
|
||||
Multiple config files
|
||||
=====================
|
||||
(a) lvm.conf
|
||||
(b) lvm_<host_tag>.conf
|
||||
|
||||
At startup, load lvm.conf.
|
||||
Process tag settings.
|
||||
If any host tags were defined, load lvm_tag.conf for each tag, if present.
|
||||
|
||||
When searching for a specific config file entry, search order is (b)
|
||||
then (a), stopping at the first match.
|
||||
Within (b) use reverse order tags got set, so file for last tag set is
|
||||
searched first.
|
||||
New tags set in (b) *do* trigger additional config file loads.
|
||||
|
||||
Usage Examples
|
||||
==============
|
||||
1) Simple activation control via metadata with static config files
|
||||
|
||||
lvm.conf: (Identical on every machine - global settings)
|
||||
tags {
|
||||
hostname_tags = 1
|
||||
}
|
||||
|
||||
From any machine in the cluster, add db1 to the list of machines that
|
||||
activate vg1/lvol2:
|
||||
|
||||
lvchange --tag @db1 vg1/lvol2
|
||||
(followed by lvchange -ay to actually activate it)
|
||||
|
||||
|
||||
2) Multiple hosts.
|
||||
|
||||
Activate vg1 only on the database hosts, db1 and db2.
|
||||
Activate vg2 only on the fileserver host fs1.
|
||||
Activate nothing initially on the fileserver backup host fsb1, but be
|
||||
prepared for it to take over from fs1.
|
||||
|
||||
Option (i) - centralised admin, static configuration replicated between hosts
|
||||
# Add @database tag to vg1's metadata
|
||||
vgchange --tag @database vg1
|
||||
|
||||
# Add @fileserver tag to vg2's metadata
|
||||
vgchange --tag @fileserver vg2
|
||||
|
||||
lvm.conf: (Identical on every machine)
|
||||
tags {
|
||||
database {
|
||||
host_list = [ "db1", "db2" ]
|
||||
}
|
||||
fileserver {
|
||||
host_list = [ "fs1" ]
|
||||
}
|
||||
fileserverbackup {
|
||||
host_list = [ "fsb1" ]
|
||||
}
|
||||
}
|
||||
|
||||
activation {
|
||||
# Only activate if host has a tag that matches a metadata tag
|
||||
volume_list = [ "@*" ]
|
||||
}
|
||||
|
||||
In the event of the fileserver host going down, vg2 can be brought up
|
||||
on fsb1 by running *on any node* 'vgchange --tag @fileserverbackup vg2'
|
||||
followed by 'vgchange -ay vg2'
|
||||
|
||||
|
||||
Option (ii) - localised admin & configuation
|
||||
(i.e. each host holds *locally* which classes of volumes to activate)
|
||||
# Add @database tag to vg1's metadata
|
||||
vgchange --tag @database vg1
|
||||
|
||||
# Add @fileserver tag to vg2's metadata
|
||||
vgchange --tag @fileserver vg2
|
||||
|
||||
lvm.conf: (Identical on every machine - global settings)
|
||||
tags {
|
||||
hosttags = 1
|
||||
}
|
||||
|
||||
lvm_db1.conf: (only needs to be on db1 - could be symlink to lvm_db.conf)
|
||||
activation {
|
||||
volume_list = [ "@database" ]
|
||||
}
|
||||
|
||||
lvm_db2.conf: (only needs to be on db2 - could be symlink to lvm_db.conf)
|
||||
activation {
|
||||
volume_list = [ "@database" ]
|
||||
}
|
||||
|
||||
lvm_fs1.conf: (only needs to be on fs1 - could be symlink to lvm_fs.conf)
|
||||
activation {
|
||||
volume_list = [ "@fileserver" ]
|
||||
}
|
||||
|
||||
If fileserver goes down, to bring a spare machine fsb1 in as fileserver,
|
||||
create lvm_fsb1.conf on fsb1 (or symlink to lvm_fs.conf):
|
||||
|
||||
activation {
|
||||
volume_list = [ "@fileserver" ]
|
||||
}
|
||||
|
||||
and run 'vgchange -ay vg2' or 'vgchange -ay @fileserver'
|
||||
|
@@ -47,3 +47,4 @@
|
||||
../lib/report/report.h
|
||||
../lib/uuid/uuid.h
|
||||
../po/pogen.h
|
||||
../tools/version.h
|
||||
|
@@ -43,6 +43,7 @@ SOURCES =\
|
||||
datastruct/str_list.c \
|
||||
device/dev-cache.c \
|
||||
device/dev-io.c \
|
||||
device/dev-md.c \
|
||||
device/device.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
@@ -75,6 +76,7 @@ SOURCES =\
|
||||
misc/crc.c \
|
||||
misc/lvm-file.c \
|
||||
misc/lvm-string.c \
|
||||
mm/dbg_malloc.c \
|
||||
mm/memlock.c \
|
||||
mm/pool.c \
|
||||
regex/matcher.c \
|
||||
@@ -120,10 +122,6 @@ ifeq ("@MIRRORS@", "internal")
|
||||
SOURCES += mirror/mirrored.c
|
||||
endif
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
SOURCES += mm/dbg_malloc.c
|
||||
endif
|
||||
|
||||
ifeq ("@DEVMAPPER@", "yes")
|
||||
SOURCES +=\
|
||||
activate/dev_manager.c \
|
||||
|
@@ -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;
|
||||
}
|
||||
@@ -919,7 +946,7 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||
struct pool *mem;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(mem = pool_create(16 * 1024))) {
|
||||
if (!(mem = pool_create("dev_manager", 16 * 1024))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -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,10 +65,10 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Removing directory %s", vg_path);
|
||||
|
||||
if (is_empty_dir(vg_path))
|
||||
if (is_empty_dir(vg_path)) {
|
||||
log_very_verbose("Removing directory %s", vg_path);
|
||||
rmdir(vg_path);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -202,9 +202,9 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
|
||||
}
|
||||
|
||||
if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
|
||||
if (errno != ENOENT)
|
||||
log_error("%s not symbolic link - not removing",
|
||||
lv_path);
|
||||
if (errno == ENOENT)
|
||||
return 1;
|
||||
log_error("%s not symbolic link - not removing", lv_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -519,8 +519,8 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
||||
|
||||
/* regex filter. Optional. */
|
||||
if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
|
||||
log_debug("devices/filter not found in config file: no regex "
|
||||
"filter installed");
|
||||
log_very_verbose("devices/filter not found in config file: "
|
||||
"no regex filter installed");
|
||||
|
||||
else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) {
|
||||
log_error("Failed to create regex device filter");
|
||||
@@ -537,6 +537,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
||||
/* md component filter. Optional, non-critical. */
|
||||
if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
|
||||
DEFAULT_MD_COMPONENT_DETECTION)) {
|
||||
init_md_filtering(1);
|
||||
if ((filters[nr_filt] = md_filter_create()))
|
||||
nr_filt++;
|
||||
}
|
||||
@@ -827,7 +828,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
|
||||
goto error;
|
||||
|
||||
if (!(cmd->libmem = pool_create(4 * 1024))) {
|
||||
if (!(cmd->libmem = pool_create("library", 4 * 1024))) {
|
||||
log_error("Library memory pool creation failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -858,7 +859,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
if (!_init_filters(cmd))
|
||||
goto error;
|
||||
|
||||
if (!(cmd->mem = pool_create(4 * 1024))) {
|
||||
if (!(cmd->mem = pool_create("command", 4 * 1024))) {
|
||||
log_error("Command memory pool creation failed");
|
||||
return 0;
|
||||
}
|
||||
|
@@ -99,7 +99,7 @@ static int _tok_match(const char *str, const char *b, const char *e)
|
||||
struct config_tree *create_config_tree(const char *filename)
|
||||
{
|
||||
struct cs *c;
|
||||
struct pool *mem = pool_create(10 * 1024);
|
||||
struct pool *mem = pool_create("config", 10 * 1024);
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
|
@@ -82,6 +82,7 @@ struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
dev->dev = 0;
|
||||
dev->fd = -1;
|
||||
dev->open_count = 0;
|
||||
dev->block_size = -1;
|
||||
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||
list_init(&dev->open_list);
|
||||
|
||||
@@ -101,6 +102,7 @@ static struct device *_dev_create(dev_t d)
|
||||
dev->dev = d;
|
||||
dev->fd = -1;
|
||||
dev->open_count = 0;
|
||||
dev->block_size = -1;
|
||||
dev->end = UINT64_C(0);
|
||||
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||
list_init(&dev->open_list);
|
||||
@@ -387,7 +389,7 @@ int dev_cache_init(void)
|
||||
{
|
||||
_cache.names = NULL;
|
||||
|
||||
if (!(_cache.mem = pool_create(10 * 1024))) {
|
||||
if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -81,7 +81,9 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
||||
}
|
||||
|
||||
if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
|
||||
log_sys_error("lseek", dev_name(where->dev));
|
||||
log_error("%s: lseek %" PRIu64 " failed: %s",
|
||||
dev_name(where->dev), (uint64_t) where->start,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -92,6 +94,14 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
||||
read(fd, buffer, (size_t) where->size - total);
|
||||
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
|
||||
|
||||
if (n < 0)
|
||||
log_error("%s: %s failed after %" PRIu64 " of %" PRIu64
|
||||
" at %" PRIu64 ": %s", dev_name(where->dev),
|
||||
should_write ? "write" : "read",
|
||||
(uint64_t) total,
|
||||
(uint64_t) where->size,
|
||||
(uint64_t) where->start, strerror(errno));
|
||||
|
||||
if (n <= 0)
|
||||
break;
|
||||
|
||||
@@ -114,14 +124,18 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
||||
*/
|
||||
static int _get_block_size(struct device *dev, unsigned int *size)
|
||||
{
|
||||
int s;
|
||||
const char *name = dev_name(dev);
|
||||
|
||||
if (ioctl(dev_fd(dev), BLKBSZGET, &s) < 0) {
|
||||
log_sys_error("ioctl BLKBSZGET", dev_name(dev));
|
||||
return 0;
|
||||
if ((dev->block_size == -1)) {
|
||||
if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) {
|
||||
log_sys_error("ioctl BLKBSZGET", name);
|
||||
return 0;
|
||||
}
|
||||
log_debug("%s: block size is %u bytes", name, dev->block_size);
|
||||
}
|
||||
|
||||
*size = (unsigned int) s;
|
||||
*size = (unsigned int) dev->block_size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -217,7 +231,6 @@ int dev_get_size(const struct device *dev, uint64_t *size)
|
||||
int fd;
|
||||
const char *name = dev_name(dev);
|
||||
|
||||
log_very_verbose("Getting size of %s", name);
|
||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||
log_sys_error("open", name);
|
||||
return 0;
|
||||
@@ -225,22 +238,27 @@ int dev_get_size(const struct device *dev, uint64_t *size)
|
||||
|
||||
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
|
||||
log_sys_error("ioctl BLKGETSIZE64", name);
|
||||
close(fd);
|
||||
if (close(fd))
|
||||
log_sys_error("close", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*size >>= BLKSIZE_SHIFT; /* Convert to sectors */
|
||||
close(fd);
|
||||
if (close(fd))
|
||||
log_sys_error("close", name);
|
||||
|
||||
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME Unused
|
||||
int dev_get_sectsize(struct device *dev, uint32_t *size)
|
||||
{
|
||||
int fd;
|
||||
int s;
|
||||
const char *name = dev_name(dev);
|
||||
|
||||
log_very_verbose("Getting size of %s", name);
|
||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||
log_sys_error("open", name);
|
||||
return 0;
|
||||
@@ -254,8 +272,12 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
|
||||
|
||||
close(fd);
|
||||
*size = (uint32_t) s;
|
||||
|
||||
log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
void dev_flush(struct device *dev)
|
||||
{
|
||||
@@ -274,8 +296,20 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
const char *name;
|
||||
|
||||
if (dev->fd >= 0) {
|
||||
dev->open_count++;
|
||||
return 1;
|
||||
if ((dev->flags & DEV_OPENED_RW) ||
|
||||
((flags & O_ACCMODE) != O_RDWR)) {
|
||||
dev->open_count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dev->open_count) {
|
||||
/* FIXME Ensure we never get here */
|
||||
log_debug("WARNING: %s already opened read-only",
|
||||
dev_name(dev));
|
||||
dev->open_count++;
|
||||
}
|
||||
|
||||
dev_close_immediate(dev);
|
||||
}
|
||||
|
||||
if (memlock())
|
||||
@@ -311,14 +345,18 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev->open_count = 1;
|
||||
dev->open_count++;
|
||||
dev->flags &= ~DEV_ACCESSED_W;
|
||||
if ((flags & O_ACCMODE) == O_RDWR)
|
||||
dev->flags |= DEV_OPENED_RW;
|
||||
else
|
||||
dev->flags &= ~DEV_OPENED_RW;
|
||||
|
||||
if (!(dev->flags & DEV_REGULAR) &&
|
||||
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
|
||||
log_error("%s: fstat failed: Has device name changed?", name);
|
||||
dev_close(dev);
|
||||
dev->fd = -1;
|
||||
dev_close_immediate(dev);
|
||||
dev->open_count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -327,12 +365,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
dev_flush(dev);
|
||||
#endif
|
||||
|
||||
if ((flags & O_CREAT) && !(flags & O_TRUNC)) {
|
||||
if ((flags & O_CREAT) && !(flags & O_TRUNC))
|
||||
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
|
||||
}
|
||||
|
||||
list_add(&_open_devices, &dev->open_list);
|
||||
log_debug("Opened %s", dev_name(dev));
|
||||
|
||||
log_debug("Opened %s %s", dev_name(dev),
|
||||
dev->flags & DEV_OPENED_RW ? "RW" : "RO");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -360,6 +399,7 @@ static void _close(struct device *dev)
|
||||
if (close(dev->fd))
|
||||
log_sys_error("close", dev_name(dev));
|
||||
dev->fd = -1;
|
||||
dev->block_size = -1;
|
||||
list_del(&dev->open_list);
|
||||
|
||||
log_debug("Closed %s", dev_name(dev));
|
||||
@@ -385,8 +425,11 @@ static int _dev_close(struct device *dev, int immediate)
|
||||
dev_flush(dev);
|
||||
#endif
|
||||
|
||||
if (dev->open_count > 0)
|
||||
dev->open_count--;
|
||||
|
||||
/* FIXME lookup device in cache to get vgname and see if it's locked? */
|
||||
if (--dev->open_count < 1 && (immediate || !vgs_locked()))
|
||||
if (immediate || (dev->open_count < 1 && !vgs_locked()))
|
||||
_close(dev);
|
||||
|
||||
return 1;
|
||||
@@ -418,8 +461,10 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct device_area where;
|
||||
|
||||
if (!dev->open_count)
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
where.dev = dev;
|
||||
where.start = offset;
|
||||
@@ -437,8 +482,10 @@ int dev_append(struct device *dev, size_t len, void *buffer)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!dev->open_count)
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = dev_write(dev, dev->end, len, buffer);
|
||||
dev->end += (uint64_t) len;
|
||||
@@ -453,8 +500,10 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct device_area where;
|
||||
|
||||
if (!dev->open_count)
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
where.dev = dev;
|
||||
where.start = offset;
|
||||
@@ -501,6 +550,5 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
/* FIXME: Always display error */
|
||||
return (len == 0);
|
||||
}
|
||||
|
69
lib/device/dev-md.c
Normal file
69
lib/device/dev-md.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Luca Berra
|
||||
* 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 Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 "lib.h"
|
||||
#include "metadata.h"
|
||||
#include "xlate.h"
|
||||
|
||||
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
|
||||
|
||||
#define MD_SB_MAGIC 0xa92b4efc
|
||||
#define MD_RESERVED_BYTES (64 * 1024)
|
||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
|
||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
|
||||
- MD_RESERVED_SECTORS)
|
||||
|
||||
/*
|
||||
* Returns -1 on error
|
||||
*/
|
||||
int dev_is_md(struct device *dev, uint64_t *sb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef linux
|
||||
|
||||
uint64_t size, sb_offset;
|
||||
uint32_t md_magic;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size < MD_RESERVED_SECTORS * 2)
|
||||
return 0;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
|
||||
|
||||
/* Check if it is an md component device. */
|
||||
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
|
||||
(md_magic == xlate32(MD_SB_MAGIC))) {
|
||||
if (sb)
|
||||
*sb = sb_offset;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
@@ -13,6 +13,93 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "lvm-types.h"
|
||||
#include "device.h"
|
||||
#include "metadata.h"
|
||||
#include "filter.h"
|
||||
#include "xlate.h"
|
||||
|
||||
/* See linux/genhd.h and fs/partitions/msdos */
|
||||
|
||||
#define PART_MAGIC 0xAA55
|
||||
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
|
||||
#define PART_OFFSET UINT64_C(0x1BE)
|
||||
|
||||
struct partition {
|
||||
uint8_t boot_ind;
|
||||
uint8_t head;
|
||||
uint8_t sector;
|
||||
uint8_t cyl;
|
||||
uint8_t sys_ind; /* partition type */
|
||||
uint8_t end_head;
|
||||
uint8_t end_sector;
|
||||
uint8_t end_cyl;
|
||||
uint32_t start_sect;
|
||||
uint32_t nr_sects;
|
||||
} __attribute__((packed));
|
||||
|
||||
static int _is_partitionable(struct device *dev)
|
||||
{
|
||||
int parts = max_partitions(MAJOR(dev->dev));
|
||||
|
||||
if ((parts <= 1) || (MINOR(dev->dev) % parts))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _has_partition_table(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned p;
|
||||
uint8_t buf[SECTOR_SIZE];
|
||||
uint16_t *part_magic;
|
||||
struct partition *part;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dev_read(dev, 0, sizeof(buf), &buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* FIXME Check for other types of partition table too */
|
||||
|
||||
/* Check for msdos partition table */
|
||||
part_magic = (uint16_t *)(buf + PART_MAGIC_OFFSET);
|
||||
if ((*part_magic == xlate16(PART_MAGIC))) {
|
||||
part = (struct partition *) (buf + PART_OFFSET);
|
||||
for (p = 0; p < 4; p++, part++) {
|
||||
/* Table is invalid if boot indicator not 0 or 0x80 */
|
||||
if ((part->boot_ind & 0x7f)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
/* Must have at least one non-empty partition */
|
||||
if (part->nr_sects)
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int is_partitioned_dev(struct device *dev)
|
||||
{
|
||||
if (!_is_partitionable(dev))
|
||||
return 0;
|
||||
|
||||
return _has_partition_table(dev);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -27,24 +114,13 @@
|
||||
#include <linux/major.h>
|
||||
#include <linux/genhd.h>
|
||||
|
||||
#include "dbg_malloc.h"
|
||||
#include "log.h"
|
||||
#include "dev-cache.h"
|
||||
#include "metadata.h"
|
||||
#include "device.h"
|
||||
|
||||
int _get_partition_type(struct dev_filter *filter, struct device *d);
|
||||
|
||||
#define MINOR_PART(dm, d) (MINOR((d)->dev) % dev_max_partitions(dm, (d)->dev))
|
||||
#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
|
||||
|
||||
int is_whole_disk(struct dev_filter *filter, struct device *d)
|
||||
int is_extended_partition(struct device *d)
|
||||
{
|
||||
return (MINOR_PART(dm, d)) ? 0 : 1;
|
||||
}
|
||||
|
||||
int is_extended_partition(struct dev_mgr *dm, struct device *d)
|
||||
{
|
||||
return (MINOR_PART(dm, d) > 4) ? 1 : 0;
|
||||
return (MINOR_PART(d) > 4) ? 1 : 0;
|
||||
}
|
||||
|
||||
struct device *dev_primary(struct dev_mgr *dm, struct device *d)
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
|
||||
#define DEV_REGULAR 0x00000002 /* Regular file? */
|
||||
#define DEV_ALLOCED 0x00000004 /* dbg_malloc used */
|
||||
#define DEV_OPENED_RW 0x00000008 /* Opened RW */
|
||||
|
||||
/*
|
||||
* All devices in LVM will be represented by one of these.
|
||||
@@ -34,6 +35,7 @@ struct device {
|
||||
/* private */
|
||||
int fd;
|
||||
int open_count;
|
||||
int block_size;
|
||||
uint32_t flags;
|
||||
uint64_t end;
|
||||
struct list open_list;
|
||||
@@ -89,15 +91,14 @@ static inline const char *dev_name(const struct device *dev)
|
||||
/* Return a valid device name from the alias list; NULL otherwise */
|
||||
const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
|
||||
/* Does device contain md superblock? If so, where? */
|
||||
int dev_is_md(struct device *dev, uint64_t *sb);
|
||||
|
||||
/* FIXME Check partition type if appropriate */
|
||||
|
||||
#define is_lvm_partition(a) 1
|
||||
/* int is_lvm_partition(const char *name); */
|
||||
|
||||
/*
|
||||
static inline int is_lvm_partition(const char *name)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
int is_partitioned_dev(struct device *dev);
|
||||
|
||||
#endif
|
||||
|
@@ -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 ---");
|
||||
|
||||
|
@@ -28,42 +28,24 @@
|
||||
|
||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
uint64_t size, sector;
|
||||
uint32_t md_magic;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size < MD_RESERVED_SECTORS * 2)
|
||||
/*
|
||||
* We could ignore it since it is obviously too
|
||||
* small, but that's not our job.
|
||||
*/
|
||||
int ret;
|
||||
|
||||
if (!md_filtering())
|
||||
return 1;
|
||||
|
||||
ret = dev_is_md(dev, NULL);
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
if (ret == 1) {
|
||||
log_debug("%s: Skipping md component device", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
sector = MD_NEW_SIZE_SECTORS(size);
|
||||
|
||||
/* Check if it is an md component device. */
|
||||
if (dev_read(dev, sector << SECTOR_SHIFT, sizeof(uint32_t), &md_magic)) {
|
||||
if (md_magic == MD_SB_MAGIC) {
|
||||
log_debug("%s: Skipping md component device",
|
||||
dev_name(dev));
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (ret < 0) {
|
||||
log_debug("%s: Skipping: error in md component detection",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -212,13 +212,10 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||
sl = list_item(ah, struct str_list);
|
||||
hash_insert(pf->devices, sl->str, l);
|
||||
}
|
||||
}
|
||||
} else if (l == PF_BAD_DEVICE)
|
||||
log_debug("%s: Skipping (cached)", dev_name(dev));
|
||||
|
||||
if (l == PF_BAD_DEVICE) {
|
||||
log_debug("%s: Skipping (cached)", dev_name(dev));
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
return (l == PF_BAD_DEVICE) ? 0 : 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
|
@@ -101,7 +101,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
|
||||
unsigned count = 0;
|
||||
int i, r = 0;
|
||||
|
||||
if (!(scratch = pool_create(1024))) {
|
||||
if (!(scratch = pool_create("filter matcher", 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -186,6 +186,9 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
||||
first = 0;
|
||||
}
|
||||
|
||||
if (rejected)
|
||||
log_debug("%s: Skipping (regex)", dev_name(dev));
|
||||
|
||||
/*
|
||||
* pass everything that doesn't match
|
||||
* anything.
|
||||
@@ -201,7 +204,7 @@ static void _destroy(struct dev_filter *f)
|
||||
|
||||
struct dev_filter *regex_filter_create(struct config_value *patterns)
|
||||
{
|
||||
struct pool *mem = pool_create(10 * 1024);
|
||||
struct pool *mem = pool_create("filter regex", 10 * 1024);
|
||||
struct rfilter *rf;
|
||||
struct dev_filter *f;
|
||||
|
||||
|
@@ -194,8 +194,10 @@ static int _read_devs(struct dev_set *ds, const char *dir)
|
||||
dtype = d->d_type;
|
||||
|
||||
if (dtype == DT_UNKNOWN) {
|
||||
if (stat(path, &info) >= 0) {
|
||||
if (S_ISDIR(info.st_mode))
|
||||
if (lstat(path, &info) >= 0) {
|
||||
if (S_ISLNK(info.st_mode))
|
||||
dtype = DT_LNK;
|
||||
else if (S_ISDIR(info.st_mode))
|
||||
dtype = DT_DIR;
|
||||
else if (S_ISREG(info.st_mode))
|
||||
dtype = DT_REG;
|
||||
@@ -246,7 +248,11 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
||||
if (ds->initialised != 1)
|
||||
return 1;
|
||||
|
||||
return _set_lookup(ds, dev->dev);
|
||||
if (!_set_lookup(ds, dev->dev)) {
|
||||
log_debug("%s: Skipping (sysfs)", dev_name(dev));
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
@@ -265,7 +271,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
|
||||
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
|
||||
return NULL;
|
||||
|
||||
if (!(mem = pool_create(256))) {
|
||||
if (!(mem = pool_create("sysfs", 256))) {
|
||||
log_error("sysfs pool creation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "filter.h"
|
||||
#include "lvm-string.h"
|
||||
#include "config.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
@@ -27,6 +28,10 @@
|
||||
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
/* FIXME Make this sparse */
|
||||
/* 0 means LVM won't use this major number. */
|
||||
static int _max_partitions_by_major[NUMBER_OF_MAJORS];
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const int max_partitions;
|
||||
@@ -39,12 +44,19 @@ int md_major(void)
|
||||
return _md_major;
|
||||
}
|
||||
|
||||
/* This list can be supplemented with devices/types in the config file */
|
||||
/*
|
||||
* Devices are only checked for partition tables if their minor number
|
||||
* is a multiple of the number corresponding to their type below
|
||||
* i.e. this gives the granularity of whole-device minor numbers.
|
||||
* Use 1 if the device is not partitionable.
|
||||
*
|
||||
* The list can be supplemented with devices/types in the config file.
|
||||
*/
|
||||
static const device_info_t device_info[] = {
|
||||
{"ide", 16}, /* IDE disk */
|
||||
{"ide", 64}, /* IDE disk */
|
||||
{"sd", 16}, /* SCSI disk */
|
||||
{"md", 16}, /* Multiple Disk driver (SoftRAID) */
|
||||
{"loop", 16}, /* Loop device */
|
||||
{"md", 1}, /* Multiple Disk driver (SoftRAID) */
|
||||
{"loop", 1}, /* Loop device */
|
||||
{"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
|
||||
{"dac960", 8}, /* DAC960 */
|
||||
{"nbd", 16}, /* Network Block Device */
|
||||
@@ -53,6 +65,7 @@ static const device_info_t device_info[] = {
|
||||
{"ubd", 16}, /* User-mode virtual block device */
|
||||
{"ataraid", 16}, /* ATA Raid */
|
||||
{"drbd", 16}, /* Distributed Replicated Block Device */
|
||||
{"emcpower", 16}, /* EMC Powerpath */
|
||||
{"power2", 16}, /* EMC Powerpath */
|
||||
{"i2o_block", 16}, /* i2o Block Disk */
|
||||
{"iseries/vd", 8}, /* iSeries disks */
|
||||
@@ -62,29 +75,49 @@ static const device_info_t device_info[] = {
|
||||
static int _passes_lvm_type_device_filter(struct dev_filter *f,
|
||||
struct device *dev)
|
||||
{
|
||||
int fd;
|
||||
const char *name = dev_name(dev);
|
||||
int ret = 0;
|
||||
uint64_t size;
|
||||
|
||||
/* Is this a recognised device type? */
|
||||
if (!(((int *) f->private)[MAJOR(dev->dev)])) {
|
||||
if (!_max_partitions_by_major[MAJOR(dev->dev)]) {
|
||||
log_debug("%s: Skipping: Unrecognised LVM device type %"
|
||||
PRIu64, name, (uint64_t) MAJOR(dev->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check it's accessible */
|
||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||
log_debug("%s: Skipping: open failed: %s", name,
|
||||
strerror(errno));
|
||||
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
|
||||
log_debug("%s: Skipping: open failed", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check it's not too small */
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
log_debug("%s: Skipping: dev_get_size failed", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
if (size < PV_MIN_SIZE) {
|
||||
log_debug("%s: Skipping: Too small to hold a PV", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 1;
|
||||
if (is_partitioned_dev(dev)) {
|
||||
log_debug("%s: Skipping: Partition table signature found",
|
||||
name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
dev_close(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
static int _scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
{
|
||||
char line[80];
|
||||
char proc_devices[PATH_MAX];
|
||||
@@ -94,36 +127,31 @@ static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
int blocksection = 0;
|
||||
size_t dev_len = 0;
|
||||
struct config_value *cv;
|
||||
int *max_partitions_by_major;
|
||||
char *name;
|
||||
|
||||
/* FIXME Make this sparse */
|
||||
if (!(max_partitions_by_major =
|
||||
dbg_malloc(sizeof(int) * NUMBER_OF_MAJORS))) {
|
||||
log_error("Filter failed to allocate max_partitions_by_major");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!*proc) {
|
||||
log_verbose("No proc filesystem found: using all block device "
|
||||
"types");
|
||||
for (i = 0; i < NUMBER_OF_MAJORS; i++)
|
||||
max_partitions_by_major[i] = 1;
|
||||
return max_partitions_by_major;
|
||||
_max_partitions_by_major[i] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* All types unrecognised initially */
|
||||
memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
|
||||
|
||||
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
|
||||
"%s/devices", proc) < 0) {
|
||||
log_error("Failed to create /proc/devices string");
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pd = fopen(proc_devices, "r"))) {
|
||||
log_sys_error("fopen", proc_devices);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
|
||||
while (fgets(line, 80, pd) != NULL) {
|
||||
i = 0;
|
||||
while (line[i] == ' ' && line[i] != '\0')
|
||||
@@ -158,13 +186,13 @@ static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
if (dev_len <= strlen(line + i) &&
|
||||
!strncmp(device_info[j].name, line + i, dev_len) &&
|
||||
(line_maj < NUMBER_OF_MAJORS)) {
|
||||
max_partitions_by_major[line_maj] =
|
||||
_max_partitions_by_major[line_maj] =
|
||||
device_info[j].max_partitions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_partitions_by_major[line_maj] || !cn)
|
||||
if (!cn)
|
||||
continue;
|
||||
|
||||
/* Check devices/types for local variations */
|
||||
@@ -172,7 +200,7 @@ static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Expecting string in devices/types "
|
||||
"in config file");
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
dev_len = strlen(cv->v.str);
|
||||
name = cv->v.str;
|
||||
@@ -181,24 +209,29 @@ static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
log_error("Max partition count missing for %s "
|
||||
"in devices/types in config file",
|
||||
name);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (!cv->v.i) {
|
||||
log_error("Zero partition count invalid for "
|
||||
"%s in devices/types in config file",
|
||||
name);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (dev_len <= strlen(line + i) &&
|
||||
!strncmp(name, line + i, dev_len) &&
|
||||
(line_maj < NUMBER_OF_MAJORS)) {
|
||||
max_partitions_by_major[line_maj] = cv->v.i;
|
||||
_max_partitions_by_major[line_maj] = cv->v.i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(pd);
|
||||
return max_partitions_by_major;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int max_partitions(int major)
|
||||
{
|
||||
return _max_partitions_by_major[major];
|
||||
}
|
||||
|
||||
struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
@@ -213,8 +246,9 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
|
||||
f->passes_filter = _passes_lvm_type_device_filter;
|
||||
f->destroy = lvm_type_filter_destroy;
|
||||
f->private = NULL;
|
||||
|
||||
if (!(f->private = _scan_proc_dev(proc, cn))) {
|
||||
if (!_scan_proc_dev(proc, cn)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -224,7 +258,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
|
||||
void lvm_type_filter_destroy(struct dev_filter *f)
|
||||
{
|
||||
dbg_free(f->private);
|
||||
dbg_free(f);
|
||||
return;
|
||||
}
|
||||
|
@@ -37,4 +37,6 @@ void lvm_type_filter_destroy(struct dev_filter *f);
|
||||
|
||||
int md_major(void);
|
||||
|
||||
int max_partitions(int major);
|
||||
|
||||
#endif
|
||||
|
@@ -183,7 +183,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
const char *vg_name,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct pool *mem = pool_create(1024 * 10);
|
||||
struct pool *mem = pool_create("lvm1 vg_read", 1024 * 10);
|
||||
struct list pvs;
|
||||
struct volume_group *vg = NULL;
|
||||
list_init(&pvs);
|
||||
@@ -276,7 +276,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
|
||||
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct pool *mem = pool_create(1024 * 10);
|
||||
struct pool *mem = pool_create("lvm1 vg_write", 1024 * 10);
|
||||
struct list pvds;
|
||||
int r = 0;
|
||||
|
||||
@@ -299,7 +299,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
{
|
||||
struct pool *mem = pool_create(1024);
|
||||
struct pool *mem = pool_create("lvm1 pv_read", 1024);
|
||||
struct disk_list *dl;
|
||||
struct device *dev;
|
||||
int r = 0;
|
||||
@@ -421,7 +421,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
pv->pe_size = pv->pe_count = 0;
|
||||
pv->pe_start = PE_ALIGN;
|
||||
|
||||
if (!(mem = pool_create(1024))) {
|
||||
if (!(mem = pool_create("lvm1 pv_write", 1024))) {
|
||||
stack;
|
||||
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;
|
||||
|
@@ -344,7 +344,7 @@ int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct list *pvds)
|
||||
{
|
||||
int r = 0;
|
||||
struct pool *scratch = pool_create(10 * 1024);
|
||||
struct pool *scratch = pool_create("lvm1 import_extents", 10 * 1024);
|
||||
struct hash_table *maps;
|
||||
|
||||
if (!scratch) {
|
||||
|
@@ -30,7 +30,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
struct list *pvh;
|
||||
struct list all_pvs;
|
||||
struct disk_list *dl;
|
||||
struct pool *mem = pool_create(10 * 1024);
|
||||
struct pool *mem = pool_create("lvm1 vg_number", 10 * 1024);
|
||||
int numbers[MAX_VG], i, r = 0;
|
||||
|
||||
list_init(&all_pvs);
|
||||
|
@@ -259,7 +259,7 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
||||
|
||||
/* FIXME: maybe should return a different error in memory
|
||||
* allocation failure */
|
||||
if (!(tmpmem = pool_create(512))) {
|
||||
if (!(tmpmem = pool_create("pool read_vg", 512))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -181,7 +181,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
const char *vg_name,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct pool *mem = pool_create(1024);
|
||||
struct pool *mem = pool_create("pool vg_read", 1024);
|
||||
struct list pds;
|
||||
struct volume_group *vg = NULL;
|
||||
|
||||
@@ -227,7 +227,7 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
{
|
||||
struct pool *mem = pool_create(1024);
|
||||
struct pool *mem = pool_create("pool pv_read", 1024);
|
||||
struct pool_list *pl;
|
||||
struct device *dev;
|
||||
int r = 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;
|
||||
@@ -652,7 +652,7 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
||||
struct physical_volume *pv;
|
||||
char buffer[32], *name;
|
||||
|
||||
if (!(f->mem = pool_create(512))) {
|
||||
if (!(f->mem = pool_create("text pv_names", 512))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
|
@@ -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)
|
||||
@@ -150,7 +149,7 @@ 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));
|
||||
log_error("cluster request failed: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,7 @@ static struct str_list _log_dev_alias;
|
||||
static int _verbose_level = VERBOSE_BASE_LEVEL;
|
||||
static int _test = 0;
|
||||
static int _partial = 0;
|
||||
static int _md_filtering = 0;
|
||||
static int _pvmove = 0;
|
||||
static int _debug_level = 0;
|
||||
static int _syslog = 0;
|
||||
@@ -138,6 +139,11 @@ void init_partial(int level)
|
||||
_partial = level;
|
||||
}
|
||||
|
||||
void init_md_filtering(int level)
|
||||
{
|
||||
_md_filtering = level;
|
||||
}
|
||||
|
||||
void init_pvmove(int level)
|
||||
{
|
||||
_pvmove = level;
|
||||
@@ -187,6 +193,11 @@ int partial_mode()
|
||||
return _partial;
|
||||
}
|
||||
|
||||
int md_filtering()
|
||||
{
|
||||
return _md_filtering;
|
||||
}
|
||||
|
||||
int pvmove_mode()
|
||||
{
|
||||
return _pvmove;
|
||||
@@ -215,7 +226,7 @@ int debug_level()
|
||||
void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024], buf2[4096];
|
||||
char buf[1024], buf2[4096], locn[4096];
|
||||
int bufused, n;
|
||||
const char *message;
|
||||
const char *trformat; /* Translated format string */
|
||||
@@ -243,36 +254,46 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
|
||||
log_it:
|
||||
if (!_log_suppress) {
|
||||
if (_verbose_level > _LOG_DEBUG)
|
||||
lvm_snprintf(locn, sizeof(locn), "#%s:%d ",
|
||||
file, line);
|
||||
else
|
||||
locn[0] = '\0';
|
||||
|
||||
va_start(ap, format);
|
||||
switch (level) {
|
||||
case _LOG_DEBUG:
|
||||
if (!strcmp("<backtrace>", format))
|
||||
if (!strcmp("<backtrace>", format) &&
|
||||
_verbose_level <= _LOG_DEBUG)
|
||||
break;
|
||||
if (_verbose_level >= _LOG_DEBUG) {
|
||||
printf("%s%s", _cmd_name, _msg_prefix);
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
_msg_prefix);
|
||||
if (_indent)
|
||||
printf(" ");
|
||||
vprintf(trformat, ap);
|
||||
putchar('\n');
|
||||
fprintf(stderr, " ");
|
||||
vfprintf(stderr, trformat, ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
break;
|
||||
|
||||
case _LOG_INFO:
|
||||
if (_verbose_level >= _LOG_INFO) {
|
||||
printf("%s%s", _cmd_name, _msg_prefix);
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
_msg_prefix);
|
||||
if (_indent)
|
||||
printf(" ");
|
||||
vprintf(trformat, ap);
|
||||
putchar('\n');
|
||||
fprintf(stderr, " ");
|
||||
vfprintf(stderr, trformat, ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
break;
|
||||
case _LOG_NOTICE:
|
||||
if (_verbose_level >= _LOG_NOTICE) {
|
||||
printf("%s%s", _cmd_name, _msg_prefix);
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
_msg_prefix);
|
||||
if (_indent)
|
||||
printf(" ");
|
||||
vprintf(trformat, ap);
|
||||
putchar('\n');
|
||||
fprintf(stderr, " ");
|
||||
vfprintf(stderr, trformat, ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
break;
|
||||
case _LOG_WARN:
|
||||
@@ -284,7 +305,8 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
break;
|
||||
case _LOG_ERR:
|
||||
if (_verbose_level >= _LOG_ERR) {
|
||||
fprintf(stderr, "%s%s", _cmd_name, _msg_prefix);
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
_msg_prefix);
|
||||
vfprintf(stderr, trformat, ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
@@ -292,7 +314,8 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
case _LOG_FATAL:
|
||||
default:
|
||||
if (_verbose_level >= _LOG_FATAL) {
|
||||
fprintf(stderr, "%s%s", _cmd_name, _msg_prefix);
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
_msg_prefix);
|
||||
vfprintf(stderr, trformat, ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
@@ -63,6 +63,7 @@ void fin_syslog(void);
|
||||
void init_verbose(int level);
|
||||
void init_test(int level);
|
||||
void init_partial(int level);
|
||||
void init_md_filtering(int level);
|
||||
void init_pvmove(int level);
|
||||
void init_debug(int level);
|
||||
void init_cmd_name(int status);
|
||||
@@ -75,6 +76,7 @@ void set_cmd_name(const char *cmd_name);
|
||||
|
||||
int test_mode(void);
|
||||
int partial_mode(void);
|
||||
int md_filtering(void);
|
||||
int pvmove_mode(void);
|
||||
int debug_level(void);
|
||||
int ignorelockingfailure(void);
|
||||
|
@@ -458,7 +458,7 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
|
||||
if (segtype->flags & SEG_VIRTUAL)
|
||||
return _alloc_virtual(lv, allocated, segtype);
|
||||
|
||||
if (!(scratch = pool_create(1024))) {
|
||||
if (!(scratch = pool_create("allocation", 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -711,6 +711,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()) {
|
||||
|
@@ -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,6 +127,7 @@ 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;
|
||||
|
||||
|
@@ -134,17 +134,19 @@ static void _quote_hyphens(char **out, const char *src)
|
||||
char *build_dm_name(struct pool *mem, const char *vg,
|
||||
const char *lv, const char *layer)
|
||||
{
|
||||
size_t len = 0;
|
||||
int hyphens = 0;
|
||||
size_t len = 1;
|
||||
int hyphens = 1;
|
||||
char *r, *out;
|
||||
|
||||
_count_hyphens(vg, &len, &hyphens);
|
||||
_count_hyphens(lv, &len, &hyphens);
|
||||
|
||||
if (layer && *layer)
|
||||
if (layer && *layer) {
|
||||
_count_hyphens(layer, &len, &hyphens);
|
||||
hyphens++;
|
||||
}
|
||||
|
||||
len += hyphens + 2;
|
||||
len += hyphens;
|
||||
|
||||
if (!(r = pool_alloc(mem, len))) {
|
||||
stack;
|
||||
|
@@ -19,6 +19,8 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef DEBUG_MEM
|
||||
|
||||
struct memblock {
|
||||
struct memblock *prev, *next; /* All allocated blocks are linked */
|
||||
size_t length; /* Size of the requested block */
|
||||
@@ -47,7 +49,7 @@ void *malloc_aux(size_t s, const char *file, int line)
|
||||
|
||||
if (s > 50000000) {
|
||||
log_error("Huge memory allocation (size %" PRIuPTR
|
||||
") rejected - bug?", s);
|
||||
") rejected - metadata corruption?", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -166,7 +168,6 @@ void *realloc_aux(void *p, unsigned int s, const char *file, int line)
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEM
|
||||
int dump_memory(void)
|
||||
{
|
||||
unsigned long tot = 0;
|
||||
@@ -213,10 +214,18 @@ void bounds_check(void)
|
||||
mb = mb->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
#else
|
||||
|
||||
void *malloc_aux(size_t s, const char *file, int line)
|
||||
{
|
||||
if (s > 50000000) {
|
||||
log_error("Huge memory allocation (size %" PRIuPTR
|
||||
") rejected - metadata corruption?", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return malloc(s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -20,22 +20,26 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG_MEM
|
||||
void *malloc_aux(size_t s, const char *file, int line);
|
||||
# define dbg_malloc(s) malloc_aux((s), __FILE__, __LINE__)
|
||||
|
||||
#ifdef DEBUG_MEM
|
||||
|
||||
void free_aux(void *p);
|
||||
void *realloc_aux(void *p, unsigned int s, const char *file, int line);
|
||||
int dump_memory(void);
|
||||
void bounds_check(void);
|
||||
|
||||
# define dbg_malloc(s) malloc_aux((s), __FILE__, __LINE__)
|
||||
# define dbg_free(p) free_aux(p)
|
||||
# define dbg_realloc(p, s) realloc_aux(p, s, __FILE__, __LINE__)
|
||||
|
||||
#else
|
||||
# define dbg_malloc(s) malloc(s)
|
||||
|
||||
# define dbg_free(p) free(p)
|
||||
# define dbg_realloc(p, s) realloc(p, s)
|
||||
# define dump_memory()
|
||||
# define bounds_check()
|
||||
|
||||
#endif
|
||||
|
||||
static inline char *dbg_strdup(const char *str)
|
||||
|
@@ -22,38 +22,64 @@ struct block {
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned block_serialno; /* Non-decreasing serialno of block */
|
||||
unsigned blocks_allocated; /* Current number of blocks allocated */
|
||||
unsigned blocks_max; /* Max no of concurrently-allocated blocks */
|
||||
unsigned int bytes, maxbytes;
|
||||
} pool_stats;
|
||||
|
||||
struct pool {
|
||||
const char *name;
|
||||
|
||||
int begun;
|
||||
struct block *object;
|
||||
|
||||
struct block *blocks;
|
||||
struct block *tail;
|
||||
|
||||
pool_stats stats;
|
||||
};
|
||||
|
||||
/* by default things come out aligned for doubles */
|
||||
#define DEFAULT_ALIGNMENT __alignof__ (double)
|
||||
|
||||
struct pool *pool_create(size_t chunk_hint)
|
||||
struct pool *pool_create(const char *name, size_t chunk_hint)
|
||||
{
|
||||
struct pool *mem = dbg_malloc(sizeof(*mem));
|
||||
|
||||
if (!mem) {
|
||||
log_error("Couldn't create memory pool (size %" PRIsize_t ")",
|
||||
sizeof(*mem));
|
||||
log_error("Couldn't create memory pool %s (size %"
|
||||
PRIsize_t ")", name, sizeof(*mem));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem->name = name;
|
||||
mem->begun = 0;
|
||||
mem->object = 0;
|
||||
mem->blocks = mem->tail = NULL;
|
||||
|
||||
mem->stats.block_serialno = 0;
|
||||
mem->stats.blocks_allocated = 0;
|
||||
mem->stats.blocks_max = 0;
|
||||
mem->stats.bytes = 0;
|
||||
mem->stats.maxbytes = 0;
|
||||
|
||||
#ifdef DEBUG_POOL
|
||||
log_debug("Created mempool %s", name);
|
||||
#endif
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void _free_blocks(struct block *b)
|
||||
static void _free_blocks(struct pool *p, struct block *b)
|
||||
{
|
||||
struct block *n;
|
||||
|
||||
while (b) {
|
||||
p->stats.bytes -= b->size;
|
||||
p->stats.blocks_allocated--;
|
||||
|
||||
n = b->next;
|
||||
dbg_free(b->data);
|
||||
dbg_free(b);
|
||||
@@ -61,9 +87,22 @@ static void _free_blocks(struct block *b)
|
||||
}
|
||||
}
|
||||
|
||||
static void _pool_stats(struct pool *p, const char *action)
|
||||
{
|
||||
#ifdef DEBUG_POOL
|
||||
log_debug("%s mempool %s: %u/%u bytes, %u/%u blocks, "
|
||||
"%u allocations)", action, p->name, p->stats.bytes,
|
||||
p->stats.maxbytes, p->stats.blocks_allocated,
|
||||
p->stats.blocks_max, p->stats.block_serialno);
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
||||
void pool_destroy(struct pool *p)
|
||||
{
|
||||
_free_blocks(p->blocks);
|
||||
_pool_stats(p, "Destroying");
|
||||
_free_blocks(p, p->blocks);
|
||||
dbg_free(p);
|
||||
}
|
||||
|
||||
@@ -79,6 +118,15 @@ static void _append_block(struct pool *p, struct block *b)
|
||||
p->tail = b;
|
||||
} else
|
||||
p->blocks = p->tail = b;
|
||||
|
||||
p->stats.block_serialno++;
|
||||
p->stats.blocks_allocated++;
|
||||
if (p->stats.blocks_allocated > p->stats.blocks_max)
|
||||
p->stats.blocks_max = p->stats.blocks_allocated;
|
||||
|
||||
p->stats.bytes += b->size;
|
||||
if (p->stats.bytes > p->stats.maxbytes)
|
||||
p->stats.maxbytes = p->stats.bytes;
|
||||
}
|
||||
|
||||
static struct block *_new_block(size_t s, unsigned alignment)
|
||||
@@ -121,12 +169,14 @@ void *pool_alloc_aligned(struct pool *p, size_t s, unsigned alignment)
|
||||
return NULL;
|
||||
|
||||
_append_block(p, b);
|
||||
|
||||
return b->data;
|
||||
}
|
||||
|
||||
void pool_empty(struct pool *p)
|
||||
{
|
||||
_free_blocks(p->blocks);
|
||||
_pool_stats(p, "Emptying");
|
||||
_free_blocks(p, p->blocks);
|
||||
p->blocks = p->tail = NULL;
|
||||
}
|
||||
|
||||
@@ -134,6 +184,8 @@ void pool_free(struct pool *p, void *ptr)
|
||||
{
|
||||
struct block *b, *prev = NULL;
|
||||
|
||||
_pool_stats(p, "Freeing (before)");
|
||||
|
||||
for (b = p->blocks; b; b = b->next) {
|
||||
if (b->data == ptr)
|
||||
break;
|
||||
@@ -147,13 +199,15 @@ void pool_free(struct pool *p, void *ptr)
|
||||
*/
|
||||
assert(b);
|
||||
|
||||
_free_blocks(b);
|
||||
_free_blocks(p, b);
|
||||
|
||||
if (prev) {
|
||||
p->tail = prev;
|
||||
prev->next = NULL;
|
||||
} else
|
||||
p->blocks = p->tail = NULL;
|
||||
|
||||
_pool_stats(p, "Freeing (after)");
|
||||
}
|
||||
|
||||
int pool_begin_object(struct pool *p, size_t init_size)
|
||||
|
@@ -36,14 +36,14 @@ struct chunk *_new_chunk(struct pool *p, size_t s);
|
||||
/* by default things come out aligned for doubles */
|
||||
#define DEFAULT_ALIGNMENT __alignof__ (double)
|
||||
|
||||
struct pool *pool_create(size_t chunk_hint)
|
||||
struct pool *pool_create(const char *name, size_t chunk_hint)
|
||||
{
|
||||
size_t new_size = 1024;
|
||||
struct pool *p = dbg_malloc(sizeof(*p));
|
||||
|
||||
if (!p) {
|
||||
log_error("Couldn't create memory pool (size %" PRIsize_t ")",
|
||||
sizeof(*p));
|
||||
log_error("Couldn't create memory pool %s (size %"
|
||||
PRIsize_t ")", name, sizeof(*p));
|
||||
return 0;
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
@@ -55,7 +55,7 @@
|
||||
struct pool;
|
||||
|
||||
/* constructor and destructor */
|
||||
struct pool *pool_create(size_t chunk_hint);
|
||||
struct pool *pool_create(const char *name, size_t chunk_hint);
|
||||
void pool_destroy(struct pool *p);
|
||||
|
||||
/* simple allocation/free routines */
|
||||
|
@@ -275,7 +275,7 @@ struct matcher *matcher_create(struct pool *mem, const char **patterns,
|
||||
int i;
|
||||
size_t len = 0;
|
||||
struct rx_node *rx;
|
||||
struct pool *scratch = pool_create(10 * 1024);
|
||||
struct pool *scratch = pool_create("regex matcher", 10 * 1024);
|
||||
struct matcher *m;
|
||||
|
||||
if (!scratch) {
|
||||
|
@@ -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
|
||||
@@ -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;
|
||||
@@ -1081,7 +1081,7 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
|
||||
rh->field_prefix = "";
|
||||
}
|
||||
|
||||
if (!(rh->mem = pool_create(10 * 1024))) {
|
||||
if (!(rh->mem = pool_create("report", 10 * 1024))) {
|
||||
log_error("Allocation of memory pool for report failed");
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ static const char *_name(const struct lv_segment *seg)
|
||||
static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
struct hash_table *pv_hash)
|
||||
{
|
||||
uint32_t chunk_size;
|
||||
uint32_t chunk_size, extent_count;
|
||||
const char *org_name, *cow_name;
|
||||
struct logical_volume *org, *cow;
|
||||
|
||||
@@ -70,7 +70,11 @@ 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 (!get_config_uint32(sn, "extent_count", &extent_count))
|
||||
extent_count = org->le_count;
|
||||
|
||||
if (!vg_add_snapshot(org, cow, 1, &seg->lv->lvid.id[1], extent_count,
|
||||
chunk_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -81,6 +85,8 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
static int _text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
{
|
||||
outf(f, "chunk_size = %u", seg->chunk_size);
|
||||
if (seg->len != seg->origin->le_count)
|
||||
outf(f, "extent_count = %u", seg->len);
|
||||
outf(f, "origin = \"%s\"", seg->origin->name);
|
||||
outf(f, "cow_store = \"%s\"", seg->cow->name);
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-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 the device-mapper userspace tools.
|
||||
#
|
||||
@@ -17,13 +17,16 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
interface = @interface@
|
||||
|
||||
SOURCES = libdm-common.c $(interface)/libdm-iface.c
|
||||
SOURCES = libdm-common.c libdm-file.c $(interface)/libdm-iface.c
|
||||
|
||||
INCLUDES = -I$(interface)
|
||||
|
||||
LIB_STATIC = $(interface)/libdevmapper.a
|
||||
LIB_SHARED = $(interface)/libdevmapper.so
|
||||
|
||||
CFLAGS += -DDEVICE_UID=@DEVICE_UID@ -DDEVICE_GID=@DEVICE_GID@ \
|
||||
-DDEVICE_MODE=@DEVICE_MODE@
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
.PHONY: install_dynamic install_static \
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-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 the device-mapper userspace tools.
|
||||
*
|
||||
@@ -13,22 +13,17 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "libdm-targets.h"
|
||||
#include "libdm-common.h"
|
||||
#include "log.h"
|
||||
#include "libdm-file.h"
|
||||
|
||||
#ifdef DM_COMPAT
|
||||
# include "libdm-compat.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <limits.h>
|
||||
|
||||
@@ -53,6 +48,13 @@
|
||||
#error The version of dm-ioctl.h included is incompatible.
|
||||
#endif
|
||||
|
||||
/* FIXME This should be exported in device-mapper.h */
|
||||
#define DM_NAME "device-mapper"
|
||||
|
||||
#define PROC_MISC "/proc/misc"
|
||||
#define PROC_DEVICES "/proc/devices"
|
||||
#define MISC_NAME "misc"
|
||||
|
||||
/* dm major version no for running kernel */
|
||||
static int _dm_version = DM_VERSION_MAJOR;
|
||||
static int _log_suppress = 0;
|
||||
@@ -114,22 +116,143 @@ static void *_align(void *ptr, unsigned int a)
|
||||
return (void *) (((unsigned long) ptr + agn) & ~agn);
|
||||
}
|
||||
|
||||
static int _get_proc_number(const char *file, const char *name,
|
||||
uint32_t *number)
|
||||
{
|
||||
FILE *fl;
|
||||
char nm[256];
|
||||
int c;
|
||||
|
||||
if (!(fl = fopen(file, "r"))) {
|
||||
log_error("%s: fopen failed: %s", file, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!feof(fl)) {
|
||||
if (fscanf(fl, "%d %255s\n", number, &nm[0]) == 2) {
|
||||
if (!strcmp(name, nm)) {
|
||||
fclose(fl);
|
||||
return 1;
|
||||
}
|
||||
} else do {
|
||||
c = fgetc(fl);
|
||||
} while (c != EOF && c != '\n');
|
||||
}
|
||||
fclose(fl);
|
||||
|
||||
log_error("%s: No entry for %s found", file, name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _control_device_number(uint32_t *major, uint32_t *minor)
|
||||
{
|
||||
if (!_get_proc_number(PROC_DEVICES, MISC_NAME, major) ||
|
||||
!_get_proc_number(PROC_MISC, DM_NAME, minor)) {
|
||||
*major = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if exists; 0 if it doesn't; -1 if it's wrong
|
||||
*/
|
||||
static int _control_exists(const char *control, uint32_t major, uint32_t minor)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if (stat(control, &buf) < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_error("%s: stat failed: %s", control,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISCHR(buf.st_mode)) {
|
||||
log_verbose("%s: Wrong inode type", control);
|
||||
if (!unlink(control))
|
||||
return 0;
|
||||
log_error("%s: unlink failed: %s", control,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (major && buf.st_rdev != MKDEV(major, minor)) {
|
||||
log_verbose("%s: Wrong device number: (%u, %u) instead of "
|
||||
"(%u, %u)", control,
|
||||
MAJOR(buf.st_mode), MINOR(buf.st_mode),
|
||||
major, minor);
|
||||
if (!unlink(control))
|
||||
return 0;
|
||||
log_error("%s: unlink failed: %s", control,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _create_control(const char *control, uint32_t major, uint32_t minor)
|
||||
{
|
||||
int ret;
|
||||
mode_t old_umask;
|
||||
|
||||
if (!major)
|
||||
return 0;
|
||||
|
||||
old_umask = umask(0022);
|
||||
ret = create_dir(dm_dir());
|
||||
umask(old_umask);
|
||||
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
log_verbose("Creating device %s (%u, %u)", control, major, minor);
|
||||
|
||||
if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
|
||||
MKDEV(major, minor)) < 0) {
|
||||
log_error("%s: mknod failed: %s", control, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!set_selinux_context(control)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _open_control(void)
|
||||
{
|
||||
char control[PATH_MAX];
|
||||
uint32_t major = 0, minor;
|
||||
|
||||
if (_control_fd != -1)
|
||||
return 1;
|
||||
|
||||
snprintf(control, sizeof(control), "%s/control", dm_dir());
|
||||
|
||||
if (!_control_device_number(&major, &minor))
|
||||
log_error("Is device-mapper driver missing from kernel?");
|
||||
|
||||
if (!_control_exists(control, major, minor) &&
|
||||
!_create_control(control, major, minor))
|
||||
goto error;
|
||||
|
||||
if ((_control_fd = open(control, O_RDWR)) < 0) {
|
||||
log_error("%s: open failed: %s", control, strerror(errno));
|
||||
log_error("Is device-mapper driver missing from kernel?");
|
||||
return 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
log_error("Failure to communicate with kernel device-mapper driver.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dm_task_destroy(struct dm_task *dmt)
|
||||
@@ -495,9 +618,14 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (dmi->flags & DM_BUFFER_FULL_FLAG)
|
||||
/* FIXME Increase buffer size and retry operation (if query) */
|
||||
log_error("Warning: libdevmapper buffer too small for data");
|
||||
|
||||
switch (dmt->type) {
|
||||
case DM_DEVICE_CREATE:
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev));
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
|
||||
dmt->uid, dmt->gid, dmt->mode);
|
||||
break;
|
||||
|
||||
case DM_DEVICE_REMOVE:
|
||||
@@ -511,7 +639,8 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
||||
case DM_DEVICE_MKNODES:
|
||||
if (dmi->flags & DM_EXISTS_FLAG)
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
|
||||
MINOR(dmi->dev));
|
||||
MINOR(dmi->dev),
|
||||
dmt->uid, dmt->gid, dmt->mode);
|
||||
else
|
||||
rm_dev_node(dmt->dev_name);
|
||||
break;
|
||||
@@ -800,6 +929,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;
|
||||
@@ -1152,7 +1288,8 @@ int dm_task_run(struct dm_task *dmt)
|
||||
if (dmt->type == DM_DEVICE_CREATE && dmt->head)
|
||||
return _create_and_load_v4(dmt);
|
||||
|
||||
if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name)
|
||||
if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
|
||||
!dmt->uuid && dmt->major <= 0)
|
||||
return _mknodes_v4(dmt);
|
||||
|
||||
if (!_open_control())
|
||||
@@ -1168,8 +1305,13 @@ 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 : "");
|
||||
if (ioctl(_control_fd, command, dmi) < 0) {
|
||||
if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
|
||||
@@ -1189,22 +1331,28 @@ int dm_task_run(struct dm_task *dmt)
|
||||
ignore_error:
|
||||
switch (dmt->type) {
|
||||
case DM_DEVICE_CREATE:
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev));
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
|
||||
dmt->uid, dmt->gid, dmt->mode);
|
||||
break;
|
||||
|
||||
case DM_DEVICE_REMOVE:
|
||||
rm_dev_node(dmt->dev_name);
|
||||
/* FIXME Kernel needs to fill in dmi->name */
|
||||
if (dmt->dev_name)
|
||||
rm_dev_node(dmt->dev_name);
|
||||
break;
|
||||
|
||||
case DM_DEVICE_RENAME:
|
||||
rename_dev_node(dmt->dev_name, dmt->newname);
|
||||
/* FIXME Kernel needs to fill in dmi->name */
|
||||
if (dmt->dev_name)
|
||||
rename_dev_node(dmt->dev_name, dmt->newname);
|
||||
break;
|
||||
|
||||
case DM_DEVICE_MKNODES:
|
||||
if (dmi->flags & DM_EXISTS_FLAG)
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
|
||||
MINOR(dmi->dev));
|
||||
else
|
||||
add_dev_node(dmi->name, MAJOR(dmi->dev),
|
||||
MINOR(dmi->dev),
|
||||
dmt->uid, dmt->gid, dmt->mode);
|
||||
else if (dmt->dev_name)
|
||||
rm_dev_node(dmt->dev_name);
|
||||
break;
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#define LIB_DMTARGETS_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct dm_ioctl;
|
||||
struct dm_ioctl_v1;
|
||||
@@ -40,6 +41,9 @@ struct dm_task {
|
||||
uint32_t event_nr;
|
||||
int major;
|
||||
int minor;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t mode;
|
||||
union {
|
||||
struct dm_ioctl *v4;
|
||||
struct dm_ioctl_v1 *v1;
|
||||
@@ -47,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.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-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 the device-mapper userspace tools.
|
||||
*
|
||||
@@ -13,20 +13,14 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "libdm-targets.h"
|
||||
#include "libdm-common.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "kdev_t.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
@@ -63,7 +57,7 @@ static void _default_log(int level, const char *file, int line,
|
||||
if (level < _LOG_WARN)
|
||||
fprintf(stderr, "\n");
|
||||
else
|
||||
printf("\n");
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
dm_log_fn _log = _default_log;
|
||||
@@ -100,19 +94,22 @@ struct dm_task *dm_task_create(int type)
|
||||
{
|
||||
struct dm_task *dmt = malloc(sizeof(*dmt));
|
||||
|
||||
if (!dm_check_version())
|
||||
return NULL;
|
||||
|
||||
if (!dmt) {
|
||||
log_error("dm_task_create: malloc(%d) failed", sizeof(*dmt));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dm_check_version())
|
||||
return NULL;
|
||||
|
||||
memset(dmt, 0, sizeof(*dmt));
|
||||
|
||||
dmt->type = type;
|
||||
dmt->minor = -1;
|
||||
dmt->major = -1;
|
||||
dmt->uid = DEVICE_UID;
|
||||
dmt->gid = DEVICE_GID;
|
||||
dmt->mode = DEVICE_MODE;
|
||||
|
||||
return dmt;
|
||||
}
|
||||
@@ -202,7 +199,7 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
static int _set_selinux_context(const char *path)
|
||||
int set_selinux_context(const char *path)
|
||||
{
|
||||
security_context_t scontext;
|
||||
|
||||
@@ -226,11 +223,13 @@ static int _set_selinux_context(const char *path)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
|
||||
static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
uid_t uid, gid_t gid, mode_t mode)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct stat info;
|
||||
dev_t dev = MKDEV(major, minor);
|
||||
mode_t old_mask;
|
||||
|
||||
_build_dev_path(path, sizeof(path), dev_name);
|
||||
|
||||
@@ -241,6 +240,7 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If right inode already exists we don't touch uid etc. */
|
||||
if (info.st_rdev == dev)
|
||||
return 1;
|
||||
|
||||
@@ -251,12 +251,20 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
|
||||
}
|
||||
}
|
||||
|
||||
if (mknod(path, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, dev) < 0) {
|
||||
old_mask = umask(0);
|
||||
if (mknod(path, S_IFBLK | mode, dev) < 0) {
|
||||
log_error("Unable to make device node for '%s'", dev_name);
|
||||
return 0;
|
||||
}
|
||||
umask(old_mask);
|
||||
|
||||
if (chown(path, uid, gid) < 0) {
|
||||
log_error("%s: chown failed: %s", path, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!_set_selinux_context(path))
|
||||
if (!set_selinux_context(path))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
@@ -324,11 +332,12 @@ typedef enum {
|
||||
} node_op_t;
|
||||
|
||||
static int _do_node_op(node_op_t type, const char *dev_name, uint32_t major,
|
||||
uint32_t minor, const char *old_name)
|
||||
uint32_t minor, uid_t uid, gid_t gid, mode_t mode,
|
||||
const char *old_name)
|
||||
{
|
||||
switch (type) {
|
||||
case NODE_ADD:
|
||||
return _add_dev_node(dev_name, major, minor);
|
||||
return _add_dev_node(dev_name, major, minor, uid, gid, mode);
|
||||
case NODE_DEL:
|
||||
return _rm_dev_node(dev_name);
|
||||
case NODE_RENAME:
|
||||
@@ -346,6 +355,9 @@ struct node_op_parms {
|
||||
char *dev_name;
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t mode;
|
||||
char *old_name;
|
||||
char names[0];
|
||||
};
|
||||
@@ -358,7 +370,8 @@ static void _store_str(char **pos, char **ptr, const char *str)
|
||||
}
|
||||
|
||||
static int _stack_node_op(node_op_t type, const char *dev_name, uint32_t major,
|
||||
uint32_t minor, const char *old_name)
|
||||
uint32_t minor, uid_t uid, gid_t gid, mode_t mode,
|
||||
const char *old_name)
|
||||
{
|
||||
struct node_op_parms *nop;
|
||||
size_t len = strlen(dev_name) + strlen(old_name) + 2;
|
||||
@@ -373,6 +386,9 @@ static int _stack_node_op(node_op_t type, const char *dev_name, uint32_t major,
|
||||
nop->type = type;
|
||||
nop->major = major;
|
||||
nop->minor = minor;
|
||||
nop->uid = uid;
|
||||
nop->gid = gid;
|
||||
nop->mode = mode;
|
||||
|
||||
_store_str(&pos, &nop->dev_name, dev_name);
|
||||
_store_str(&pos, &nop->old_name, old_name);
|
||||
@@ -390,25 +406,27 @@ static void _pop_node_ops(void)
|
||||
list_iterate_safe(noph, nopht, &_node_ops) {
|
||||
nop = list_item(noph, struct node_op_parms);
|
||||
_do_node_op(nop->type, nop->dev_name, nop->major, nop->minor,
|
||||
nop->old_name);
|
||||
nop->uid, nop->gid, nop->mode, nop->old_name);
|
||||
list_del(&nop->list);
|
||||
free(nop);
|
||||
}
|
||||
}
|
||||
|
||||
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
|
||||
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
uid_t uid, gid_t gid, mode_t mode)
|
||||
{
|
||||
return _stack_node_op(NODE_ADD, dev_name, major, minor, "");
|
||||
return _stack_node_op(NODE_ADD, dev_name, major, minor, uid, gid, mode,
|
||||
"");
|
||||
}
|
||||
|
||||
int rename_dev_node(const char *old_name, const char *new_name)
|
||||
{
|
||||
return _stack_node_op(NODE_RENAME, new_name, 0, 0, old_name);
|
||||
return _stack_node_op(NODE_RENAME, new_name, 0, 0, 0, 0, 0, old_name);
|
||||
}
|
||||
|
||||
int rm_dev_node(const char *dev_name)
|
||||
{
|
||||
return _stack_node_op(NODE_DEL, dev_name, 0, 0, "");
|
||||
return _stack_node_op(NODE_DEL, dev_name, 0, 0, 0, 0, 0, "");
|
||||
}
|
||||
|
||||
void update_devs(void)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-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 the device-mapper userspace tools.
|
||||
*
|
||||
@@ -22,11 +22,14 @@ struct target *create_target(uint64_t start,
|
||||
uint64_t len,
|
||||
const char *type, const char *params);
|
||||
|
||||
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major);
|
||||
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major,
|
||||
uid_t uid, gid_t gid, mode_t mode);
|
||||
int rm_dev_node(const char *dev_name);
|
||||
int rename_dev_node(const char *old_name, const char *new_name);
|
||||
void update_devs(void);
|
||||
|
||||
int set_selinux_context(const char *path);
|
||||
|
||||
#define DM_LIB_VERSION @DM_LIB_VERSION@
|
||||
|
||||
#endif
|
||||
|
73
libdm/libdm-file.c
Normal file
73
libdm/libdm-file.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* 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 "lib.h"
|
||||
#include "libdm-file.h"
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <malloc.h>
|
||||
|
||||
static int _create_dir_recursive(const char *dir)
|
||||
{
|
||||
char *orig, *s;
|
||||
int rc;
|
||||
|
||||
log_verbose("Creating directory \"%s\"", dir);
|
||||
/* Create parent directories */
|
||||
orig = s = strdup(dir);
|
||||
while ((s = strchr(s, '/')) != NULL) {
|
||||
*s = '\0';
|
||||
if (*orig) {
|
||||
rc = mkdir(orig, 0777);
|
||||
if (rc < 0 && errno != EEXIST) {
|
||||
log_error("%s: mkdir failed: %s", orig,
|
||||
strerror(errno));
|
||||
free(orig);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*s++ = '/';
|
||||
}
|
||||
free(orig);
|
||||
|
||||
/* Create final directory */
|
||||
rc = mkdir(dir, 0777);
|
||||
if (rc < 0 && errno != EEXIST) {
|
||||
log_error("%s: mkdir failed: %s", orig,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int create_dir(const char *dir)
|
||||
{
|
||||
struct stat info;
|
||||
|
||||
if (!*dir)
|
||||
return 1;
|
||||
|
||||
if (stat(dir, &info) < 0)
|
||||
return _create_dir_recursive(dir);
|
||||
|
||||
if (S_ISDIR(info.st_mode))
|
||||
return 1;
|
||||
|
||||
log_error("Directory \"%s\" not found", dir);
|
||||
return 0;
|
||||
}
|
||||
|
25
libdm/libdm-file.h
Normal file
25
libdm/libdm-file.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* 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 LIB_DMFILE_H
|
||||
#define LIB_DMFILE_H
|
||||
|
||||
/*
|
||||
* Create directory (recursively) if necessary. Return 1
|
||||
* if directory was successfully created (or already exists), else 0.
|
||||
*/
|
||||
int create_dir(const char *dir);
|
||||
|
||||
#endif
|
@@ -30,7 +30,7 @@ MAN8DIR=${mandir}/man8
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
ifeq ("@CLVMD@", "yes")
|
||||
ifneq ("@CLVMD@", "none")
|
||||
install: install_cluster
|
||||
endif
|
||||
|
||||
|
@@ -4,26 +4,34 @@ lvchange \- change attributes of a logical volume
|
||||
.SH SYNOPSIS
|
||||
.B lvchange
|
||||
[\-\-addtag Tag]
|
||||
[\-A/\-\-autobackup y/n] [\-a/\-\-available y/n]
|
||||
[\-A/\-\-autobackup y/n] [\-a/\-\-available y/n/ey/en/ly/ln]
|
||||
[\-\-alloc AllocationPolicy]
|
||||
[\-C/\-\-contiguous y/n] [\-d/\-\-debug] [\-\-deltag Tag]
|
||||
[\-h/\-?/\-\-help]
|
||||
[\-\-ignorelockingfailure]
|
||||
[\-M/\-\-persistent y/n] [\-\-minor minor]
|
||||
[\-P/\-\-partial y/n]
|
||||
[\-p/\-\-permission r/w] [\-r/\-\-readahead ReadAheadSectors]
|
||||
[\-\-refresh]
|
||||
[\-t/\-\-test]
|
||||
[\-v/\-\-verbose] LogicalVolumePath [LogicalVolumePath...]
|
||||
.SH DESCRIPTION
|
||||
lvchange allows you to change the attributes of a logical volume.
|
||||
lvchange allows you to change the attributes of a logical volume
|
||||
including making them known to the kernel ready for use.
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
.I \-a, \-\-available y/n
|
||||
.I \-a, \-\-available y/n/ey/en/ly/ln
|
||||
Controls the availability of the logical volumes for use.
|
||||
This is (among others) useful for changing the logical volume's name
|
||||
( see
|
||||
.B lvrename(8)
|
||||
) safely.
|
||||
Communicates with the kernel device-mapper driver via
|
||||
libdevmapper to activate (-ay) or deactivate (-an) the
|
||||
logical volumes.
|
||||
.IP
|
||||
If clustered locking is enabled, -ae will activate exclusively
|
||||
on one node and -aly will activate only on the local node.
|
||||
To deactivate only on the local node use -aln.
|
||||
Logical volumes with single-host snapshots are always activated
|
||||
exclusively because they can only be used on one node at once.
|
||||
.TP
|
||||
.I \-C, \-\-contiguous y/n
|
||||
Tries to set or reset the contiguous allocation policy for
|
||||
@@ -42,11 +50,18 @@ Change access permission to read-only or read/write.
|
||||
.TP
|
||||
.I \-r, \-\-readahead ReadAheadSectors
|
||||
Change read ahead sector count per logical between 2 and 120.
|
||||
Not used by device-mapper.
|
||||
For compatability with LVM1 only. Ignored by LVM2.
|
||||
.TP
|
||||
.I \-\-refresh
|
||||
If the logical volume is active, reload its metadata.
|
||||
This is not necessary in normal operation, but may be useful
|
||||
if something has gone wrong or if you're doing clustering
|
||||
manually without a clustered lock manager.
|
||||
.SH Examples
|
||||
"lvchange -p r vg00/lvol1" changes the permission on
|
||||
"lvchange -pr vg00/lvol1" changes the permission on
|
||||
volume lvol1 in volume group vg00 to be read-only.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR lvcreate (8)
|
||||
.BR lvcreate (8),
|
||||
.BR vgchange (8)
|
||||
|
@@ -4,6 +4,7 @@ lvcreate \- create a logical volume in an existing volume group
|
||||
.SH SYNOPSIS
|
||||
.B lvcreate
|
||||
[\-\-addtag Tag]
|
||||
[\-\-alloc AllocationPolicy]
|
||||
[\-A/\-\-autobackup y/n] [\-C/\-\-contiguous y/n] [\-d/\-\-debug]
|
||||
[\-h/\-?/\-\-help]
|
||||
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
|
||||
|
@@ -10,12 +10,15 @@ lvdisplay \- display attributes of a logical volume
|
||||
.SH DESCRIPTION
|
||||
lvdisplay allows you to see the attributes of a logical volume
|
||||
like size, read/write status, snapshot information etc.
|
||||
.P
|
||||
\fBlvs\fP (8) is an alternative that provides the same information
|
||||
in the style of \fBps\fP (1).
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
.I \-c, \-\-colon
|
||||
Deprecated. To be replaced with a more-powerful reporting tool.
|
||||
Generate colon separated output for easier parsing in scripts or programs.
|
||||
N.B. \fBlvs\fP (8) provides considerably more control over the output.
|
||||
.nf
|
||||
|
||||
The values are:
|
||||
|
@@ -3,6 +3,7 @@
|
||||
lvextend \- extend the size of a logical volume
|
||||
.SH SYNOPSIS
|
||||
.B lvextend
|
||||
[\-\-alloc AllocationPolicy]
|
||||
[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
|
||||
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
|
||||
{\-l/\-\-extents [+]LogicalExtentsNumber |
|
||||
|
75
man/lvm.8
75
man/lvm.8
@@ -18,23 +18,44 @@ If \fBlvm\fP is invoked with argv[0] set to the name of a specific
|
||||
LVM command (for example by using a hard or soft link) it acts as
|
||||
that command.
|
||||
.LP
|
||||
Where commands take VG or LV names as arguments, the full path name is
|
||||
optional. An LV called "lvol0" in a VG called "vg0" can be specified
|
||||
as "vg0/lvol0". Where a list of VGs is required but is left empty,
|
||||
a list of all VGs will be substituted. Where a list of LVs is required
|
||||
but a VG is given, a list of all the LVs in that VG will be substituted.
|
||||
So "lvdisplay vg0" will display all the LVs in "vg0".
|
||||
Tags can also be used - see \fBaddtag\fP below.
|
||||
.LP
|
||||
One advantage of using the built-in shell is that configuration
|
||||
information is cached internally between commands.
|
||||
information gets cached internally between commands.
|
||||
.LP
|
||||
A file containing a simple script with one command per line
|
||||
can also be given on the command line. The script can also be
|
||||
executed directly if the first line is #! followed by the absolute
|
||||
path of \fBlvm\fP.
|
||||
.SH BUILT-IN COMMANDS
|
||||
The following commands are built into lvm without links normally
|
||||
being created in the filesystem for them.
|
||||
.TP
|
||||
\fBdumpconfig\fP \(em Display the configuration information after
|
||||
loading \fBlvm.conf\fP (8) and any other configuration files.
|
||||
.TP
|
||||
\fBformats\fP \(em Display recognised metadata formats.
|
||||
.TP
|
||||
\fBhelp\fP \(em Display the help text.
|
||||
.TP
|
||||
\fBpvdata\fP \(em Not implemented in LVM2.
|
||||
.TP
|
||||
\fBsegtypes\fP \(em Display recognised logical volume segment types.
|
||||
.TP
|
||||
\fBversion\fP \(em Display version information.
|
||||
.LP
|
||||
Where commands take VG or LV names as arguments, the full path name is
|
||||
optional. An LV called "lvol0" in a VG called "vg0" can be specified
|
||||
as "vg0/lvol0". If a list of VGs is required but is left empty, a list of
|
||||
all VGs will be substituted. If a list of LVs is required
|
||||
but a VG is given, a list of all the LVs in that VG will be substituted.
|
||||
So "lvdisplay vg0" will display all the LVs in "vg0".
|
||||
The following commands are not implemented in LVM2 but might be
|
||||
in future: lvmsadc, lvmsar, pvdata, pvresize.
|
||||
.SH OPTIONS
|
||||
The following options are available for many of the commands and are
|
||||
not documented on individual manual pages.
|
||||
The following options are available for many of the commands.
|
||||
They are implemented generically and documented here rather
|
||||
than repeated on individual manual pages.
|
||||
.TP
|
||||
\fB-h | --help\fP \(em Display the help text.
|
||||
.TP
|
||||
@@ -54,6 +75,10 @@ Overrides -d and -v.
|
||||
.TP
|
||||
\fB-t | --test\fP \(em Run in test mode.
|
||||
Commands will not update metadata.
|
||||
This is implemented by disabling all metadata writing but nevertheless
|
||||
returning success to the calling function. This may lead to unusual
|
||||
error messages in multi-stage operations if a tool relies on reading
|
||||
back metadata it believes has changed but hasn't.
|
||||
.TP
|
||||
\fB--driverloaded\fP { \fBy\fP | \fBn\fP }
|
||||
Whether or not the device-mapper kernel driver is loaded.
|
||||
@@ -109,6 +134,27 @@ Characters allowed in tags are: A-Z a-z 0-9 _ + . -
|
||||
.TP
|
||||
\fB--deltag tag\fP
|
||||
Delete the tag \fBtag\fP from a PV, VG or LV, if it's present.
|
||||
.TP
|
||||
\fB--alloc AllocationPolicy\fP
|
||||
The allocation policy to use: \fBcontiguous\fP, \fBnormal\fP, \fBanywhere\fP or \fBinherit\fP.
|
||||
When a command needs to allocate physical extents from the volume group,
|
||||
the allocation policy controls how they are chosen.
|
||||
Each volume group and logical volume has an allocation policy.
|
||||
The default for a volume group is \fBnormal\fP which applies
|
||||
common-sense rules such as not placing parallel stripes on the same
|
||||
physical volume. The default for a logical volume is \fBinherit\fP
|
||||
which applies the same policy as for the volume group. These policies can
|
||||
be changed using \fBlvchange\fP (8) and \fBvgchange\fP (8) or over-ridden
|
||||
on the command line of any command that performs allocation.
|
||||
The \fBcontiguous\fP policy requires that new extents are adjacent to
|
||||
existing extents. If there are sufficient free extents to satisfy
|
||||
an allocation request but \fBnormal\fP doesn't use them,
|
||||
\fBanywhere\fP will - even if that reduces performance by
|
||||
placing two stripes on the same physical volume.
|
||||
.IP
|
||||
N.B. The policies described above are not implemented fully yet.
|
||||
In particular, \fBcontiguous\fP does not place new extents adjacent to existing
|
||||
extents and \fBanywhere\fP is not implemented at all.
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.TP
|
||||
\fBLVM_SYSTEM_DIR\fP
|
||||
@@ -131,31 +177,42 @@ All tools return a status code of zero on success or non-zero on failure.
|
||||
.br
|
||||
.I $HOME/.lvm_history
|
||||
.SH SEE ALSO
|
||||
.BR clvmd (8),
|
||||
.BR lvchange (8),
|
||||
.BR lvcreate (8),
|
||||
.BR lvdisplay (8),
|
||||
.BR lvextend (8),
|
||||
.BR lvmchange (8),
|
||||
.BR lvmdiskscan (8),
|
||||
.BR lvreduce (8),
|
||||
.BR lvremove (8),
|
||||
.BR lvrename (8),
|
||||
.BR lvresize (8),
|
||||
.BR lvs (8),
|
||||
.BR lvscan (8),
|
||||
.BR pvchange (8),
|
||||
.BR pvcreate (8),
|
||||
.BR pvdisplay (8),
|
||||
.BR pvmove (8),
|
||||
.BR pvremove (8),
|
||||
.BR pvs (8),
|
||||
.BR pvscan (8),
|
||||
.BR vgcfgbackup (8),
|
||||
.BR vgchange (8),
|
||||
.BR vgck (8),
|
||||
.BR vgconvert (8),
|
||||
.BR vgcreate (8),
|
||||
.BR vgdisplay (8),
|
||||
.BR vgextend (8),
|
||||
.BR vgimport (8),
|
||||
.BR vgmerge (8),
|
||||
.BR vgmknodes (8),
|
||||
.BR vgreduce (8),
|
||||
.BR vgremove (8),
|
||||
.BR vgrename (8),
|
||||
.BR vgs (8),
|
||||
.BR vgscan (8),
|
||||
.BR vgsplit (8),
|
||||
.BR readline (3),
|
||||
.BR lvm.conf (5)
|
||||
|
||||
|
223
man/lvm.conf.5
223
man/lvm.conf.5
@@ -4,9 +4,13 @@ lvm.conf \- Configuration file for LVM2
|
||||
.SH SYNOPSIS
|
||||
.B /etc/lvm/lvm.conf
|
||||
.SH DESCRIPTION
|
||||
lvm.conf is loaded once, during the initialisation phase of
|
||||
\fBlvm\fP.
|
||||
lvm.conf is loaded during the initialisation phase of
|
||||
\fBlvm\fP (8). This file can in turn lead to other files
|
||||
being loaded - settings read in later override earlier
|
||||
settings. File timestamps are checked between commands and if
|
||||
any have changed, all the files are reloaded.
|
||||
.LP
|
||||
Use \fBlvm dumpconfig\fP to check what settings are in use.
|
||||
.SH SYNTAX
|
||||
.LP
|
||||
This section describes the configuration file syntax.
|
||||
@@ -69,7 +73,8 @@ The sections that may be present in the file are:
|
||||
\fBdevices\fP \(em Device settings
|
||||
.IP
|
||||
\fBdir\fP \(em Directory in which to create volume group device nodes.
|
||||
Defaults to "/dev".
|
||||
Defaults to "/dev". Commands also accept this as a prefix on volume
|
||||
group names.
|
||||
.IP
|
||||
\fBscan\fP \(em List of directories to scan recursively for
|
||||
LVM physical volumes.
|
||||
@@ -81,8 +86,13 @@ Patterns are regular expressions delimited by any character and preceded
|
||||
by \fBa\fP (for accept) or \fBr\fP (for reject). The list is traversed
|
||||
in order, and the first regex that matches determines if the device
|
||||
will be accepted or rejected (ignored). Devices that don't match
|
||||
any patterns are accepted.
|
||||
For example, to ignore /dev/cdrom you could use:
|
||||
any patterns are accepted. If you want to reject patterns that
|
||||
don't match, end the list with "r/.*/".
|
||||
If there are several names for the same device (e.g. symbolic links
|
||||
in /dev), if any name matches any \fBa\fP pattern, the
|
||||
device is accepted; otherwise if any name matches any \fBr\fP
|
||||
pattern it is rejected; otherwise it is accepted.
|
||||
As an example, to ignore /dev/cdrom you could use:
|
||||
\fBdevices { filter=["r|cdrom|"] }\fP
|
||||
.IP
|
||||
\fBcache\fP \(em Persistent filter cache file.
|
||||
@@ -95,9 +105,24 @@ Defaults to 1.
|
||||
\fBtypes\fP \(em List of pairs of additional acceptable block device types
|
||||
found in /proc/devices together with maximum (non-zero) number of
|
||||
partitions (normally 16). By default, LVM2 supports ide, sd, md, loop,
|
||||
dasd, dac960, nbd, ida, cciss, ubd and ataraid. Block devices with major
|
||||
numbers of different types are ignored by LVM2. Example:
|
||||
\fBtypes = ["fd", 16]\fP
|
||||
dasd, dac960, nbd, ida, cciss, ubd, ataraid, drbd, power2, i2o_block
|
||||
and iseries/vd. Block devices with major
|
||||
numbers of different types are ignored by LVM2.
|
||||
Example: \fBtypes = ["fd", 16]\fP.
|
||||
To create physical volumes on device-mapper volumes
|
||||
created outside LVM2, perhaps encrypted ones from \fBcryptsetup\fP,
|
||||
you'll need \fBtypes = ["device-mapper", 16]\fP. But if you do this,
|
||||
be careful to avoid recursion within LVM2. The figure for number
|
||||
of partitions is not currently used in LVM2 - and might never be.
|
||||
.IP
|
||||
\fBsysfs_scan\fP (em If set to 1 and your kernel supports sysfs and
|
||||
it is mounted, sysfs will be used as a quick way of filtering out
|
||||
block devices that are not present.
|
||||
.IP
|
||||
\fBmd_component_detection\fP (em If set to 1, LVM2 will ignore devices
|
||||
used as components of software RAID (md) devices by looking for md
|
||||
superblocks. This doesn't always work satisfactorily e.g. if a device
|
||||
has been reused without wiping the md superblocks first.
|
||||
.TP
|
||||
\fBlog\fP \(em Default log settings
|
||||
.IP
|
||||
@@ -120,7 +145,8 @@ See /usr/include/sys/syslog.h for safe facility values to use.
|
||||
For example, LOG_LOCAL0 might be 128.
|
||||
.IP
|
||||
\fBindent\fP \(em When set to 1 (the default) messages are indented
|
||||
according to their severity. Set to 0 to turn off indentation.
|
||||
according to their severity, two spaces per level.
|
||||
Set to 0 to turn off indentation.
|
||||
.IP
|
||||
\fBcommand_names\fP \(em When set to 1, the command name is used as a
|
||||
prefix for each message.
|
||||
@@ -128,6 +154,11 @@ Default is 0 (off).
|
||||
.IP
|
||||
\fBprefix\fP \(em Prefix used for all messages (after the command name).
|
||||
Default is two spaces.
|
||||
.IP
|
||||
\fBactivation\fP \(em Set to 1 to log messages while
|
||||
devices are suspended during activation.
|
||||
Only set this temporarily while debugging a problem because
|
||||
in low memory situations this setting can cause your machine to lock up.
|
||||
.TP
|
||||
\fBbackup\fP \(em Configuration for metadata backups.
|
||||
.IP
|
||||
@@ -165,8 +196,13 @@ Defaults to 30.
|
||||
.TP
|
||||
\fBglobal\fP \(em Global settings
|
||||
.IP
|
||||
\fBtest\fP \(em If set to 1, run tools in test mode i.e. no metadata
|
||||
gets updated.
|
||||
\fBtest\fP \(em If set to 1, run tools in test mode i.e. no changes to
|
||||
the on-disk metadata will get made. It's equivalent to having the
|
||||
-t option on every command.
|
||||
.IP
|
||||
\fBactivation\fP \(em Set to 0 to turn off all communication with
|
||||
the device-mapper driver. Useful if you want to manipulate logical
|
||||
volumes while device-mapper is not present in your kernel.
|
||||
.IP
|
||||
\fBproc\fP \(em Mount point of proc filesystem.
|
||||
Defaults to /proc.
|
||||
@@ -175,12 +211,167 @@ Defaults to /proc.
|
||||
Interpreted as octal if the first digit is zero.
|
||||
Defaults to 077.
|
||||
Use 022 to allow other users to read the files by default.
|
||||
.IP
|
||||
\fBformat\fP \(em The default value of \fB--metadatatype\fP used
|
||||
to determine which format of metadata to use when creating new
|
||||
physical volumes and volume groups. \fBlvm1\fP or \fBlvm2\fP.
|
||||
.IP
|
||||
\fBfallback_to_lvm1\fP \(em Set this to 1 if you need to
|
||||
be able to switch between 2.4 kernels using LVM1 and kernels
|
||||
including device-mapper.
|
||||
The LVM2 tools should be installed as normal and
|
||||
the LVM1 tools should be installed with a .lvm1 suffix e.g.
|
||||
vgscan.lvm1.
|
||||
If an LVM2 tool is then run but unable to communicate
|
||||
with device-mapper, it will automatically invoke the equivalent LVM1
|
||||
version of the tool. Note that for LVM1 tools to
|
||||
manipulate physical volumes and volume groups created by LVM2 you
|
||||
must use \fB--metadataformat lvm1\fP when creating them.
|
||||
.IP
|
||||
\fBlibrary_dir\fP \(em A directory searched for LVM2's shared libraries
|
||||
ahead of the places \fBdlopen\fP (3) searches.
|
||||
.IP
|
||||
\fBformat_libraries\fP \(em A list of shared libraries to load that contain
|
||||
code to process different formats of metadata. For example, liblvm2formatpool.so
|
||||
is needed to read GFS pool metadata if LVM2 was configured \fB--with-pool=shared\fP.
|
||||
.IP
|
||||
\fBlocking_type\fP \(em What type of locking to use.
|
||||
1 is the default, which use flocks on files in \fBlocking_dir\fP
|
||||
(see below) to
|
||||
avoid conflicting LVM2 commands running concurrently on a single
|
||||
machine. 0 disables locking and risks corrupting your metadata.
|
||||
If set to 2, the tools will load the external \fBlocking_library\fP
|
||||
(see below).
|
||||
If the tools were configured \fB--with-cluster=internal\fP
|
||||
(the default) then 3 means to use built-in cluster-wide locking.
|
||||
All changes to logical volumes and their states are communicated
|
||||
using locks.
|
||||
.IP
|
||||
\fBlocking_dir\fP \(em The directory LVM2 places its file locks
|
||||
if \fBlocking_type\fP is set to 1. The default is \fB/var/lock/lvm\fP.
|
||||
.IP
|
||||
\fBlocking_library\fP \(em The name of the external locking
|
||||
library to load if \fBlocking_type\fP is set to 2.
|
||||
The default is \fBlvm2_locking.so\fP. If you need to write
|
||||
such a library, look at the lib/locking source code directory.
|
||||
.TP
|
||||
\fBtags\fP \(em Host tag settings
|
||||
.IP
|
||||
\fBhosttags\fP \(em If set to 1, create a host tag with the machine name.
|
||||
Setting this to 0 does nothing, neither creating nor destroying any tag.
|
||||
The machine name used is the nodename as returned by \fBuname\fP (2).
|
||||
.IP
|
||||
Additional host tags to be set can be listed here as subsections.
|
||||
The @ prefix for tags is optional.
|
||||
Each of these host tag subsections can contain a \fBhost_list\fP
|
||||
array of host names. If any one of these entries matches the machine
|
||||
name exactly then the host tag gets defined on this particular host,
|
||||
otherwise it doesn't.
|
||||
.IP
|
||||
After lvm.conf has been processed, LVM2 works through each host
|
||||
tag that has been defined in turn, and if there is a configuration
|
||||
file called lvm_\fB<host_tag>\fP.conf it attempts to load it.
|
||||
Any settings read in override settings found in earlier files.
|
||||
Any additional host tags defined get appended to the search list,
|
||||
so in turn they can lead to further configuration files being processed.
|
||||
Use \fBlvm dumpconfig\fP to check the result of config
|
||||
file processing.
|
||||
.IP
|
||||
The following example always sets host tags \fBtag1\fP and
|
||||
sets \fBtag2\fP on machines fs1 and fs2:
|
||||
.IP
|
||||
tags { tag1 { } tag2 { host_list = [ "fs1", "fs2" ] } }
|
||||
.IP
|
||||
These options are useful if you are replicating configuration files
|
||||
around a cluster. Use of \fBhosttags = 1\fP means every machine
|
||||
can have static and identical local configuration files yet use
|
||||
different settings and activate different logical volumes by
|
||||
default. See also \fBvolume_list\fP below and \fB--addtag\fP
|
||||
in \fBlvm\fP (8).
|
||||
.TP
|
||||
\fBactivation\fP \(em Settings affecting device-mapper activation
|
||||
.IP
|
||||
\fBmissing_stripe_filler\fP \(em When activating an incomplete
|
||||
logical volume in partial mode, this missing data is replaced
|
||||
with this device. It could perhaps be a block device that always
|
||||
returns an error when it is accessed, or one that always
|
||||
returns zeros. See \fBlvcreate\fP (8) for how to create
|
||||
such devices.
|
||||
.IP
|
||||
\fBmirror_region_size\fP \(em Unit size in KB for copy operations
|
||||
when mirroring.
|
||||
.IP
|
||||
\fBreserved_memory\fP, \fBreserved_stack\fP \(em How many KB to reserve
|
||||
for LVM2 to use while logical volumes are suspended. If insufficient
|
||||
memory is reserved before suspension, there is a risk of machine deadlock.
|
||||
.IP
|
||||
\fBprocess_priority\fP \(em The nice value to use while devices are
|
||||
suspended. This is set to a high priority so that logical volumes
|
||||
are suspended (with I/O generated by other processes to those
|
||||
logical volumes getting queued) for the shortest possible time.
|
||||
.IP
|
||||
\fBvolume_list\fP \(em This acts as a filter through which
|
||||
all requests to activate a logical volume on this machine
|
||||
are passed. A logical volume is only activated if it matches
|
||||
an item in the list. Tags must be preceded by @ and are checked
|
||||
against all tags defined in the logical volume and volume group
|
||||
metadata for a match.
|
||||
@* is short-hand to check every tag set on the host machine (see
|
||||
\fBtags\fP above).
|
||||
Logical volume and volume groups can also be included in the list
|
||||
by name e.g. vg00, vg00/lvol1.
|
||||
.TP
|
||||
\fBmetadata\fP \(em Advanced metadata settings
|
||||
.IP
|
||||
\fBpvmetadatacopies\fP \(em When creating a physical volume using the
|
||||
LVM2 metadata format, this is the default number of copies of metadata
|
||||
to store on each physical volume.
|
||||
Currently it can be set to 0, 1 or 2. The default is 1.
|
||||
If set to 2, one copy is placed at the beginning of the disk
|
||||
and the other is placed at the end.
|
||||
It can be overridden on the command line with \fB--metadatacopies\fP.
|
||||
If creating a volume group with just one physical volume, it's a
|
||||
good idea to have 2 copies. If creating a large volume group with
|
||||
many physical volumes, you may decide that 3 copies of the metadata
|
||||
is sufficient, i.e. setting it to 1 on three of the physical volumes,
|
||||
and 0 on the rest. Every volume group must contain at least one
|
||||
physical volume with at least 1 copy of the metadata (unless using
|
||||
the text files described below). The disadvantage of having lots
|
||||
of copies is that every time the tools access the volume group, every
|
||||
copy of the metadata has to be accessed, and this slows down the
|
||||
tools.
|
||||
.IP
|
||||
\fBpvmetadatasize\fP \(em Approximate number of sectors to set aside
|
||||
for each copy of the metadata. Volume groups with large numbers of
|
||||
physical or logical volumes, or volumes groups containing complex
|
||||
logical volume structures will need additional space for their metadata.
|
||||
The metadata areas are treated as circular buffers, so
|
||||
unused space becomes filled with an archive of the most recent
|
||||
previous versions of the metadata.
|
||||
.IP
|
||||
\fBdirs\fP \(em List of directories holding live copies of LVM2
|
||||
metadata as text files. These directories must not be on logical
|
||||
volumes. It is possible to use LVM2 with a couple of directories
|
||||
here, preferably on different (non-logical-volume) filesystems
|
||||
and with no other on-disk metadata, \fBpvmetadatacopies = 0\fP.
|
||||
Alternatively these directories can be in addition to the
|
||||
on-disk metadata areas. This feature was created during the
|
||||
development of the LVM2 metadata before the new on-disk metadata
|
||||
areas were designed and no longer gets tested.
|
||||
It is not supported under low-memory conditions, and it is
|
||||
important never to edit these metadata files unless you fully
|
||||
understand how things work: to make changes you should always use
|
||||
the tools as normal, or else vgcfgbackup, edit backup, vgcfgrestore.
|
||||
.SH FILES
|
||||
.I /etc/lvm/lvm.conf
|
||||
.br
|
||||
.I $HOME/.lvm_history
|
||||
.I /etc/lvm/.cache
|
||||
.I /etc/lvm/archive
|
||||
.I /etc/lvm/backup
|
||||
.I /var/lock/lvm
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8)
|
||||
.BR umask (2)
|
||||
.BR syslog (3)
|
||||
.BR lvm (8),
|
||||
.BR umask (2),
|
||||
.BR uname (2),
|
||||
.BR dlopen (3),
|
||||
.BR syslog (3),
|
||||
.BR syslog.conf (5)
|
||||
|
@@ -15,12 +15,16 @@ reduced part is lost!!!
|
||||
.br
|
||||
You should therefore ensure that any filesystem on the volume is
|
||||
resized
|
||||
.i before
|
||||
.I before
|
||||
running lvreduce so that the extents that are to be removed are not in use.
|
||||
.br.
|
||||
.br
|
||||
Shrinking snapshot logical volumes (see
|
||||
.B lvcreate(8)
|
||||
for information to create snapshots) is supported as well.
|
||||
.br
|
||||
Sizes will be rounded if necessary - for example, the volume size must
|
||||
be an exact number of extents and the size of a striped segment must
|
||||
be a multiple of the number of stripes.
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
@@ -41,11 +45,12 @@ With the - sign the value will be subtracted from
|
||||
the logical volume's actual size and without it it will be taken as
|
||||
an absolute size.
|
||||
.SH Example
|
||||
"lvreduce -l -3 /dev/vg00/lvol1" reduces the size of logical volume lvol1
|
||||
"lvreduce -l -3 vg00/lvol1" reduces the size of logical volume lvol1
|
||||
in volume group vg00 by 3 logical extents.
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR lvchange (8),
|
||||
.BR lvcreate (8),
|
||||
.BR lvextend (8),
|
||||
.BR lvresize (8),
|
||||
.BR lvchange (8)
|
||||
.BR lvm (8),
|
||||
.BR lvresize (8),
|
||||
.BR vgreduce (8)
|
||||
|
@@ -8,17 +8,28 @@ lvremove \- remove a logical volume
|
||||
[\-t/\-\-test]
|
||||
[\-v/\-\-verbose] LogicalVolumePath [LogicalVolumePath...]
|
||||
.SH DESCRIPTION
|
||||
lvremove allows you to remove one or more inactive logical volumes.
|
||||
\fBlvremove\fP removes one or more logical volumes.
|
||||
Confirmation will be requested before deactivating any active logical
|
||||
volume prior to removal. Logical volumes cannot be deactivated
|
||||
or removed while they are open (e.g. if they contain a mounted filesystem).
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
See \fBlvm\fP(8) for common options.
|
||||
.TP
|
||||
.I \-f, \-\-force
|
||||
Force remove without confirmation.
|
||||
.SH Example
|
||||
"lvremove -f /dev/vg00/lvol1" removes that inactive logical volume
|
||||
unconditionally.
|
||||
Remove active logical volumes without confirmation.
|
||||
.SH EXAMPLES
|
||||
Remove the active logical volume lvol1 in volume group vg00
|
||||
without asking for confirmation:
|
||||
.sp
|
||||
\ \fBlvremove -f vg00/lvol1\fP
|
||||
.sp
|
||||
Remove all logical volumes in volume group vg00:
|
||||
.sp
|
||||
\ \fBlvremove vg00\fP
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR lvcreate (8),
|
||||
.BR lvdisplay (8),
|
||||
.BR lvscan (8)
|
||||
.BR lvm (8),
|
||||
.BR lvs (8),
|
||||
.BR lvscan (8),
|
||||
.BR vgremove (8)
|
||||
|
@@ -3,6 +3,7 @@
|
||||
lvresize \- resize a logical volume
|
||||
.SH SYNOPSIS
|
||||
.B lvresize
|
||||
[\-\-alloc AllocationPolicy]
|
||||
[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
|
||||
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
|
||||
{\-l/\-\-extents [+]LogicalExtentsNumber |
|
||||
@@ -27,7 +28,7 @@ With the + or - sign the value is added to or subtracted from the actual size
|
||||
of the logical volume and without it, the value is taken as an absolute one.
|
||||
.TP
|
||||
.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtT]
|
||||
Change or set the logical volume size in units in units of megabytes.
|
||||
Change or set the logical volume size in units of megabytes.
|
||||
A size suffix of M for megabytes, G for gigabytes or T for terabytes is
|
||||
optional. With the + or - sign the value is added to or subtracted from
|
||||
the actual size of the logical volume and without it, the value is taken as an
|
||||
|
38
man/lvs.8
38
man/lvs.8
@@ -13,7 +13,7 @@ lvs \- report information about logical volumes
|
||||
[\-v/\-\-verbose]
|
||||
[\-\-version] [VolumeGroupName [VolumeGroupName...]]
|
||||
.SH DESCRIPTION
|
||||
vgs produces formatted output about volume groups
|
||||
lvs produces formatted output about logical volumes.
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
@@ -30,16 +30,35 @@ if processing the output.
|
||||
.TP
|
||||
.I \-o, \-\-options
|
||||
Comma-separated ordered list of columns. Precede the list with '+' to append
|
||||
to the default selection of columns. Column names are:
|
||||
lv_uuid, lv_name, lv_attr, lv_minor, lv_size, seg_count, origin,
|
||||
snap_percent (suppressed if no kernel driver), segtype, stripes,
|
||||
stripesize, chunksize, seg_start, seg_size.
|
||||
to the default selection of columns instead of replacing it. Column names are:
|
||||
lv_uuid, lv_name, lv_attr, lv_major, lv_minor, lv_kernel_major, lv_kernel_minor,
|
||||
lv_size, seg_count, origin, snap_percent,
|
||||
copy_percent, move_pv, lv_tags,
|
||||
segtype, stripes,
|
||||
stripesize, chunksize, seg_start, seg_size, seg_tags, devices.
|
||||
.IP
|
||||
With \-\-segments, any "seg_" prefixes are optional; otherwise any "lv_"
|
||||
prefixes are optional. Columns mentioned in \fBvgs (8)\fP
|
||||
can also be chosen
|
||||
The lv_attr bits are: (o)rigin, (s)napshot, (w)riteable, (r)eadonly,
|
||||
(c)ontiguous allocation, (n)ext free allocation, fixed (m)inor, (s)uspended,
|
||||
(a)ctive, device (o)pen.
|
||||
can also be chosen.
|
||||
.IP
|
||||
The lv_attr bits are:
|
||||
.RS
|
||||
.IP 1 3
|
||||
Volume type: (m)irrored, (o)rigin, (p)vmove, (s)napshot,
|
||||
invalid (S)napshot, (v)irtual
|
||||
.IP 2 3
|
||||
Permissions: (w)riteable, (r)ead-only
|
||||
.IP 3 3
|
||||
Allocation policy: (c)ontiguous, (n)ormal, (a)nywhere, (i)nherited
|
||||
This is capitalised if the volume is currently locked against allocation
|
||||
changes, for example during \fBpvmove\fP (8).
|
||||
.IP 4 3
|
||||
fixed (m)inor
|
||||
.IP 5 3
|
||||
State: (a)ctive, (s)uspended, (I)nvalid snapshot, invalid (S)uspended snapshot
|
||||
.IP 6 3
|
||||
device (o)pen
|
||||
.RE
|
||||
.TP
|
||||
.I \-\-segments
|
||||
Use default columns that emphasize segment information.
|
||||
@@ -60,5 +79,6 @@ All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
|
||||
of 1000 (S.I.) instead of 1024. Can also specify custom (u)nits e.g.
|
||||
\-\-units 3M
|
||||
.SH SEE ALSO
|
||||
.BR lvdisplay (8),
|
||||
.BR pvs (8),
|
||||
.BR vgs (8)
|
||||
|
@@ -16,6 +16,7 @@ pvcreate \- initialize a disk or partition for use by LVM
|
||||
.RB [ \-\-restorefile file ]
|
||||
.RB [ \-\-setphysicalvolumesize size ]
|
||||
.RB [ \-\-version ]
|
||||
.RB [ \-Z | \-\-zero y/n ]
|
||||
.IR PhysicalVolume " [" PhysicalVolume ...]
|
||||
.SH DESCRIPTION
|
||||
.B pvcreate
|
||||
@@ -59,6 +60,13 @@ onto a replacement device - see \fBvgcfgrestore\fP(8).
|
||||
.TP
|
||||
.BR \-y ", " \-\-yes
|
||||
Answer yes to all questions.
|
||||
.TP
|
||||
.BR \-Z ", " \-\-zero " y/n"
|
||||
Whether or not the first 4 sectors (2048 bytes) of the device should be
|
||||
wiped.
|
||||
If this option is not given, the
|
||||
default is to wipe these sectors unless either or both of the --restorefile
|
||||
or --uuid options were specified.
|
||||
.SH NEW METADATA OPTIONS
|
||||
LVM2 introduces a new format for storing metadata on disk.
|
||||
This new format is more efficient and resilient than the format the
|
||||
|
@@ -10,11 +10,15 @@ PhysicalVolumePath [PhysicalVolumePath...]
|
||||
pvdisplay allows you to see the attributes of one or more physical volumes
|
||||
like size, physical extent size, space used for the volume group descriptor
|
||||
area and so on.
|
||||
.P
|
||||
\fBpvs\fP (8) is an alternative that provides the same information
|
||||
in the style of \fBps\fP (1).
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
.I \-c, \-\-colon
|
||||
Generate colon separated output for easier parsing in scripts or programs.
|
||||
N.B. \fBpvs\fP (8) provides considerably more control over the output.
|
||||
.nf
|
||||
|
||||
The values are:
|
||||
|
@@ -3,7 +3,9 @@
|
||||
pvmove \- move physical extents
|
||||
.SH SYNOPSIS
|
||||
.B pvmove
|
||||
[\-\-abort] [\-\-background]
|
||||
[\-\-abort]
|
||||
[\-\-alloc AllocationPolicy]
|
||||
[\-\-background]
|
||||
[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
|
||||
[\-n/\-\-name LogicalVolume]
|
||||
[SourcePhysicalVolume[:PE[-PE]...] [DestinationPhysicalVolume[:PE[-PE]...]...]]
|
||||
|
@@ -12,7 +12,7 @@ pvs \- report information about physical volumes
|
||||
[\-v/\-\-verbose]
|
||||
[\-\-version] [PhysicalVolume [PhysicalVolume...]]
|
||||
.SH DESCRIPTION
|
||||
pvs produces formatted output about physical volumes
|
||||
pvs produces formatted output about physical volumes.
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
@@ -30,7 +30,8 @@ if processing the output.
|
||||
.I \-o, \-\-options
|
||||
Comma-separated ordered list of columns. Precede the list with '+' to append
|
||||
to the default selection of columns. Column names are: pv_fmt, pv_uuid,
|
||||
pv_size, pv_free, pv_used, pv_name, pv_attr, pv_pe_count, pv_pe_alloc_count.
|
||||
pv_size, dev_size, pv_free, pv_used, pv_name, pv_attr, pv_pe_count,
|
||||
pv_pe_alloc_count, pv_tags.
|
||||
The "pv_" prefix is optional. Columns mentioned in \fBvgs (8)\fP can also
|
||||
be chosen. The pv_attr bits are: (a)llocatable and e(x)ported.
|
||||
.TP
|
||||
@@ -50,5 +51,6 @@ All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
|
||||
of 1000 (S.I.) instead of 1024. Can also specify custom (u)nits e.g.
|
||||
\-\-units 3M
|
||||
.SH SEE ALSO
|
||||
.BR pvdisplay (8),
|
||||
.BR lvs (8),
|
||||
.BR vgs (8)
|
||||
|
@@ -3,22 +3,24 @@
|
||||
vgchange \- change attributes of a volume group
|
||||
.SH SYNOPSIS
|
||||
.B vgchange
|
||||
.RB [\-\-addtag
|
||||
.RB [ \-\-addtag
|
||||
.IR Tag ]
|
||||
.RB [\-A | \-\-autobackup " {" y | n }]
|
||||
.RB [\-a | \-\-available " {" y | n }]
|
||||
.RB [\-d | \-\-debug]
|
||||
.RB [\-\-deltag
|
||||
.RB [ \-\-alloc
|
||||
.IR AllocationPolicy ]
|
||||
.RB [ \-A | \-\-autobackup " {" y | n }]
|
||||
.RB [ \-a | \-\-available " [e|l] {" y | n }]
|
||||
.RB [ \-d | \-\-debug]
|
||||
.RB [ \-\-deltag
|
||||
.IR Tag ]
|
||||
.RB [\-h | \-\-help]
|
||||
.RB [\-\-ignorelockingfailure]
|
||||
.RB [\-l | \-\-logicalvolume
|
||||
.RB [ \-h | \-\-help]
|
||||
.RB [ \-\-ignorelockingfailure]
|
||||
.RB [ \-l | \-\-logicalvolume
|
||||
.IR MaxLogicalVolumes ]
|
||||
.RB [\-P | \-\-partial]
|
||||
.RB [-t | \-\-test]
|
||||
.RB [\-v | \-\-verbose]
|
||||
.RB [\-\-version ]
|
||||
.RB [\-x | \-\-resizeable " {" y | n }]
|
||||
.RB [ \-P | \-\-partial]
|
||||
.RB [ -t | \-\-test]
|
||||
.RB [ \-v | \-\-verbose]
|
||||
.RB [ \-\-version ]
|
||||
.RB [ \-x | \-\-resizeable " {" y | n }]
|
||||
.RI [ VolumeGroupName ...]
|
||||
.SH DESCRIPTION
|
||||
.B vgchange
|
||||
@@ -42,9 +44,16 @@ Controls automatic backup of metadata after the change. See
|
||||
.B vgcfgbackup (8).
|
||||
Default is yes.
|
||||
.TP
|
||||
.BR \-a ", " \-\-available { y | n }
|
||||
Controls the availability of the volume group for input/output.
|
||||
In other words: makes a volume group known/unknown to the kernel.
|
||||
.BR \-a ", " \-\-available [e|l] { y | n }
|
||||
Controls the availability of the logical volumes in the volume
|
||||
group for input/output.
|
||||
In other words, makes the logical volumes known/unknown to the kernel.
|
||||
.IP
|
||||
If clustered locking is enabled, add 'e' to activate/deactivate
|
||||
exclusively on one node or 'l' to activate/deactivate only
|
||||
on the local node.
|
||||
Logical volumes with single-host snapshots are always activated
|
||||
exclusively because they can only be used on one node at once.
|
||||
.TP
|
||||
.BR \-l ", " \-\-logicalvolume " " \fIMaxLogicalVolumes\fR
|
||||
Changes the maximum logical volume number of an existing inactive
|
||||
@@ -69,5 +78,6 @@ to 128.
|
||||
|
||||
.fi
|
||||
.SH SEE ALSO
|
||||
.BR lvchange (8),
|
||||
.BR lvm (8),
|
||||
.BR vgcreate (8)
|
||||
|
@@ -5,6 +5,8 @@ vgcreate \- create a volume group
|
||||
.B vgcreate
|
||||
.RB [ \-\-addtag
|
||||
.IR Tag ]
|
||||
.RB [ \-\-alloc
|
||||
.IR AllocationPolicy ]
|
||||
.RB [ \-A | \-\-autobackup " {" y | n }]
|
||||
.RB [ \-d | \-\-debug ]
|
||||
.RB [ \-h | \-\-help ]
|
||||
@@ -31,45 +33,55 @@ 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
|
||||
using physical volumes
|
||||
.BR /dev/hdk1 ", " /dev/hdl1 ", and " /dev/hdm1
|
||||
.BR /dev/hdk1 ", and " /dev/hdl1
|
||||
with default physical extent size of 4MB:
|
||||
.nf
|
||||
|
||||
\ vgcreate test_vg /dev/sd[k-m]1
|
||||
\ 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),
|
||||
|
@@ -19,6 +19,9 @@ allows you to see the attributes of
|
||||
.I VolumeGroupName
|
||||
(or all volume groups if none is given) with it's physical and logical
|
||||
volumes and their sizes etc.
|
||||
.P
|
||||
\fBvgs\fP (8) is an alternative that provides the same information
|
||||
in the style of \fBps\fP (1).
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
@@ -27,6 +30,7 @@ Only select the active volume groups.
|
||||
.TP
|
||||
.BR \-c ", " \-\-colon
|
||||
Generate colon separated output for easier parsing in scripts or programs.
|
||||
N.B. \fBvgs\fP (8) provides considerably more control over the output.
|
||||
.nf
|
||||
|
||||
The values are:
|
||||
@@ -63,6 +67,7 @@ information of vgdisplay's activities.
|
||||
Display version and exit successfully.
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR vgs (8),
|
||||
.BR pvcreate (8),
|
||||
.BR vgcreate (8),
|
||||
.BR lvcreate (8)
|
||||
|
@@ -7,13 +7,15 @@ vgremove \- remove a volume group
|
||||
VolumeGroupName [VolumeGroupName...]
|
||||
.SH DESCRIPTION
|
||||
vgremove allows you to remove one or more volume groups.
|
||||
The volume group(s) must not have any logical volumes allocated
|
||||
and must also be inactive (see
|
||||
.B vgchange(8)
|
||||
).
|
||||
The volume group(s) must not have any logical volumes allocated:
|
||||
Remove them first with \fBlvremove\fP. If one or more physical
|
||||
volumes in the volume group are lost, consider
|
||||
\fBvgreduce --removemissing\fP to make the volume group
|
||||
metadata consistent again.
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR lvremove (8),
|
||||
.BR vgcreate (8),
|
||||
.BR vgreduce (8)
|
||||
|
@@ -13,7 +13,7 @@ vgs \- report information about volume groups
|
||||
[\-v/\-\-verbose]
|
||||
[\-\-version] [VolumeGroupName [VolumeGroupName...]]
|
||||
.SH DESCRIPTION
|
||||
vgs produces formatted output about volume groups
|
||||
vgs produces formatted output about volume groups.
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
@@ -32,7 +32,8 @@ if processing the output.
|
||||
Comma-separated ordered list of columns. Precede the list with '+' to append
|
||||
to the default selection of columns. Column names are: vg_fmt, vg_uuid,
|
||||
vg_name, vg_attr, vg_size, vg_free, vg_sysid, vg_extent_size, vg_extent_count,
|
||||
vg_free_count, max_lv, max_pv, pv_count, lv_count, snap_count, vg_seqno.
|
||||
vg_free_count, max_lv, max_pv, pv_count, lv_count, snap_count, vg_seqno,
|
||||
vg_tags.
|
||||
Any "vg_" prefixes are optional. Columns mentioned in either \fBpvs (8)\fP
|
||||
or \fBlvs (8)\fP can also be chosen, but columns cannot be taken from both
|
||||
at the same time. The vg_attr bits are: (w)riteable, (r)eadonly,
|
||||
@@ -54,5 +55,6 @@ All sizes are output in these units: (h)uman-readable, (s)ectors, (b)ytes,
|
||||
of 1000 (S.I.) instead of 1024. Can also specify custom (u)nits e.g.
|
||||
\-\-units 3M
|
||||
.SH SEE ALSO
|
||||
.BR vgdisplay (8),
|
||||
.BR pvs (8),
|
||||
.BR lvs (8)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
.TH VGMERGE 8 "LVM TOOLS" "Sistina Software UK" \" -*- nroff -*-
|
||||
.TH VGSPLIT 8 "LVM TOOLS" "Sistina Software UK" \" -*- nroff -*-
|
||||
.SH NAME
|
||||
vgsplit \- split a volume group into two
|
||||
.SH SYNOPSIS
|
||||
|
1375
po/lvm2.po
1375
po/lvm2.po
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,10 @@ if [ -z "$PREFIX" ]
|
||||
then
|
||||
echo "usage: $0 <prefix> [<config file>] [<library>]"
|
||||
echo ""
|
||||
echo "<prefix> location of the cluster locking shared library. (no default)"
|
||||
echo "<config file> name of the LVM config file (default: /etc/lvm/lvm.conf)"
|
||||
echo "<library> name of the shared library (default: liblvm2clusterlock.so)"
|
||||
echo "<prefix>|UNDO location of the cluster locking shared library. (no default)"
|
||||
echo " UNDO will reset the locking back to local"
|
||||
echo "<config file> name of the LVM config file (default: /etc/lvm/lvm.conf)"
|
||||
echo "<library> name of the shared library (default: liblvm2clusterlock.so)"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
@@ -25,10 +26,23 @@ fi
|
||||
[ -z "$LVMCONF" ] && LVMCONF="/etc/lvm/lvm.conf"
|
||||
[ -z "$LIB" ] && LIB="liblvm2clusterlock.so"
|
||||
|
||||
if [ "${PREFIX:0:1}" != "/" ]
|
||||
if [ "$PREFIX" = "UNDO" ]
|
||||
then
|
||||
echo "Prefix must be an absolute path name (starting with a /)"
|
||||
exit 12
|
||||
locking_type="1"
|
||||
else
|
||||
locking_type="2"
|
||||
|
||||
if [ "${PREFIX:0:1}" != "/" ]
|
||||
then
|
||||
echo "Prefix must be an absolute path name (starting with a /)"
|
||||
exit 12
|
||||
fi
|
||||
|
||||
if [ ! -f "$PREFIX/$LIB" ]
|
||||
then
|
||||
echo "$PREFIX/$LIB does not exist, did you do a \"make install\" ?"
|
||||
exit 11
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$LVMCONF" ]
|
||||
@@ -37,12 +51,6 @@ then
|
||||
exit 10
|
||||
fi
|
||||
|
||||
if [ ! -f "$PREFIX/$LIB" ]
|
||||
then
|
||||
echo "$PREFIX/$LIB does not exist, did you do a \"make install\" ?"
|
||||
exit 11
|
||||
fi
|
||||
|
||||
|
||||
SCRIPTFILE=`mktemp -t lvmscript.XXXXXXXXXX`
|
||||
TMPFILE=`mktemp -t lvmtmp.XXXXXXXXXX`
|
||||
@@ -87,7 +95,7 @@ then
|
||||
cat $LVMCONF - <<EOF > $TMPFILE
|
||||
global {
|
||||
# Enable locking for cluster LVM
|
||||
locking_type = 2
|
||||
locking_type = $locking_type
|
||||
library_dir = "$PREFIX"
|
||||
locking_library = "$LIB"
|
||||
}
|
||||
@@ -105,7 +113,7 @@ else
|
||||
|
||||
if [ "$have_type" = "0" ]
|
||||
then
|
||||
SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = 2/g"
|
||||
SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $locking_type/g"
|
||||
else
|
||||
SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = 2"
|
||||
fi
|
||||
|
166
scripts/clvmd_init_rhel4
Normal file
166
scripts/clvmd_init_rhel4
Normal file
@@ -0,0 +1,166 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# chkconfig: 345 24 76
|
||||
# description: Starts and stops clvmd
|
||||
#
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides:
|
||||
### END INIT INFO
|
||||
|
||||
. /etc/init.d/functions
|
||||
[ -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
|
||||
then
|
||||
echo -n "Starting clvmd:"
|
||||
clvmd > /dev/null 2>&1
|
||||
rtrn=$?
|
||||
if [ $rtrn -eq 0 ]
|
||||
then
|
||||
success
|
||||
echo
|
||||
else
|
||||
failure
|
||||
echo
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$LVM_VGS" ]
|
||||
then
|
||||
for vg in $LVM_VGS
|
||||
do
|
||||
echo -n "Activating lvm $vg:"
|
||||
if $vgchange -ayl $vg > /dev/null 2>&1
|
||||
then
|
||||
success
|
||||
echo
|
||||
else
|
||||
rtrn=$?
|
||||
failure
|
||||
echo
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo -n "Activating lvms:"
|
||||
if $vgchange -ayl > /dev/null 2>&1
|
||||
then
|
||||
success
|
||||
echo
|
||||
else
|
||||
rtrn=$?
|
||||
failure
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
return $rtrn
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
for rtrn in 0
|
||||
do
|
||||
if [ -n "$LVM_VGS" ]
|
||||
then
|
||||
for vg in $LVM_VGS
|
||||
do
|
||||
echo -n "Deactivating lvm $vg:"
|
||||
if $vgchange -anl $vg > /dev/null 2>&1
|
||||
then
|
||||
success
|
||||
echo
|
||||
else
|
||||
rtrn=$?
|
||||
failure
|
||||
echo
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo -n "Deactivating lvms:"
|
||||
if $vgchange -anl > /dev/null 2>&1
|
||||
then
|
||||
success
|
||||
echo
|
||||
else
|
||||
rtrn=$?
|
||||
failure
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
|
||||
[ $rtrn -ne 0 ] && break
|
||||
|
||||
echo -n "Stopping clvm:"
|
||||
pid=$(pidof clvmd)
|
||||
if [ -n "$pid" ]
|
||||
then
|
||||
while kill $pid > /dev/null 2>&1
|
||||
do
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
if [ $rtrn -eq 0 ]
|
||||
then
|
||||
success
|
||||
echo
|
||||
else
|
||||
failure
|
||||
echo
|
||||
fi
|
||||
done
|
||||
modprobe -r dlm > /dev/null 2>&1
|
||||
|
||||
return $rtrn
|
||||
}
|
||||
|
||||
rtrn=1
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
rtrn=$?
|
||||
[ $rtrn = 0 ] && touch $LOCK_FILE
|
||||
;;
|
||||
|
||||
stop)
|
||||
stop
|
||||
rtrn=$?
|
||||
[ $rtrn = 0 ] && rm -f $LOCK_FILE
|
||||
;;
|
||||
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
rtrn=$?
|
||||
;;
|
||||
|
||||
status)
|
||||
status clvmd
|
||||
vols=$( $lvdisplay -C --nohead 2> /dev/null | awk '($3 ~ /....a./) {print $1}' )
|
||||
echo active volumes: ${vols:-"(none)"}
|
||||
rtrn=0
|
||||
;;
|
||||
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|restart|status}"
|
||||
;;
|
||||
esac
|
||||
|
||||
exit $rtrn
|
@@ -43,6 +43,7 @@ arg(mknodes_ARG, '\0', "mknodes", NULL)
|
||||
arg(minor_ARG, '\0', "minor", minor_arg)
|
||||
arg(type_ARG, '\0', "type", segtype_arg)
|
||||
arg(alloc_ARG, '\0', "alloc", alloc_arg)
|
||||
arg(separator_ARG, '\0', "separator", string_arg)
|
||||
|
||||
/* Allow some variations */
|
||||
arg(resizable_ARG, '\0', "resizable", yes_no_arg)
|
||||
@@ -99,7 +100,6 @@ arg(readahead_ARG, 'r', "readahead", int_arg)
|
||||
arg(resizefs_ARG, 'r', "resizefs", NULL)
|
||||
arg(reset_ARG, 'R', "reset", NULL)
|
||||
arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg)
|
||||
arg(separator_ARG, 's', "separator", string_arg)
|
||||
arg(stdin_ARG, 's', "stdin", NULL)
|
||||
arg(snapshot_ARG, 's', "snapshot", NULL)
|
||||
arg(short_ARG, 's', "short", NULL)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user