mirror of
git://sourceware.org/git/lvm2.git
synced 2026-01-11 00:32:47 +03:00
Compare commits
72 Commits
dm_v1_02_1
...
v2_02_17
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f48ca5132 | ||
|
|
da983848b4 | ||
|
|
bc03f7bad3 | ||
|
|
a1c8bd3846 | ||
|
|
404bc284e0 | ||
|
|
9dee30ff0e | ||
|
|
f91aadbea8 | ||
|
|
aa15a10c91 | ||
|
|
5b03e36351 | ||
|
|
b9ba9ffad2 | ||
|
|
642be5d16c | ||
|
|
ee68d715bf | ||
|
|
224084f056 | ||
|
|
1cd8c849b8 | ||
|
|
169f68bfcd | ||
|
|
d2b7cfa2d1 | ||
|
|
a40c7dff5d | ||
|
|
e8e00630d3 | ||
|
|
e33720c854 | ||
|
|
bd8a4e0d17 | ||
|
|
586a2aef76 | ||
|
|
ce1d8f6754 | ||
|
|
7b0f401065 | ||
|
|
8387016eef | ||
|
|
4e1342b641 | ||
|
|
e45a184d90 | ||
|
|
979e1012d2 | ||
|
|
fe10a50e23 | ||
|
|
8ab6d72519 | ||
|
|
3aada6dd1d | ||
|
|
0933036366 | ||
|
|
05f5abdc06 | ||
|
|
fb875e0709 | ||
|
|
9acdc2f6bf | ||
|
|
028ce4bff6 | ||
|
|
3f245ad6db | ||
|
|
23115f4116 | ||
|
|
cf5f48e6cc | ||
|
|
997fa756ad | ||
|
|
e23f75b1cc | ||
|
|
6531e88761 | ||
|
|
e76a9c2618 | ||
|
|
45be8a836b | ||
|
|
954b6032e7 | ||
|
|
bd95416f27 | ||
|
|
df2577ace2 | ||
|
|
720e6558c9 | ||
|
|
c239f15d8a | ||
|
|
dfa1f80a57 | ||
|
|
15dfb93b17 | ||
|
|
0ec8488c2b | ||
|
|
94b2e29cb1 | ||
|
|
fefa8e9b4d | ||
|
|
32c4c44812 | ||
|
|
05195e2b1d | ||
|
|
4c2ff675b8 | ||
|
|
e5692a4721 | ||
|
|
312e6a0d31 | ||
|
|
5bb8efa41f | ||
|
|
949a835f4a | ||
|
|
85e6042941 | ||
|
|
3cd2f28975 | ||
|
|
2179a72c3a | ||
|
|
a5f282f156 | ||
|
|
40e8631f63 | ||
|
|
9ded05bb97 | ||
|
|
ec8efa35a1 | ||
|
|
f72bf20482 | ||
|
|
ebde2002e8 | ||
|
|
352a66f46f | ||
|
|
d84c5391f7 | ||
|
|
f4c582472b |
@@ -16,7 +16,7 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SUBDIRS = doc include man
|
||||
SUBDIRS = doc include man scripts
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
SUBDIRS += po
|
||||
|
||||
68
WHATS_NEW
68
WHATS_NEW
@@ -1,6 +1,70 @@
|
||||
Version 2.02.12 -
|
||||
Version 2.02.17 - 14th December 2006
|
||||
====================================
|
||||
Add missing pvremove error message when device doesn't exist.
|
||||
When lvconvert allocates a mirror log, respect parallel area constraints.
|
||||
Use loop to iterate through the now-ordered policy list in _allocate().
|
||||
Check for failure to allocate just the mirror log.
|
||||
Introduce calc_area_multiple().
|
||||
Support mirror log allocation when there is only one PV: area_count now 0.
|
||||
Fix detection of smallest area in _alloc_parallel_area() for cling policy.
|
||||
Add manpage entry for clvmd -T
|
||||
Fix gulm operation of clvmd, including a hang when doing lvchange -aey
|
||||
Fix hang in clvmd if a pre-command failed.
|
||||
|
||||
Version 2.02.16 - 1st December 2006
|
||||
===================================
|
||||
Propogate clustered flag in vgsplit and require resizeable flag.
|
||||
Fix VG clustered read locks to use PR not CR.
|
||||
Adjust some alignments for ia64/sparc.
|
||||
Fix mirror segment removal to use temporary error segment.
|
||||
Always compile debug logging into clvmd.
|
||||
Add startup timeout to RHEL4 clvmd startup script.
|
||||
Add -T (startup timeout) switch to clvmd.
|
||||
Improve lvm_dump.sh robustness.
|
||||
Update lvm2create_initrd to support gentoo.
|
||||
|
||||
Version 2.02.15 - 21st November 2006
|
||||
====================================
|
||||
Fix clvmd_init_rhel4 line truncation (2.02.14).
|
||||
Install lvmdump by default.
|
||||
Fix check for snapshot module when activating snapshot.
|
||||
Fix pvremove error path for case when PV is in use.
|
||||
Warn if certain duplicate config file entries are seen.
|
||||
Enhance lvm_dump.sh for sysreport integration and add man page.
|
||||
Fix --autobackup argument which could never disable backups.
|
||||
Fix a label_verify error path.
|
||||
|
||||
Version 2.02.14 - 10th November 2006
|
||||
====================================
|
||||
Fix adjusted_mirror_region_size() to handle 64-bit size.
|
||||
Add some missing bounds checks on 32-bit extent counters.
|
||||
Add Petabyte and Exabyte support.
|
||||
Fix lvcreate error message when 0 extents requested.
|
||||
lvremove man page: volumes must be cluster inactive before being removed.
|
||||
Protect .cache manipulations with fcntl locking.
|
||||
Change .cache timestamp comparisons to use ctime.
|
||||
Fix mirror log LV writing to set all bits in whole LV.
|
||||
Fix clustered VG detection and default runlevels in clvmd_init_rhel4.
|
||||
Fix high-level free space check for partial allocations.
|
||||
|
||||
Version 2.02.13 - 27th October 2006
|
||||
===================================
|
||||
Add couple of missing files to tools/Makefile CLEAN_TARGETS.
|
||||
When adding snapshot leave cow LV mapped device active after zeroing.
|
||||
Fix a clvmd debug message.
|
||||
Add dev_flush() to set_lv().
|
||||
Add lvchange --resync.
|
||||
Perform high-level free space check before each allocation attempt.
|
||||
Don't allow a node to remove an LV that's exclusively active on anther node.
|
||||
Cope if same PV is included more than once in cmdline PE range list.
|
||||
Set PV size to current device size if it is found to be zero.
|
||||
Add segment parameter to target_present functions.
|
||||
|
||||
Version 2.02.12 - 16th October 2006
|
||||
===================================
|
||||
Fix pvdisplay to use vg_read() for non-orphans.
|
||||
Fall back to internal locking if external locking lib is missing or fails.
|
||||
Retain activation state after changing LV minor number with --force.
|
||||
Propagate clustered flag in vgsplit and require resizeable flag.
|
||||
|
||||
Version 2.02.11 - 12th October 2006
|
||||
===================================
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
Version 1.02.14 -
|
||||
=============================
|
||||
|
||||
Version 1.02.13 - 28 Nov 2006
|
||||
=============================
|
||||
Update dmsetup man page (setgeometry & message).
|
||||
Fix dmsetup free after getline with debug.
|
||||
Suppress encryption key in 'dmsetup table' output unless --showkeys supplied.
|
||||
|
||||
Version 1.02.12 - 13 Oct 2006
|
||||
=============================
|
||||
Avoid deptree attempting to suspend a device that's already suspended.
|
||||
|
||||
3
configure
vendored
3
configure
vendored
@@ -11203,7 +11203,7 @@ fi
|
||||
|
||||
|
||||
################################################################################
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile scripts/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
# tests run on this system so they can be shared between configure
|
||||
@@ -11745,6 +11745,7 @@ do
|
||||
"lib/snapshot/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
|
||||
"man/Makefile" ) CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
|
||||
"po/Makefile" ) CONFIG_FILES="$CONFIG_FILES po/Makefile" ;;
|
||||
"scripts/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
|
||||
"tools/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
|
||||
"tools/version.h" ) CONFIG_FILES="$CONFIG_FILES tools/version.h" ;;
|
||||
"tools/fsadm/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/fsadm/Makefile" ;;
|
||||
|
||||
@@ -637,6 +637,7 @@ lib/mirror/Makefile \
|
||||
lib/snapshot/Makefile \
|
||||
man/Makefile \
|
||||
po/Makefile \
|
||||
scripts/Makefile \
|
||||
tools/Makefile \
|
||||
tools/version.h \
|
||||
tools/fsadm/Makefile \
|
||||
|
||||
@@ -191,12 +191,16 @@ static int lock_vg(struct local_client *client)
|
||||
dm_hash_remove(lock_hash, lockname);
|
||||
}
|
||||
else {
|
||||
|
||||
/* Read locks need to be PR; other modes get passed through */
|
||||
if ((lock_cmd & LCK_TYPE_MASK) == LCK_READ) {
|
||||
lock_cmd &= ~LCK_TYPE_MASK;
|
||||
lock_cmd |= LCK_PREAD;
|
||||
}
|
||||
status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
dm_hash_insert(lock_hash, lockname, (void *)lkid);
|
||||
dm_hash_insert(lock_hash, lockname, (void *)(long)lkid);
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -220,7 +224,7 @@ int do_pre_command(struct local_client *client)
|
||||
switch (header->cmd) {
|
||||
case CLVMD_CMD_TEST:
|
||||
status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid);
|
||||
client->bits.localsock.private = (void *) lockid;
|
||||
client->bits.localsock.private = (void *)(long)lockid;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
|
||||
@@ -730,7 +730,7 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
/* This needs to be converted from DLM/LVM2 value for GULM */
|
||||
if (flags == LCK_NONBLOCK) flags = lg_lock_flag_Try;
|
||||
if (flags & LKF_NOQUEUE) flags = lg_lock_flag_Try;
|
||||
|
||||
dm_hash_insert(lock_hash, resource, &lwait);
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
||||
@@ -828,6 +828,7 @@ static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
}
|
||||
break;
|
||||
|
||||
case LCK_PREAD:
|
||||
case LCK_READ:
|
||||
status = _lock_resource(lock1, lg_lock_state_Shared, flags, lockid);
|
||||
if (status)
|
||||
@@ -864,6 +865,7 @@ static int _sync_unlock(const char *resource, int lockid)
|
||||
/* The held lock mode is in the lock id */
|
||||
assert(lockid == LCK_EXCL ||
|
||||
lockid == LCK_READ ||
|
||||
lockid == LCK_PREAD ||
|
||||
lockid == LCK_WRITE);
|
||||
|
||||
status = _unlock_resource(lock1, lockid);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
|
||||
/* DLM constant that clvmd uses as a generic NONBLOCK lock flag */
|
||||
#define LKF_NOQUEUE 1
|
||||
|
||||
extern int get_next_node_csid(void **context, char *csid);
|
||||
extern void add_down_node(char *csid);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@@ -85,6 +86,7 @@ struct lvm_thread_cmd {
|
||||
int msglen;
|
||||
unsigned short xid;
|
||||
};
|
||||
static int debug = 0;
|
||||
static pthread_t lvm_thread;
|
||||
static pthread_mutex_t lvm_thread_mutex;
|
||||
static pthread_cond_t lvm_thread_cond;
|
||||
@@ -99,6 +101,7 @@ static int child_pipe[2];
|
||||
#define DFAIL_LOCAL_SOCK 2
|
||||
#define DFAIL_CLUSTER_IF 3
|
||||
#define DFAIL_MALLOC 4
|
||||
#define DFAIL_TIMEOUT 5
|
||||
#define SUCCESS 0
|
||||
|
||||
/* Prototypes for code further down */
|
||||
@@ -122,7 +125,7 @@ static int process_reply(struct clvm_header *msg, int msglen, char *csid);
|
||||
static int open_local_sock(void);
|
||||
static struct local_client *find_client(int clientid);
|
||||
static void main_loop(int local_sock, int cmd_timeout);
|
||||
static void be_daemon(void);
|
||||
static void be_daemon(int start_timeout);
|
||||
static int check_all_clvmds_running(struct local_client *client);
|
||||
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
|
||||
int len, char *csid,
|
||||
@@ -146,6 +149,7 @@ static void usage(char *prog, FILE *file)
|
||||
fprintf(file, " -d Don't fork, run in the foreground\n");
|
||||
fprintf(file, " -R Tell all running clvmds in the cluster to reload their device cache\n");
|
||||
fprintf(file, " -t<secs> Command timeout (default 60 seconds)\n");
|
||||
fprintf(file, " -T<secs> Startup timeout (default none)\n");
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
@@ -161,21 +165,36 @@ static void child_init_signal(int status)
|
||||
}
|
||||
|
||||
|
||||
void debuglog(const char *fmt, ...)
|
||||
{
|
||||
time_t P;
|
||||
va_list ap;
|
||||
|
||||
if (!debug)
|
||||
return;
|
||||
|
||||
va_start(ap,fmt);
|
||||
time(&P);
|
||||
fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 );
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int local_sock;
|
||||
struct local_client *newfd;
|
||||
struct utsname nodeinfo;
|
||||
signed char opt;
|
||||
int debug = 0;
|
||||
int cmd_timeout = DEFAULT_CMD_TIMEOUT;
|
||||
int start_timeout = 0;
|
||||
sigset_t ss;
|
||||
int using_gulm = 0;
|
||||
|
||||
/* Deal with command-line arguments */
|
||||
opterr = 0;
|
||||
optind = 0;
|
||||
while ((opt = getopt(argc, argv, "?vVhdt:R")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "?vVhdt:RT:")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
usage(argv[0], stdout);
|
||||
@@ -200,6 +219,14 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
start_timeout = atoi(optarg);
|
||||
if (start_timeout <= 0) {
|
||||
fprintf(stderr, "startup timeout is invalid\n");
|
||||
usage(argv[0], stderr);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
printf("Cluster LVM daemon version: %s\n", LVM_VERSION);
|
||||
@@ -214,7 +241,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Fork into the background (unless requested not to) */
|
||||
if (!debug) {
|
||||
be_daemon();
|
||||
be_daemon(start_timeout);
|
||||
}
|
||||
|
||||
DEBUGLOG("CLVMD started\n");
|
||||
@@ -298,7 +325,8 @@ int main(int argc, char *argv[])
|
||||
/* This needs to be started after cluster initialisation
|
||||
as it may need to take out locks */
|
||||
DEBUGLOG("starting LVM thread\n");
|
||||
pthread_create(&lvm_thread, NULL, lvm_thread_fn, (void *)using_gulm);
|
||||
pthread_create(&lvm_thread, NULL, lvm_thread_fn,
|
||||
(void *)(long)using_gulm);
|
||||
|
||||
/* Tell the rest of the cluster our version number */
|
||||
/* CMAN can do this immediately, gulm needs to wait until
|
||||
@@ -385,16 +413,17 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
|
||||
|
||||
len = read(thisfd->fd, buffer, sizeof(int));
|
||||
|
||||
DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
|
||||
thisfd->fd, len, *(int *) buffer);
|
||||
|
||||
if (len == sizeof(int)) {
|
||||
status = *(int *) buffer;
|
||||
memcpy(&status, buffer, sizeof(int));
|
||||
}
|
||||
|
||||
DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
|
||||
thisfd->fd, len, status);
|
||||
|
||||
/* EOF on pipe or an error, close it */
|
||||
if (len <= 0) {
|
||||
int jstat;
|
||||
void *ret = &status;
|
||||
close(thisfd->fd);
|
||||
|
||||
/* Clear out the cross-link */
|
||||
@@ -404,9 +433,7 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
|
||||
|
||||
/* Reap child thread */
|
||||
if (thisfd->bits.pipe.threadid) {
|
||||
jstat =
|
||||
pthread_join(thisfd->bits.pipe.threadid,
|
||||
(void **) &status);
|
||||
jstat = pthread_join(thisfd->bits.pipe.threadid, &ret);
|
||||
thisfd->bits.pipe.threadid = 0;
|
||||
if (thisfd->bits.pipe.client != NULL)
|
||||
thisfd->bits.pipe.client->bits.localsock.
|
||||
@@ -647,16 +674,66 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
close(local_sock);
|
||||
}
|
||||
|
||||
static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
|
||||
{
|
||||
int child_status;
|
||||
int sstat;
|
||||
fd_set fds;
|
||||
struct timeval tv = {timeout, 0};
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(c_pipe, &fds);
|
||||
|
||||
sstat = select(c_pipe+1, &fds, NULL, NULL, timeout? &tv: NULL);
|
||||
if (sstat == 0) {
|
||||
fprintf(stderr, "clvmd startup timed out\n");
|
||||
exit(DFAIL_TIMEOUT);
|
||||
}
|
||||
if (sstat == 1) {
|
||||
if (read(c_pipe, &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);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "clvmd startup, select failed: %s\n", strerror(errno));
|
||||
exit(DFAIL_INIT);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
static void be_daemon(int timeout)
|
||||
{
|
||||
pid_t pid;
|
||||
int child_status;
|
||||
int devnull = open("/dev/null", O_RDWR);
|
||||
if (devnull == -1) {
|
||||
perror("Can't open /dev/null");
|
||||
@@ -676,36 +753,7 @@ static void be_daemon()
|
||||
|
||||
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);
|
||||
}
|
||||
wait_for_child(child_pipe[0], timeout);
|
||||
}
|
||||
|
||||
/* Detach ourself from the calling environment */
|
||||
@@ -1091,8 +1139,8 @@ static int distribute_command(struct local_client *thisfd)
|
||||
}
|
||||
|
||||
/* Process a command from a remote node and return the result */
|
||||
void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
char *csid)
|
||||
static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
char *csid)
|
||||
{
|
||||
char *replyargs;
|
||||
char nodename[max_cluster_member_name_len];
|
||||
@@ -1116,11 +1164,12 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
(struct clvm_header *) malloc(msg->arglen +
|
||||
sizeof(struct clvm_header));
|
||||
if (newmsg) {
|
||||
if (system_lv_read_data
|
||||
(nodename, (char *) newmsg,
|
||||
(size_t *) &msglen) == 0) {
|
||||
ssize_t len;
|
||||
if (system_lv_read_data(nodename, (char *) newmsg,
|
||||
&len) == 0) {
|
||||
msg = newmsg;
|
||||
msg_malloced = 1;
|
||||
msglen = len;
|
||||
} else {
|
||||
struct clvm_header head;
|
||||
DEBUGLOG("System LV read failed\n");
|
||||
@@ -1166,8 +1215,11 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
/* Version check is internal - don't bother exposing it in
|
||||
clvmd-command.c */
|
||||
if (msg->cmd == CLVMD_CMD_VERSION) {
|
||||
int *version_nums = (int *) msg->args;
|
||||
int version_nums[3];
|
||||
char node[256];
|
||||
|
||||
memcpy(version_nums, msg->args, sizeof(version_nums));
|
||||
|
||||
clops->name_from_csid(csid, node);
|
||||
DEBUGLOG("Remote node %s is version %d.%d.%d\n",
|
||||
node,
|
||||
@@ -1339,7 +1391,7 @@ static void add_reply_to_list(struct local_client *client, int status,
|
||||
}
|
||||
|
||||
/* This is the thread that runs the PRE and post commands for a particular connection */
|
||||
static void *pre_and_post_thread(void *arg)
|
||||
static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
|
||||
{
|
||||
struct local_client *client = (struct local_client *) arg;
|
||||
int status;
|
||||
@@ -1374,6 +1426,8 @@ static void *pre_and_post_thread(void *arg)
|
||||
DEBUGLOG("Writing status %d down pipe %d\n", status, pipe_fd);
|
||||
/* Tell the parent process we have finished this bit */
|
||||
write(pipe_fd, &status, sizeof(int));
|
||||
if (status)
|
||||
continue; /* Wait for another PRE command */
|
||||
|
||||
/* We may need to wait for the condition variable before running the post command */
|
||||
pthread_mutex_lock(&client->bits.localsock.mutex);
|
||||
@@ -1407,7 +1461,6 @@ static void *pre_and_post_thread(void *arg)
|
||||
}
|
||||
DEBUGLOG("Subthread finished\n");
|
||||
pthread_exit((void *) 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Process a command on the local node and store the result */
|
||||
@@ -1516,7 +1569,7 @@ static void send_local_reply(struct local_client *client, int status, int fd)
|
||||
if (thisreply->status)
|
||||
clientreply->flags |= CLVMD_FLAG_NODEERRS;
|
||||
|
||||
*(int *) ptr = thisreply->status;
|
||||
memcpy(ptr, &thisreply->status, sizeof(int));
|
||||
ptr += sizeof(int);
|
||||
|
||||
if (thisreply->replymsg) {
|
||||
@@ -1572,19 +1625,22 @@ static void send_version_message()
|
||||
{
|
||||
char message[sizeof(struct clvm_header) + sizeof(int) * 3];
|
||||
struct clvm_header *msg = (struct clvm_header *) message;
|
||||
int *version_nums = (int *) msg->args;
|
||||
int version_nums[3];
|
||||
|
||||
msg->cmd = CLVMD_CMD_VERSION;
|
||||
msg->status = 0;
|
||||
msg->flags = 0;
|
||||
msg->clientid = 0;
|
||||
msg->arglen = sizeof(int) * 3;
|
||||
msg->arglen = sizeof(version_nums);
|
||||
|
||||
version_nums[0] = htonl(CLVMD_MAJOR_VERSION);
|
||||
version_nums[1] = htonl(CLVMD_MINOR_VERSION);
|
||||
version_nums[2] = htonl(CLVMD_PATCH_VERSION);
|
||||
|
||||
memcpy(&msg->args, version_nums, sizeof(version_nums));
|
||||
|
||||
hton_clvm(msg);
|
||||
|
||||
clops->cluster_send_message(message, sizeof(message), NULL,
|
||||
"Error Sending version number");
|
||||
}
|
||||
@@ -1641,11 +1697,11 @@ static int process_work_item(struct lvm_thread_cmd *cmd)
|
||||
/*
|
||||
* Routine that runs in the "LVM thread".
|
||||
*/
|
||||
static void *lvm_thread_fn(void *arg)
|
||||
static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
|
||||
{
|
||||
struct list *cmdl, *tmp;
|
||||
sigset_t ss;
|
||||
int using_gulm = (int)arg;
|
||||
int using_gulm = (int)(long)arg;
|
||||
|
||||
/* Don't let anyone else to do work until we are started */
|
||||
pthread_mutex_lock(&lvm_start_mutex);
|
||||
@@ -1689,7 +1745,6 @@ static void *lvm_thread_fn(void *arg)
|
||||
}
|
||||
pthread_mutex_unlock(&lvm_thread_mutex);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Pass down some work to the LVM thread */
|
||||
|
||||
@@ -95,11 +95,7 @@ struct local_client {
|
||||
} bits;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUGLOG(fmt, args...) {time_t P; time(&P); fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 ); fprintf(stderr, fmt, ## args);}
|
||||
#else
|
||||
#define DEBUGLOG(fmt, args...)
|
||||
#endif
|
||||
#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args);
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
@@ -117,6 +113,7 @@ extern int add_client(struct local_client *new_client);
|
||||
|
||||
extern void clvmd_cluster_init_completed(void);
|
||||
extern void process_message(struct local_client *client, char *buf, int len, char *csid);
|
||||
extern void debuglog(const char *fmt, ... );
|
||||
|
||||
int sync_lock(const char *resource, int mode, int flags, int *lockid);
|
||||
int sync_unlock(const char *resource, int lockid);
|
||||
|
||||
@@ -243,7 +243,7 @@ static int do_resume_lv(char *resource)
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1) {
|
||||
DEBUGLOG("do_deactivate_lock, lock not already held\n");
|
||||
DEBUGLOG("do_resume_lv, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,6 @@ static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
int *outptr;
|
||||
char *inptr;
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
@@ -223,17 +222,14 @@ static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
* With an extra pair of INTs on the front to sanity
|
||||
* check the pointer when we are given it back to free
|
||||
*/
|
||||
outptr = dm_malloc(sizeof(lvm_response_t) * num_responses +
|
||||
*response = dm_malloc(sizeof(lvm_response_t) * num_responses +
|
||||
sizeof(int) * 2);
|
||||
if (!outptr) {
|
||||
if (!*response) {
|
||||
errno = ENOMEM;
|
||||
status = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*response = (lvm_response_t *) (outptr + 2);
|
||||
outptr[0] = LVM_SIGNATURE;
|
||||
outptr[1] = num_responses;
|
||||
rarray = *response;
|
||||
|
||||
/* Unpack the response into an lvm_response_t array */
|
||||
@@ -252,7 +248,7 @@ static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
dm_free(rarray[i].response);
|
||||
free(outptr);
|
||||
free(*response);
|
||||
errno = ENOMEM;
|
||||
status = -1;
|
||||
goto out;
|
||||
@@ -274,25 +270,15 @@ static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
}
|
||||
|
||||
/* Free reply array */
|
||||
static int _cluster_free_request(lvm_response_t * response)
|
||||
static int _cluster_free_request(lvm_response_t * response, int num)
|
||||
{
|
||||
int *ptr = (int *) response - 2;
|
||||
int i;
|
||||
int num;
|
||||
|
||||
/* Check it's ours to free */
|
||||
if (response == NULL || *ptr != LVM_SIGNATURE) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
num = ptr[1];
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
dm_free(response[i].response);
|
||||
}
|
||||
|
||||
dm_free(ptr);
|
||||
dm_free(response);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -327,7 +313,7 @@ int refresh_clvmd()
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
_cluster_free_request(response);
|
||||
_cluster_free_request(response, num_responses);
|
||||
errno = saved_errno;
|
||||
|
||||
return status;
|
||||
|
||||
@@ -782,12 +782,19 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
{
|
||||
uint32_t s;
|
||||
struct list *snh;
|
||||
struct lv_segment *seg_present;
|
||||
|
||||
/* Ensure required device-mapper targets are loaded */
|
||||
if (seg->segtype->ops->target_present &&
|
||||
!seg->segtype->ops->target_present()) {
|
||||
seg_present = find_cow(seg->lv) ? : seg;
|
||||
|
||||
log_debug("Checking kernel supports %s segment type for %s%s%s",
|
||||
seg_present->segtype->name, seg->lv->name,
|
||||
layer ? "-" : "", layer ? : "");
|
||||
|
||||
if (seg_present->segtype->ops->target_present &&
|
||||
!seg_present->segtype->ops->target_present(seg_present)) {
|
||||
log_error("Can't expand LV %s: %s target support missing "
|
||||
"from kernel?", seg->lv->name, seg->segtype->name);
|
||||
"from kernel?", seg->lv->name, seg_present->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1065,7 +1072,7 @@ int dev_manager_device_uses_vg(struct device *dev,
|
||||
{
|
||||
struct dm_tree *dtree;
|
||||
struct dm_tree_node *root;
|
||||
char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1];
|
||||
char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1] __attribute((aligned(8)));
|
||||
int r = 1;
|
||||
|
||||
if (!(dtree = dm_tree_create())) {
|
||||
|
||||
13
lib/cache/lvmcache.c
vendored
13
lib/cache/lvmcache.c
vendored
@@ -114,7 +114,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
|
||||
struct list *devh, *tmp;
|
||||
struct list devs;
|
||||
struct device_list *devl;
|
||||
char vgid_found[ID_LEN + 1];
|
||||
char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
|
||||
return NULL;
|
||||
@@ -151,7 +151,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
|
||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
char id[ID_LEN + 1];
|
||||
char id[ID_LEN + 1] __attribute((aligned(8)));
|
||||
|
||||
if (!_vgid_hash || !vgid)
|
||||
return NULL;
|
||||
@@ -186,7 +186,7 @@ const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
char id[ID_LEN + 1];
|
||||
char id[ID_LEN + 1] __attribute((aligned(8)));
|
||||
|
||||
if (!_pvid_hash || !pvid)
|
||||
return NULL;
|
||||
@@ -476,7 +476,8 @@ static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
|
||||
struct lvmcache_vginfo *primary_vginfo)
|
||||
{
|
||||
struct lvmcache_vginfo *last_vginfo = primary_vginfo;
|
||||
char uuid_primary[64], uuid_new[64];
|
||||
char uuid_primary[64] __attribute((aligned(8)));
|
||||
char uuid_new[64] __attribute((aligned(8)));
|
||||
int use_new = 0;
|
||||
|
||||
/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
|
||||
@@ -709,7 +710,7 @@ int lvmcache_update_vg(struct volume_group *vg)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
struct lvmcache_info *info;
|
||||
char pvid_s[ID_LEN + 1];
|
||||
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
|
||||
|
||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||
|
||||
@@ -733,7 +734,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
{
|
||||
struct label *label;
|
||||
struct lvmcache_info *existing, *info;
|
||||
char pvid_s[ID_LEN + 1];
|
||||
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
|
||||
|
||||
if (!_vgname_hash && !lvmcache_init()) {
|
||||
log_error("Internal cache initialisation failed");
|
||||
|
||||
@@ -330,7 +330,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cfl->cft = create_config_tree(config_file))) {
|
||||
if (!(cfl->cft = create_config_tree(config_file, 0))) {
|
||||
log_error("config_tree allocation failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -370,7 +370,7 @@ static int _init_lvm_conf(struct cmd_context *cmd)
|
||||
{
|
||||
/* No config file if LVM_SYSTEM_DIR is empty */
|
||||
if (!*cmd->sys_dir) {
|
||||
if (!(cmd->cft = create_config_tree(NULL))) {
|
||||
if (!(cmd->cft = create_config_tree(NULL, 0))) {
|
||||
log_error("Failed to create config tree");
|
||||
return 0;
|
||||
}
|
||||
@@ -408,7 +408,7 @@ static int _merge_config_files(struct cmd_context *cmd)
|
||||
|
||||
/* Replace temporary duplicate copy of lvm.conf */
|
||||
if (cmd->cft->root) {
|
||||
if (!(cmd->cft = create_config_tree(NULL))) {
|
||||
if (!(cmd->cft = create_config_tree(NULL, 0))) {
|
||||
log_error("Failed to create config tree");
|
||||
return 0;
|
||||
}
|
||||
@@ -609,8 +609,8 @@ static int _init_filters(struct cmd_context *cmd)
|
||||
cmd->dump_filter = 0;
|
||||
|
||||
if (!stat(dev_cache, &st) &&
|
||||
(st.st_mtime > config_file_timestamp(cmd->cft)) &&
|
||||
!persistent_filter_load(f4))
|
||||
(st.st_ctime != config_file_timestamp(cmd->cft)) &&
|
||||
!persistent_filter_load(f4, NULL))
|
||||
log_verbose("Failed to load existing device cache from %s",
|
||||
dev_cache);
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ struct cs {
|
||||
time_t timestamp;
|
||||
char *filename;
|
||||
int exists;
|
||||
int keep_open;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static void _get_token(struct parser *p, int tok_prev);
|
||||
@@ -95,7 +97,7 @@ static int _tok_match(const char *str, const char *b, const char *e)
|
||||
/*
|
||||
* public interface
|
||||
*/
|
||||
struct config_tree *create_config_tree(const char *filename)
|
||||
struct config_tree *create_config_tree(const char *filename, int keep_open)
|
||||
{
|
||||
struct cs *c;
|
||||
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
|
||||
@@ -115,6 +117,8 @@ struct config_tree *create_config_tree(const char *filename)
|
||||
c->cft.root = (struct config_node *) NULL;
|
||||
c->timestamp = 0;
|
||||
c->exists = 0;
|
||||
c->keep_open = keep_open;
|
||||
c->dev = 0;
|
||||
if (filename)
|
||||
c->filename = dm_pool_strdup(c->mem, filename);
|
||||
return &c->cft;
|
||||
@@ -122,7 +126,12 @@ struct config_tree *create_config_tree(const char *filename)
|
||||
|
||||
void destroy_config_tree(struct config_tree *cft)
|
||||
{
|
||||
dm_pool_destroy(((struct cs *) cft)->mem);
|
||||
struct cs *c = (struct cs *) cft;
|
||||
|
||||
if (c->dev)
|
||||
dev_close(c->dev);
|
||||
|
||||
dm_pool_destroy(c->mem);
|
||||
}
|
||||
|
||||
static int _parse_config_file(struct parser *p, struct config_tree *cft)
|
||||
@@ -143,7 +152,7 @@ struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
|
||||
struct config_tree *cft;
|
||||
struct parser *p;
|
||||
|
||||
if (!(cft = create_config_tree(NULL)))
|
||||
if (!(cft = create_config_tree(NULL, 0)))
|
||||
return_NULL;
|
||||
|
||||
c = (struct cs *) cft;
|
||||
@@ -250,7 +259,6 @@ int read_config_file(struct config_tree *cft)
|
||||
{
|
||||
struct cs *c = (struct cs *) cft;
|
||||
struct stat info;
|
||||
struct device *dev;
|
||||
int r = 1;
|
||||
|
||||
if (stat(c->filename, &info)) {
|
||||
@@ -272,22 +280,23 @@ int read_config_file(struct config_tree *cft)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(dev = dev_create_file(c->filename, NULL, NULL, 1))) {
|
||||
stack;
|
||||
return 0;
|
||||
if (!c->dev) {
|
||||
if (!(c->dev = dev_create_file(c->filename, NULL, NULL, 1)))
|
||||
return_0;
|
||||
|
||||
if (!dev_open_flags(c->dev, O_RDONLY, 0, 0))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0,
|
||||
r = read_config_fd(cft, c->dev, 0, (size_t) info.st_size, 0, 0,
|
||||
(checksum_fn_t) NULL, 0);
|
||||
|
||||
dev_close(dev);
|
||||
if (!c->keep_open) {
|
||||
dev_close(c->dev);
|
||||
c->dev = 0;
|
||||
}
|
||||
|
||||
c->timestamp = info.st_mtime;
|
||||
c->timestamp = info.st_ctime;
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -331,7 +340,7 @@ int config_file_changed(struct config_tree *cft)
|
||||
}
|
||||
|
||||
/* Unchanged? */
|
||||
if (c->timestamp == info.st_mtime)
|
||||
if (c->timestamp == info.st_ctime)
|
||||
return 0;
|
||||
|
||||
reload:
|
||||
@@ -763,6 +772,7 @@ static struct config_node *_find_config_node(const struct config_node *cn,
|
||||
const char *path)
|
||||
{
|
||||
const char *e;
|
||||
const struct config_node *cn_found = NULL;
|
||||
|
||||
while (cn) {
|
||||
/* trim any leading slashes */
|
||||
@@ -773,22 +783,30 @@ static struct config_node *_find_config_node(const struct config_node *cn,
|
||||
for (e = path; *e && (*e != sep); e++) ;
|
||||
|
||||
/* hunt for the node */
|
||||
cn_found = NULL;
|
||||
while (cn) {
|
||||
if (_tok_match(cn->key, path, e))
|
||||
break;
|
||||
if (_tok_match(cn->key, path, e)) {
|
||||
/* Inefficient */
|
||||
if (!cn_found)
|
||||
cn_found = cn;
|
||||
else
|
||||
log_error("WARNING: Ignoring duplicate"
|
||||
" config node: %s ("
|
||||
"seeking %s)", cn->key, path);
|
||||
}
|
||||
|
||||
cn = cn->sib;
|
||||
}
|
||||
|
||||
if (cn && *e)
|
||||
cn = cn->child;
|
||||
if (cn_found && *e)
|
||||
cn = cn_found->child;
|
||||
else
|
||||
break; /* don't move into the last node */
|
||||
|
||||
path = e;
|
||||
}
|
||||
|
||||
return (struct config_node *) cn;
|
||||
return (struct config_node *) cn_found;
|
||||
}
|
||||
|
||||
static struct config_node *_find_first_config_node(const struct config_node *cn1,
|
||||
|
||||
@@ -53,7 +53,7 @@ struct config_tree_list {
|
||||
struct config_tree *cft;
|
||||
};
|
||||
|
||||
struct config_tree *create_config_tree(const char *filename);
|
||||
struct config_tree *create_config_tree(const char *filename, int keep_open);
|
||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
|
||||
const char *config_settings);
|
||||
void destroy_config_tree(struct config_tree *cft);
|
||||
|
||||
@@ -605,7 +605,7 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
|
||||
{
|
||||
size_t s;
|
||||
char buffer[4096];
|
||||
char buffer[4096] __attribute((aligned(8)));
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
|
||||
@@ -53,7 +53,7 @@ static int _has_partition_table(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned p;
|
||||
uint8_t buf[SECTOR_SIZE];
|
||||
uint16_t buf[SECTOR_SIZE/sizeof(uint16_t)];
|
||||
uint16_t *part_magic;
|
||||
struct partition *part;
|
||||
|
||||
@@ -70,7 +70,7 @@ static int _has_partition_table(struct device *dev)
|
||||
/* FIXME Check for other types of partition table too */
|
||||
|
||||
/* Check for msdos partition table */
|
||||
part_magic = (uint16_t *)(buf + PART_MAGIC_OFFSET);
|
||||
part_magic = buf + PART_MAGIC_OFFSET/sizeof(buf[0]);
|
||||
if ((*part_magic == xlate16(PART_MAGIC))) {
|
||||
part = (struct partition *) (buf + PART_OFFSET);
|
||||
for (p = 0; p < 4; p++, part++) {
|
||||
|
||||
@@ -82,6 +82,12 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||
case 't':
|
||||
v *= KILO * KILO * KILO * KILO;
|
||||
break;
|
||||
case 'p':
|
||||
v *= KILO * KILO * KILO * KILO * KILO;
|
||||
break;
|
||||
case 'e':
|
||||
v *= KILO * KILO * KILO * KILO * KILO * KILO;
|
||||
break;
|
||||
#undef KILO
|
||||
#define KILO UINT64_C(1000)
|
||||
case 'K':
|
||||
@@ -96,6 +102,12 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||
case 'T':
|
||||
v *= KILO * KILO * KILO * KILO;
|
||||
break;
|
||||
case 'P':
|
||||
v *= KILO * KILO * KILO * KILO * KILO;
|
||||
break;
|
||||
case 'E':
|
||||
v *= KILO * KILO * KILO * KILO * KILO * KILO;
|
||||
break;
|
||||
#undef KILO
|
||||
default:
|
||||
return 0;
|
||||
@@ -143,6 +155,8 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
const char *size_str[][3] = {
|
||||
{" Exabyte", " EB", "E"},
|
||||
{" Petabyte", " PB", "P"},
|
||||
{" Terabyte", " TB", "T"},
|
||||
{" Gigabyte", " GB", "G"},
|
||||
{" Megabyte", " MB", "M"},
|
||||
@@ -161,7 +175,7 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le
|
||||
|
||||
suffix = cmd->current_settings.suffix;
|
||||
|
||||
for (s = 0; s < 8; s++)
|
||||
for (s = 0; s < 10; s++)
|
||||
if (toupper((int) cmd->current_settings.unit_type) ==
|
||||
*size_str[s][2])
|
||||
break;
|
||||
@@ -171,7 +185,7 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le
|
||||
return size_buf;
|
||||
}
|
||||
|
||||
if (s < 8) {
|
||||
if (s < 10) {
|
||||
byte = cmd->current_settings.unit_factor;
|
||||
size *= UINT64_C(512);
|
||||
} else {
|
||||
@@ -181,7 +195,7 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le
|
||||
units = UINT64_C(1000);
|
||||
else
|
||||
units = UINT64_C(1024);
|
||||
byte = units * units * units;
|
||||
byte = units * units * units * units * units;
|
||||
s = 0;
|
||||
while (size_str[s] && size < byte)
|
||||
s++, byte /= units;
|
||||
@@ -220,7 +234,7 @@ const char *display_size(struct cmd_context *cmd, uint64_t size)
|
||||
|
||||
void pvdisplay_colons(struct physical_volume *pv)
|
||||
{
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (!pv)
|
||||
return;
|
||||
@@ -248,7 +262,7 @@ void pvdisplay_colons(struct physical_volume *pv)
|
||||
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
void *handle __attribute((unused)))
|
||||
{
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
const char *size;
|
||||
|
||||
uint32_t pe_free;
|
||||
@@ -310,7 +324,7 @@ int pvdisplay_short(struct cmd_context *cmd __attribute((unused)),
|
||||
struct physical_volume *pv,
|
||||
void *handle __attribute((unused)))
|
||||
{
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (!pv)
|
||||
return 0;
|
||||
@@ -357,7 +371,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
{
|
||||
struct lvinfo info;
|
||||
int inkernel, snap_active = 0;
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
struct lv_segment *snap_seg = NULL;
|
||||
float snap_percent; /* fused, fsize; */
|
||||
|
||||
@@ -523,7 +537,7 @@ void vgdisplay_full(struct volume_group *vg)
|
||||
{
|
||||
uint32_t access;
|
||||
uint32_t active_pvs;
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (vg->status & PARTIAL_VG)
|
||||
active_pvs = list_size(&vg->pvs);
|
||||
@@ -602,7 +616,7 @@ void vgdisplay_colons(struct volume_group *vg)
|
||||
{
|
||||
uint32_t active_pvs;
|
||||
const char *access;
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (vg->status & PARTIAL_VG)
|
||||
active_pvs = list_size(&vg->pvs);
|
||||
|
||||
@@ -50,7 +50,7 @@ static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
|
||||
return dm_tree_node_add_error_target(node, len);
|
||||
}
|
||||
|
||||
static int _errseg_target_present(void)
|
||||
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
|
||||
{
|
||||
static int _errseg_checked = 0;
|
||||
static int _errseg_present = 0;
|
||||
|
||||
@@ -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-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "config.h"
|
||||
#include "dev-cache.h"
|
||||
#include "filter-persistent.h"
|
||||
#include "lvm-file.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -26,11 +27,12 @@ struct pfilter {
|
||||
char *file;
|
||||
struct dm_hash_table *devices;
|
||||
struct dev_filter *real;
|
||||
time_t ctime;
|
||||
};
|
||||
|
||||
/*
|
||||
* entries in the table can be in one of these
|
||||
* states.
|
||||
* The hash table holds one of these two states
|
||||
* against each entry.
|
||||
*/
|
||||
#define PF_BAD_DEVICE ((void *) 1)
|
||||
#define PF_GOOD_DEVICE ((void *) 2)
|
||||
@@ -93,22 +95,26 @@ static int _read_array(struct pfilter *pf, struct config_tree *cft,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int persistent_filter_load(struct dev_filter *f)
|
||||
int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
|
||||
{
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
|
||||
int r = 0;
|
||||
struct config_tree *cft;
|
||||
struct stat info;
|
||||
int r = 0;
|
||||
|
||||
if (!(cft = create_config_tree(pf->file))) {
|
||||
stack;
|
||||
return 0;
|
||||
if (!stat(pf->file, &info))
|
||||
pf->ctime = info.st_ctime;
|
||||
else {
|
||||
log_very_verbose("%s: stat failed: %s", pf->file,
|
||||
strerror(errno));
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!read_config_file(cft)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(cft = create_config_tree(pf->file, 1)))
|
||||
return_0;
|
||||
|
||||
if (!read_config_file(cft))
|
||||
goto_out;
|
||||
|
||||
_read_array(pf, cft, "persistent_filter_cache/valid_devices",
|
||||
PF_GOOD_DEVICE);
|
||||
@@ -126,7 +132,10 @@ int persistent_filter_load(struct dev_filter *f)
|
||||
log_very_verbose("Loaded persistent filter cache from %s", pf->file);
|
||||
|
||||
out:
|
||||
destroy_config_tree(cft);
|
||||
if (r && cft_out)
|
||||
*cft_out = cft;
|
||||
else
|
||||
destroy_config_tree(cft);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -163,8 +172,12 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
|
||||
int persistent_filter_dump(struct dev_filter *f)
|
||||
{
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
|
||||
char *tmp_file;
|
||||
struct stat info, info2;
|
||||
struct config_tree *cft = NULL;
|
||||
FILE *fp;
|
||||
int lockfd;
|
||||
int r = 0;
|
||||
|
||||
if (!dm_hash_get_num_entries(pf->devices)) {
|
||||
log_very_verbose("Internal persistent device cache empty "
|
||||
@@ -179,11 +192,43 @@ int persistent_filter_dump(struct dev_filter *f)
|
||||
|
||||
log_very_verbose("Dumping persistent device cache to %s", pf->file);
|
||||
|
||||
fp = fopen(pf->file, "w");
|
||||
if (!fp) {
|
||||
if (errno != EROFS)
|
||||
log_sys_error("fopen", pf->file);
|
||||
return 0;
|
||||
while (1) {
|
||||
if ((lockfd = fcntl_lock_file(pf->file, F_WRLCK, 0)) < 0)
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* Ensure we locked the file we expected
|
||||
*/
|
||||
if (fstat(lockfd, &info)) {
|
||||
log_sys_error("fstat", pf->file);
|
||||
goto out;
|
||||
}
|
||||
if (stat(pf->file, &info2)) {
|
||||
log_sys_error("stat", pf->file);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!memcmp(&info.st_ino, &info2.st_ino, sizeof(ino_t)))
|
||||
break;
|
||||
|
||||
fcntl_unlock_file(lockfd);
|
||||
}
|
||||
|
||||
/*
|
||||
* If file contents changed since we loaded it, merge new contents
|
||||
*/
|
||||
if (info.st_ctime != pf->ctime)
|
||||
/* Keep cft open to avoid losing lock */
|
||||
persistent_filter_load(f, &cft);
|
||||
|
||||
tmp_file = alloca(strlen(pf->file) + 5);
|
||||
sprintf(tmp_file, "%s.tmp", pf->file);
|
||||
|
||||
if (!(fp = fopen(tmp_file, "w"))) {
|
||||
/* EACCES has been reported over NFS */
|
||||
if (errno != EROFS && errno != EACCES)
|
||||
log_sys_error("fopen", tmp_file);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fprintf(fp, "# This file is automatically maintained by lvm.\n\n");
|
||||
@@ -195,7 +240,20 @@ int persistent_filter_dump(struct dev_filter *f)
|
||||
|
||||
fprintf(fp, "}\n");
|
||||
fclose(fp);
|
||||
return 1;
|
||||
|
||||
if (rename(tmp_file, pf->file))
|
||||
log_error("%s: rename to %s failed: %s", tmp_file, pf->file,
|
||||
strerror(errno));
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
fcntl_unlock_file(lockfd);
|
||||
|
||||
if (cft)
|
||||
destroy_config_tree(cft);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||
|
||||
@@ -22,7 +22,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *f,
|
||||
const char *file);
|
||||
|
||||
int persistent_filter_wipe(struct dev_filter *f);
|
||||
int persistent_filter_load(struct dev_filter *f);
|
||||
int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out);
|
||||
int persistent_filter_dump(struct dev_filter *f);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -248,7 +248,7 @@ static int _read_uuids(struct disk_list *data)
|
||||
{
|
||||
unsigned num_read = 0;
|
||||
struct uuid_list *ul;
|
||||
char buffer[NAME_LEN];
|
||||
char buffer[NAME_LEN] __attribute((aligned(8)));
|
||||
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
|
||||
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ struct pe_disk {
|
||||
|
||||
struct uuid_list {
|
||||
struct list list;
|
||||
char uuid[NAME_LEN];
|
||||
char uuid[NAME_LEN] __attribute((aligned(8)));
|
||||
};
|
||||
|
||||
struct lvd_list {
|
||||
@@ -161,11 +161,11 @@ struct disk_list {
|
||||
struct dm_pool *mem;
|
||||
struct device *dev;
|
||||
|
||||
struct pv_disk pvd;
|
||||
struct vg_disk vgd;
|
||||
struct list uuids;
|
||||
struct list lvds;
|
||||
struct pe_disk *extents;
|
||||
struct pv_disk pvd __attribute((aligned(8)));
|
||||
struct vg_disk vgd __attribute((aligned(8)));
|
||||
struct list uuids __attribute((aligned(8)));
|
||||
struct list lvds __attribute((aligned(8)));
|
||||
struct pe_disk *extents __attribute((aligned(8)));
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -203,8 +203,8 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
|
||||
* Functions to translate to between disk and in
|
||||
* core structures.
|
||||
*/
|
||||
int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
struct volume_group *vg,
|
||||
int import_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
struct device *dev, struct volume_group *vg,
|
||||
struct physical_volume *pv, struct pv_disk *pvd,
|
||||
struct vg_disk *vgd);
|
||||
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
|
||||
|
||||
@@ -312,7 +312,7 @@ static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
|
||||
if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "toolcontext.h"
|
||||
#include "segtype.h"
|
||||
#include "pv_alloc.h"
|
||||
#include "display.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -47,11 +48,13 @@ static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
|
||||
return dm_pool_strdup(mem, ptr);
|
||||
}
|
||||
|
||||
int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
struct volume_group *vg,
|
||||
int import_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
struct device *dev, struct volume_group *vg,
|
||||
struct physical_volume *pv, struct pv_disk *pvd,
|
||||
struct vg_disk *vgd)
|
||||
{
|
||||
uint64_t size;
|
||||
|
||||
memset(pv, 0, sizeof(*pv));
|
||||
memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
|
||||
|
||||
@@ -89,6 +92,25 @@ int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
pv->pe_count = pvd->pe_total;
|
||||
pv->pe_alloc_count = 0;
|
||||
|
||||
/* Fix up pv size if missing */
|
||||
if (!pv->size) {
|
||||
if (!dev_get_size(dev, &pv->size)) {
|
||||
log_error("%s: Couldn't get size.", dev_name(pv->dev));
|
||||
return 0;
|
||||
}
|
||||
log_verbose("Fixing up missing format1 size (%s) "
|
||||
"for PV %s", display_size(fmt->cmd, pv->size),
|
||||
dev_name(pv->dev));
|
||||
if (vg) {
|
||||
size = pv->pe_count * (uint64_t) vg->extent_size +
|
||||
pv->pe_start;
|
||||
if (size > pv->size)
|
||||
log_error("WARNING: Physical Volume %s is too "
|
||||
"large for underlying device",
|
||||
dev_name(pv->dev));
|
||||
}
|
||||
}
|
||||
|
||||
list_init(&pv->tags);
|
||||
list_init(&pv->segments);
|
||||
|
||||
@@ -427,7 +449,7 @@ int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
|
||||
if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ static void _not_supported(const char *op)
|
||||
op);
|
||||
}
|
||||
|
||||
static int _lvm1_can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
static int _lvm1_can_handle(struct labeller *l, void *buf, uint64_t sector)
|
||||
{
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
uint32_t version;
|
||||
@@ -48,13 +48,13 @@ static int _lvm1_can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lvm1_write(struct label *label, char *buf)
|
||||
static int _lvm1_write(struct label *label, void *buf)
|
||||
{
|
||||
_not_supported("write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lvm1_read(struct labeller *l, struct device *dev, char *buf,
|
||||
static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
|
||||
@@ -36,7 +36,7 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
|
||||
struct dm_pool *mem, struct pool_list *pl,
|
||||
const char *vg_name)
|
||||
{
|
||||
char buf[512];
|
||||
char buf[512] __attribute((aligned(8)));
|
||||
|
||||
/* FIXME: Need to check the cache here first */
|
||||
if (!dev_read(dev, UINT64_C(0), 512, buf)) {
|
||||
@@ -59,7 +59,7 @@ static void _add_pl_to_list(struct list *head, struct pool_list *data)
|
||||
|
||||
list_iterate_items(pl, head) {
|
||||
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
|
||||
char uuid[ID_LEN + 7];
|
||||
char uuid[ID_LEN + 7] __attribute((aligned(8)));
|
||||
|
||||
id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
|
||||
|
||||
@@ -84,7 +84,7 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
struct lvmcache_info *info;
|
||||
struct id pvid;
|
||||
struct id vgid;
|
||||
char uuid[ID_LEN + 7];
|
||||
char uuid[ID_LEN + 7] __attribute((aligned(8)));
|
||||
struct pool_disk *pd = &pl->pd;
|
||||
|
||||
pool_label_in(pd, buf);
|
||||
@@ -128,7 +128,7 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
* be able to interpret ondisk labels correctly. Always use
|
||||
* this function before writing to disk.
|
||||
*/
|
||||
void pool_label_out(struct pool_disk *pl, char *buf)
|
||||
void pool_label_out(struct pool_disk *pl, void *buf)
|
||||
{
|
||||
struct pool_disk *bufpl = (struct pool_disk *) buf;
|
||||
|
||||
@@ -163,7 +163,7 @@ void pool_label_out(struct pool_disk *pl, char *buf)
|
||||
* correctly. Always use this function before using labels that
|
||||
* were read from disk.
|
||||
*/
|
||||
void pool_label_in(struct pool_disk *pl, char *buf)
|
||||
void pool_label_in(struct pool_disk *pl, void *buf)
|
||||
{
|
||||
struct pool_disk *bufpl = (struct pool_disk *) buf;
|
||||
|
||||
|
||||
@@ -134,8 +134,8 @@ struct user_device {
|
||||
|
||||
int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
struct device *dev, char *buf, struct label **label);
|
||||
void pool_label_out(struct pool_disk *pl, char *buf);
|
||||
void pool_label_in(struct pool_disk *pl, char *buf);
|
||||
void pool_label_out(struct pool_disk *pl, void *buf);
|
||||
void pool_label_in(struct pool_disk *pl, void *buf);
|
||||
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
|
||||
int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct list *pls);
|
||||
int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem,
|
||||
|
||||
@@ -29,7 +29,7 @@ static void _pool_not_supported(const char *op)
|
||||
op);
|
||||
}
|
||||
|
||||
static int _pool_can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
static int _pool_can_handle(struct labeller *l, void *buf, uint64_t sector)
|
||||
{
|
||||
|
||||
struct pool_disk pd;
|
||||
@@ -50,13 +50,13 @@ static int _pool_can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _pool_write(struct label *label, char *buf)
|
||||
static int _pool_write(struct label *label, void *buf)
|
||||
{
|
||||
_pool_not_supported("write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _pool_read(struct labeller *l, struct device *dev, char *buf,
|
||||
static int _pool_read(struct labeller *l, struct device *dev, void *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct pool_list pl;
|
||||
|
||||
@@ -221,6 +221,8 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
|
||||
"Megabytes",
|
||||
"Gigabytes",
|
||||
"Terabytes",
|
||||
"Petabytes",
|
||||
"Exabytes",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
int *precommitted)
|
||||
{
|
||||
size_t len;
|
||||
char vgnamebuf[NAME_LEN + 2];
|
||||
char vgnamebuf[NAME_LEN + 2] __attribute((aligned(8)));
|
||||
struct raw_locn *rlocn, *rlocn_precommitted;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
@@ -885,8 +885,8 @@ const char *vgname_from_mda(const struct format_type *fmt,
|
||||
uint32_t wrap = 0;
|
||||
const char *vgname = NULL;
|
||||
unsigned int len = 0;
|
||||
char buf[NAME_LEN + 1];
|
||||
char uuid[64];
|
||||
char buf[NAME_LEN + 1] __attribute((aligned(8)));
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (!dev_open(dev_area->dev)) {
|
||||
stack;
|
||||
@@ -1131,7 +1131,7 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
||||
struct lvmcache_info *info;
|
||||
struct mda_context *mdac;
|
||||
struct metadata_area *mda;
|
||||
char buf[MDA_HEADER_SIZE];
|
||||
char buf[MDA_HEADER_SIZE] __attribute((aligned(8)));
|
||||
struct mda_header *mdah = (struct mda_header *) buf;
|
||||
uint64_t adjustment;
|
||||
|
||||
@@ -1408,6 +1408,7 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
uint64_t pe_end = 0;
|
||||
unsigned mda_count = 0;
|
||||
uint64_t mda_size2 = 0;
|
||||
uint64_t pe_count;
|
||||
|
||||
/* FIXME Cope with pvchange */
|
||||
/* FIXME Merge code with _text_create_text_instance */
|
||||
@@ -1473,8 +1474,17 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
pv->pe_start + mda_size2;
|
||||
|
||||
/* Recalculate number of extents that will fit */
|
||||
if (!pv->pe_count)
|
||||
pv->pe_count = (pv->size - pv->pe_start - mda_size2) / vg->extent_size;
|
||||
if (!pv->pe_count) {
|
||||
pe_count = (pv->size - pv->pe_start - mda_size2) /
|
||||
vg->extent_size;
|
||||
if (pe_count > UINT32_MAX) {
|
||||
log_error("PV %s too large for extent size %s.",
|
||||
dev_name(pv->dev),
|
||||
display_size(vg->cmd, (uint64_t) vg->extent_size));
|
||||
return 0;
|
||||
}
|
||||
pv->pe_count = (uint32_t) pe_count;
|
||||
}
|
||||
|
||||
/* Unlike LVM1, we don't store this outside a VG */
|
||||
/* FIXME Default from config file? vgextend cmdline flag? */
|
||||
@@ -1732,7 +1742,7 @@ static int _get_config_disk_area(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
if (!(dev_area.dev = device_from_pvid(cmd, &id))) {
|
||||
char buffer[64];
|
||||
char buffer[64] __attribute((aligned(8)));
|
||||
|
||||
if (!id_write_format(&id, buffer, sizeof(buffer)))
|
||||
log_err("Couldn't find device.");
|
||||
|
||||
@@ -43,7 +43,7 @@ const char *text_vgname_import(const struct format_type *fmt,
|
||||
_text_import_initialised = 1;
|
||||
}
|
||||
|
||||
if (!(cft = create_config_tree(NULL)))
|
||||
if (!(cft = create_config_tree(NULL, 0)))
|
||||
return_NULL;
|
||||
|
||||
if ((!dev && !read_config_file(cft)) ||
|
||||
@@ -94,7 +94,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
*desc = NULL;
|
||||
*when = 0;
|
||||
|
||||
if (!(cft = create_config_tree(file)))
|
||||
if (!(cft = create_config_tree(file, 0)))
|
||||
return_NULL;
|
||||
|
||||
if ((!dev && !read_config_file(cft)) ||
|
||||
|
||||
@@ -116,6 +116,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
struct physical_volume *pv;
|
||||
struct pv_list *pvl;
|
||||
struct config_node *cn;
|
||||
uint64_t size;
|
||||
|
||||
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
|
||||
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
|
||||
@@ -148,7 +149,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
* Convert the uuid into a device.
|
||||
*/
|
||||
if (!(pv->dev = device_from_pvid(fid->fmt->cmd, &pv->id))) {
|
||||
char buffer[64];
|
||||
char buffer[64] __attribute((aligned(8)));
|
||||
|
||||
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
|
||||
log_error("Couldn't find device.");
|
||||
@@ -213,6 +214,25 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
pv->pe_alloc_count = 0;
|
||||
pv->fmt = fid->fmt;
|
||||
|
||||
/* Fix up pv size if missing */
|
||||
if (!pv->size && pv->dev) {
|
||||
if (!dev_get_size(pv->dev, &pv->size)) {
|
||||
log_error("%s: Couldn't get size.", dev_name(pv->dev));
|
||||
return 0;
|
||||
}
|
||||
log_verbose("Fixing up missing format1 size (%s) "
|
||||
"for PV %s", display_size(fid->fmt->cmd, pv->size),
|
||||
dev_name(pv->dev));
|
||||
if (vg) {
|
||||
size = pv->pe_count * (uint64_t) vg->extent_size +
|
||||
pv->pe_start;
|
||||
if (size > pv->size)
|
||||
log_error("WARNING: Physical Volume %s is too "
|
||||
"large for underlying device",
|
||||
dev_name(pv->dev));
|
||||
}
|
||||
}
|
||||
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
static int _text_can_handle(struct labeller *l __attribute((unused)),
|
||||
char *buf,
|
||||
void *buf,
|
||||
uint64_t sector __attribute((unused)))
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
@@ -35,7 +35,7 @@ static int _text_can_handle(struct labeller *l __attribute((unused)),
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _text_write(struct label *label, char *buf)
|
||||
static int _text_write(struct label *label, void *buf)
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
struct pv_header *pvhdr;
|
||||
@@ -189,7 +189,7 @@ static int _text_initialise_label(struct labeller *l __attribute((unused)),
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _text_read(struct labeller *l, struct device *dev, char *buf,
|
||||
static int _text_read(struct labeller *l, struct device *dev, void *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
|
||||
@@ -115,7 +115,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
struct lvmcache_info *info;
|
||||
uint64_t sector;
|
||||
int found = 0;
|
||||
char readbuf[LABEL_SCAN_SIZE];
|
||||
char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
|
||||
|
||||
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
|
||||
log_debug("%s: Failed to read label area", dev_name(dev));
|
||||
@@ -186,8 +186,8 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
/* FIXME Also wipe associated metadata area headers? */
|
||||
int label_remove(struct device *dev)
|
||||
{
|
||||
char buf[LABEL_SIZE];
|
||||
char readbuf[LABEL_SCAN_SIZE];
|
||||
char buf[LABEL_SIZE] __attribute((aligned(8)));
|
||||
char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
|
||||
int r = 1;
|
||||
uint64_t sector;
|
||||
int wipe;
|
||||
@@ -258,7 +258,7 @@ int label_remove(struct device *dev)
|
||||
/* FIXME Avoid repeated re-reading if cache lock held */
|
||||
int label_read(struct device *dev, struct label **result)
|
||||
{
|
||||
char buf[LABEL_SIZE];
|
||||
char buf[LABEL_SIZE] __attribute((aligned(8)));
|
||||
struct labeller *l;
|
||||
uint64_t sector;
|
||||
struct lvmcache_info *info;
|
||||
@@ -290,7 +290,7 @@ int label_read(struct device *dev, struct label **result)
|
||||
/* Caller may need to use label_get_handler to create label struct! */
|
||||
int label_write(struct device *dev, struct label *label)
|
||||
{
|
||||
char buf[LABEL_SIZE];
|
||||
char buf[LABEL_SIZE] __attribute((aligned(8)));
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
int r = 1;
|
||||
|
||||
@@ -341,19 +341,17 @@ int label_write(struct device *dev, struct label *label)
|
||||
int label_verify(struct device *dev)
|
||||
{
|
||||
struct labeller *l;
|
||||
char buf[LABEL_SIZE];
|
||||
char buf[LABEL_SIZE] __attribute((aligned(8)));
|
||||
uint64_t sector;
|
||||
struct lvmcache_info *info;
|
||||
int r = 0;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
0, NULL);
|
||||
|
||||
goto out;
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or)))
|
||||
|
||||
@@ -49,23 +49,23 @@ struct label_ops {
|
||||
/*
|
||||
* Is the device labelled with this format ?
|
||||
*/
|
||||
int (*can_handle) (struct labeller * l, char *buf, uint64_t sector);
|
||||
int (*can_handle) (struct labeller * l, void *buf, uint64_t sector);
|
||||
|
||||
/*
|
||||
* Write a label to a volume.
|
||||
*/
|
||||
int (*write) (struct label * label, char *buf);
|
||||
int (*write) (struct label * label, void *buf);
|
||||
|
||||
/*
|
||||
* Read a label from a volume.
|
||||
*/
|
||||
int (*read) (struct labeller * l, struct device * dev,
|
||||
char *buf, struct label ** label);
|
||||
void *buf, struct label ** label);
|
||||
|
||||
/*
|
||||
* Additional consistency checks for the paranoid.
|
||||
*/
|
||||
int (*verify) (struct labeller * l, char *buf, uint64_t sector);
|
||||
int (*verify) (struct labeller * l, void *buf, uint64_t sector);
|
||||
|
||||
/*
|
||||
* Populate label_type etc.
|
||||
|
||||
@@ -94,7 +94,7 @@ static int _open_local_sock(void)
|
||||
/* Send a request and return the status */
|
||||
static int _send_request(char *inbuf, int inlen, char **retbuf)
|
||||
{
|
||||
char outbuf[PIPE_BUF];
|
||||
char outbuf[PIPE_BUF] __attribute((aligned(8)));
|
||||
struct clvm_header *outheader = (struct clvm_header *) outbuf;
|
||||
int len;
|
||||
int off;
|
||||
@@ -195,8 +195,7 @@ static void _build_header(struct clvm_header *head, int cmd, const char *node,
|
||||
static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
int *outptr;
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1] __attribute((aligned(8)));
|
||||
char *inptr;
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
@@ -236,17 +235,13 @@ static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
* With an extra pair of INTs on the front to sanity
|
||||
* check the pointer when we are given it back to free
|
||||
*/
|
||||
outptr = dm_malloc(sizeof(lvm_response_t) * num_responses +
|
||||
sizeof(int) * 2);
|
||||
if (!outptr) {
|
||||
*response = dm_malloc(sizeof(lvm_response_t) * num_responses);
|
||||
if (!*response) {
|
||||
errno = ENOMEM;
|
||||
status = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*response = (lvm_response_t *) (outptr + 2);
|
||||
outptr[0] = LVM_SIGNATURE;
|
||||
outptr[1] = num_responses;
|
||||
rarray = *response;
|
||||
|
||||
/* Unpack the response into an lvm_response_t array */
|
||||
@@ -265,7 +260,7 @@ static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
dm_free(rarray[i].response);
|
||||
free(outptr);
|
||||
free(*response);
|
||||
errno = ENOMEM;
|
||||
status = -1;
|
||||
goto out;
|
||||
@@ -287,25 +282,15 @@ static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
}
|
||||
|
||||
/* Free reply array */
|
||||
static int _cluster_free_request(lvm_response_t * response)
|
||||
static int _cluster_free_request(lvm_response_t * response, int num)
|
||||
{
|
||||
int *ptr = (int *) response - 2;
|
||||
int i;
|
||||
int num;
|
||||
|
||||
/* Check it's ours to free */
|
||||
if (response == NULL || *ptr != LVM_SIGNATURE) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
num = ptr[1];
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
dm_free(response[i].response);
|
||||
}
|
||||
|
||||
dm_free(ptr);
|
||||
dm_free(response);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -374,7 +359,7 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
_cluster_free_request(response);
|
||||
_cluster_free_request(response, num_responses);
|
||||
errno = saved_errno;
|
||||
|
||||
return status;
|
||||
|
||||
@@ -144,18 +144,18 @@ int init_locking(int type, struct cmd_context *cmd)
|
||||
case 2:
|
||||
if (!cmd->is_static) {
|
||||
log_very_verbose("External locking selected.");
|
||||
if (!init_external_locking(&_locking, cmd))
|
||||
break;
|
||||
return 1;
|
||||
if (init_external_locking(&_locking, cmd))
|
||||
return 1;
|
||||
}
|
||||
if (!find_config_tree_int(cmd, "locking/fallback_to_clustered_locking",
|
||||
DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING))
|
||||
break;
|
||||
log_very_verbose("Falling back to clustered locking.");
|
||||
/* Fall through */
|
||||
#endif
|
||||
|
||||
#ifdef CLUSTER_LOCKING_INTERNAL
|
||||
log_very_verbose("Falling back to internal clustered locking.");
|
||||
/* Fall through */
|
||||
|
||||
case 3:
|
||||
log_very_verbose("Cluster locking selected.");
|
||||
if (!init_cluster_locking(&_locking, cmd))
|
||||
@@ -249,7 +249,7 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource, int flags)
|
||||
|
||||
int lock_vol(struct cmd_context *cmd, const char *vol, int flags)
|
||||
{
|
||||
char resource[258];
|
||||
char resource[258] __attribute((aligned(8)));
|
||||
|
||||
switch (flags & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
|
||||
@@ -50,7 +50,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_NULL 0x00000000 /* LCK$_NLMODE */
|
||||
#define LCK_READ 0x00000001 /* LCK$_CRMODE */
|
||||
/* LCK$_CWMODE */
|
||||
/* LCK$_PRMODE */
|
||||
#define LCK_PREAD 0x00000003 /* LCK$_PRMODE */
|
||||
#define LCK_WRITE 0x00000004 /* LCK$_PWMODE */
|
||||
#define LCK_EXCL 0x00000005 /* LCK$_EXMODE */
|
||||
#define LCK_UNLOCK 0x00000006 /* This is ours */
|
||||
|
||||
@@ -415,6 +415,15 @@ struct alloc_handle {
|
||||
struct list alloced_areas[0]; /* Lists of areas in each stripe */
|
||||
};
|
||||
|
||||
static uint32_t calc_area_multiple(const struct segment_type *segtype,
|
||||
const uint32_t area_count)
|
||||
{
|
||||
if (!segtype_is_striped(segtype) || !area_count)
|
||||
return 1;
|
||||
|
||||
return area_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preparation for a specific allocation attempt
|
||||
*/
|
||||
@@ -476,7 +485,7 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
|
||||
ah->area_count = area_count;
|
||||
ah->log_count = log_count;
|
||||
ah->alloc = alloc;
|
||||
ah->area_multiple = segtype_is_striped(segtype) ? ah->area_count : 1;
|
||||
ah->area_multiple = calc_area_multiple(segtype, area_count);
|
||||
|
||||
for (s = 0; s < ah->area_count; s++)
|
||||
list_init(&ah->alloced_areas[s]);
|
||||
@@ -553,7 +562,7 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint32_t status,
|
||||
if (mirrored_pv)
|
||||
extra_areas = 1;
|
||||
|
||||
area_multiple = segtype_is_striped(segtype) ? area_count : 1;
|
||||
area_multiple = calc_area_multiple(segtype, area_count);
|
||||
|
||||
/* log_lv gets set up elsehere */
|
||||
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, segtype, lv,
|
||||
@@ -628,17 +637,17 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t needed,
|
||||
struct pv_area **areas,
|
||||
uint32_t *ix, struct pv_area *log_area)
|
||||
{
|
||||
uint32_t area_len, smallest, remaining;
|
||||
uint32_t area_len, remaining;
|
||||
uint32_t s;
|
||||
struct alloced_area *aa;
|
||||
|
||||
remaining = needed - *ix;
|
||||
area_len = remaining / ah->area_multiple;
|
||||
|
||||
smallest = areas[ah->area_count - 1]->count;
|
||||
|
||||
if (area_len > smallest)
|
||||
area_len = smallest;
|
||||
/* Reduce area_len to the smallest of the areas */
|
||||
for (s = 0; s < ah->area_count; s++)
|
||||
if (area_len > areas[s]->count)
|
||||
area_len = areas[s]->count;
|
||||
|
||||
if (!(aa = dm_pool_alloc(ah->mem, sizeof(*aa) *
|
||||
(ah->area_count + (log_area ? 1 : 0))))) {
|
||||
@@ -707,7 +716,7 @@ static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (max_seg_len && *max_seg_len > remaining_seg_len)
|
||||
*max_seg_len = remaining_seg_len;
|
||||
|
||||
area_multiple = segtype_is_striped(seg->segtype) ? seg->area_count : 1;
|
||||
area_multiple = calc_area_multiple(seg->segtype, seg->area_count);
|
||||
area_len = remaining_seg_len / area_multiple ? : 1;
|
||||
|
||||
for (s = first_area;
|
||||
@@ -890,8 +899,17 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
uint32_t next_le;
|
||||
struct seg_pvs *spvs;
|
||||
struct list *parallel_pvs;
|
||||
uint32_t free_pes;
|
||||
|
||||
/* Is there enough total space? */
|
||||
free_pes = pv_maps_size(pvms);
|
||||
if (needed - *allocated > free_pes) {
|
||||
log_error("Insufficient free space: %" PRIu32 " extents needed,"
|
||||
" but only %" PRIu32 " available",
|
||||
needed - *allocated, free_pes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME Do calculations on free extent counts before selecting space */
|
||||
/* FIXME Select log PV appropriately if there isn't one yet */
|
||||
|
||||
/* Are there any preceding segments we must follow on from? */
|
||||
@@ -1057,6 +1075,7 @@ static int _allocate(struct alloc_handle *ah,
|
||||
int r = 0;
|
||||
struct list *pvms;
|
||||
uint32_t areas_size;
|
||||
alloc_policy_t alloc;
|
||||
|
||||
if (allocated >= new_extents && !ah->log_count) {
|
||||
log_error("_allocate called with no work to do!");
|
||||
@@ -1102,50 +1121,18 @@ static int _allocate(struct alloc_handle *ah,
|
||||
return 0;
|
||||
}
|
||||
|
||||
old_allocated = allocated;
|
||||
if (!_find_parallel_space(ah, ALLOC_CONTIGUOUS, pvms, areas,
|
||||
areas_size, can_split,
|
||||
prev_lvseg, &allocated, new_extents)) {
|
||||
stack;
|
||||
goto out;
|
||||
/* Attempt each defined allocation policy in turn */
|
||||
for (alloc = ALLOC_CONTIGUOUS; alloc < ALLOC_INHERIT; alloc++) {
|
||||
old_allocated = allocated;
|
||||
if (!_find_parallel_space(ah, alloc, pvms, areas,
|
||||
areas_size, can_split,
|
||||
prev_lvseg, &allocated, new_extents))
|
||||
goto_out;
|
||||
if ((allocated == new_extents) || (ah->alloc == alloc) ||
|
||||
(!can_split && (allocated != old_allocated)))
|
||||
break;
|
||||
}
|
||||
|
||||
if ((allocated == new_extents) || (ah->alloc == ALLOC_CONTIGUOUS) ||
|
||||
(!can_split && (allocated != old_allocated)))
|
||||
goto finished;
|
||||
|
||||
old_allocated = allocated;
|
||||
if (!_find_parallel_space(ah, ALLOC_CLING, pvms, areas,
|
||||
areas_size, can_split,
|
||||
prev_lvseg, &allocated, new_extents)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((allocated == new_extents) || (ah->alloc == ALLOC_CLING) ||
|
||||
(!can_split && (allocated != old_allocated)))
|
||||
goto finished;
|
||||
|
||||
old_allocated = allocated;
|
||||
if (!_find_parallel_space(ah, ALLOC_NORMAL, pvms, areas,
|
||||
areas_size, can_split,
|
||||
prev_lvseg, &allocated, new_extents)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((allocated == new_extents) || (ah->alloc == ALLOC_NORMAL) ||
|
||||
(!can_split && (allocated != old_allocated)))
|
||||
goto finished;
|
||||
|
||||
if (!_find_parallel_space(ah, ALLOC_ANYWHERE, pvms, areas,
|
||||
areas_size, can_split,
|
||||
prev_lvseg, &allocated, new_extents)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
finished:
|
||||
if (allocated != new_extents) {
|
||||
log_error("Insufficient suitable %sallocatable extents "
|
||||
"for logical volume %s: %u more required",
|
||||
@@ -1156,6 +1143,13 @@ static int _allocate(struct alloc_handle *ah,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ah->log_count && !ah->log_area.len) {
|
||||
log_error("Insufficient extents for log allocation "
|
||||
"for logical volume %s.",
|
||||
lv ? lv->name : "");
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "str_list.h"
|
||||
#include "pv_alloc.h"
|
||||
#include "activate.h"
|
||||
#include "display.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
@@ -122,6 +123,15 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
|
||||
pvl->pv = pv;
|
||||
list_add(&vg->pvs, &pvl->list);
|
||||
|
||||
if ((uint64_t) vg->extent_count + pv->pe_count > UINT32_MAX) {
|
||||
log_error("Unable to add %s to %s: new extent count (%"
|
||||
PRIu64 ") exceeds limit (%" PRIu32 ").",
|
||||
pv_name, vg->name,
|
||||
(uint64_t) vg->extent_count + pv->pe_count,
|
||||
UINT32_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vg->pv_count++;
|
||||
vg->extent_count += pv->pe_count;
|
||||
vg->free_count += pv->pe_count;
|
||||
@@ -728,7 +738,7 @@ int vg_validate(struct volume_group *vg)
|
||||
{
|
||||
struct pv_list *pvl, *pvl2;
|
||||
struct lv_list *lvl, *lvl2;
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
int r = 1;
|
||||
|
||||
/* FIXME Also check there's no data/metadata overlap */
|
||||
|
||||
@@ -78,17 +78,18 @@
|
||||
#define FMT_RESIZE_PV 0x00000080U /* Supports pvresize? */
|
||||
#define FMT_UNLIMITED_STRIPESIZE 0x00000100U /* Unlimited stripe size? */
|
||||
|
||||
/* Ordered list - see lv_manip.c */
|
||||
typedef enum {
|
||||
ALLOC_INVALID = 0,
|
||||
ALLOC_INHERIT,
|
||||
ALLOC_INVALID,
|
||||
ALLOC_CONTIGUOUS,
|
||||
ALLOC_CLING,
|
||||
ALLOC_NORMAL,
|
||||
ALLOC_ANYWHERE
|
||||
ALLOC_ANYWHERE,
|
||||
ALLOC_INHERIT
|
||||
} alloc_policy_t;
|
||||
|
||||
typedef enum {
|
||||
AREA_UNASSIGNED = 0,
|
||||
AREA_UNASSIGNED,
|
||||
AREA_PV,
|
||||
AREA_LV
|
||||
} area_type_t;
|
||||
@@ -285,7 +286,7 @@ struct logical_volume {
|
||||
int32_t major;
|
||||
int32_t minor;
|
||||
|
||||
uint64_t size;
|
||||
uint64_t size; /* Sectors */
|
||||
uint32_t le_count;
|
||||
|
||||
uint32_t origin_count;
|
||||
|
||||
@@ -36,20 +36,20 @@ struct lv_segment *find_mirror_seg(struct lv_segment *seg)
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure region size is compatible with volume size.
|
||||
* Reduce the region size if necessary to ensure
|
||||
* the volume size is a multiple of the region size.
|
||||
*/
|
||||
uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
|
||||
uint32_t region_size)
|
||||
{
|
||||
uint32_t region_max;
|
||||
uint64_t region_max;
|
||||
|
||||
region_max = (1 << (ffs((int)extents) - 1)) * extent_size;
|
||||
region_max = (1 << (ffs((int)extents) - 1)) * (uint64_t) extent_size;
|
||||
|
||||
if (region_max < region_size) {
|
||||
region_size = region_max;
|
||||
if (region_max < UINT32_MAX && region_size > region_max) {
|
||||
region_size = (uint32_t) region_max;
|
||||
log_print("Using reduced mirror region size of %" PRIu32
|
||||
" sectors", region_max);
|
||||
return region_max;
|
||||
" sectors", region_size);
|
||||
}
|
||||
|
||||
return region_size;
|
||||
@@ -84,6 +84,7 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
struct list *removable_pvs, int remove_log)
|
||||
{
|
||||
uint32_t m;
|
||||
uint32_t extents;
|
||||
uint32_t s, s1;
|
||||
struct logical_volume *sub_lv;
|
||||
struct logical_volume *log_lv = NULL;
|
||||
@@ -95,6 +96,7 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
struct pv_list *pvl;
|
||||
uint32_t old_area_count = mirrored_seg->area_count;
|
||||
uint32_t new_area_count = mirrored_seg->area_count;
|
||||
struct segment_type *segtype;
|
||||
|
||||
log_very_verbose("Reducing mirror set from %" PRIu32 " to %"
|
||||
PRIu32 " image(s)%s.",
|
||||
@@ -156,9 +158,14 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
/* If no more mirrors, remove mirror layer */
|
||||
if (num_mirrors == 1) {
|
||||
lv1 = seg_lv(mirrored_seg, 0);
|
||||
extents = lv1->le_count;
|
||||
_move_lv_segments(mirrored_seg->lv, lv1);
|
||||
mirrored_seg->lv->status &= ~MIRRORED;
|
||||
remove_log = 1;
|
||||
/* Replace mirror with error segment */
|
||||
segtype = get_segtype_from_string(mirrored_seg->lv->vg->cmd, "error");
|
||||
if (!lv_add_virtual_segment(lv1, 0, extents, segtype))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (remove_log && mirrored_seg->log_lv) {
|
||||
@@ -174,8 +181,6 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
* then deactivate and remove them fully.
|
||||
*/
|
||||
|
||||
/* FIXME lv1 has no segments here so shouldn't be written to disk! */
|
||||
|
||||
if (!vg_write(mirrored_seg->lv->vg)) {
|
||||
log_error("intermediate VG write failed.");
|
||||
return 0;
|
||||
@@ -562,7 +567,7 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
if (activation() && segtype->ops->target_present &&
|
||||
!segtype->ops->target_present()) {
|
||||
!segtype->ops->target_present(NULL)) {
|
||||
log_error("%s: Required device-mapper target(s) not "
|
||||
"detected in your kernel", segtype->name);
|
||||
return 0;
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
/*
|
||||
* Areas are maintained in size order, largest first.
|
||||
*
|
||||
* FIXME Cope with overlap.
|
||||
*/
|
||||
static void _insert_area(struct list *head, struct pv_area *a)
|
||||
{
|
||||
@@ -30,6 +32,7 @@ static void _insert_area(struct list *head, struct pv_area *a)
|
||||
}
|
||||
|
||||
list_add(&pva->list, &a->list);
|
||||
a->map->pe_count += a->count;
|
||||
}
|
||||
|
||||
static int _create_single_area(struct dm_pool *mem, struct pv_map *pvm,
|
||||
@@ -126,23 +129,32 @@ static int _create_all_areas_for_pv(struct dm_pool *mem, struct pv_map *pvm,
|
||||
|
||||
static int _create_maps(struct dm_pool *mem, struct list *pvs, struct list *pvms)
|
||||
{
|
||||
struct pv_map *pvm;
|
||||
struct pv_map *pvm, *pvm2;
|
||||
struct pv_list *pvl;
|
||||
|
||||
list_iterate_items(pvl, pvs) {
|
||||
if (!(pvl->pv->status & ALLOCATABLE_PV))
|
||||
continue;
|
||||
|
||||
if (!(pvm = dm_pool_zalloc(mem, sizeof(*pvm)))) {
|
||||
stack;
|
||||
return 0;
|
||||
pvm = NULL;
|
||||
|
||||
list_iterate_items(pvm2, pvms)
|
||||
if (pvm2->pv->dev == pvl->pv->dev) {
|
||||
pvm = pvm2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pvm) {
|
||||
if (!(pvm = dm_pool_zalloc(mem, sizeof(*pvm)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pvm->pv = pvl->pv;
|
||||
list_init(&pvm->areas);
|
||||
list_add(pvms, &pvm->list);
|
||||
}
|
||||
|
||||
pvm->pv = pvl->pv;
|
||||
|
||||
list_init(&pvm->areas);
|
||||
list_add(pvms, &pvm->list);
|
||||
|
||||
if (!_create_all_areas_for_pv(mem, pvm, pvl->pe_ranges)) {
|
||||
stack;
|
||||
return 0;
|
||||
@@ -180,6 +192,7 @@ struct list *create_pv_maps(struct dm_pool *mem, struct volume_group *vg,
|
||||
void consume_pv_area(struct pv_area *pva, uint32_t to_go)
|
||||
{
|
||||
list_del(&pva->list);
|
||||
pva->map->pe_count -= pva->count;
|
||||
|
||||
assert(to_go <= pva->count);
|
||||
|
||||
@@ -190,3 +203,14 @@ void consume_pv_area(struct pv_area *pva, uint32_t to_go)
|
||||
_insert_area(&pva->map->areas, pva);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t pv_maps_size(struct list *pvms)
|
||||
{
|
||||
struct pv_map *pvm;
|
||||
uint32_t pe_count = 0;
|
||||
|
||||
list_iterate_items(pvm, pvms)
|
||||
pe_count += pvm->pe_count;
|
||||
|
||||
return pe_count;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ struct pv_area {
|
||||
struct pv_map {
|
||||
struct physical_volume *pv;
|
||||
struct list areas; /* struct pv_areas */
|
||||
uint32_t pe_count; /* Total number of PEs */
|
||||
|
||||
struct list list;
|
||||
};
|
||||
@@ -49,4 +50,6 @@ struct list *create_pv_maps(struct dm_pool *mem, struct volume_group *vg,
|
||||
|
||||
void consume_pv_area(struct pv_area *area, uint32_t to_go);
|
||||
|
||||
uint32_t pv_maps_size(struct list *pvms);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -76,7 +76,7 @@ struct segtype_handler {
|
||||
struct lv_segment *seg, char *params,
|
||||
uint64_t *total_numerator,
|
||||
uint64_t *total_denominator, float *percent);
|
||||
int (*target_present) (void);
|
||||
int (*target_present) (const struct lv_segment *seg);
|
||||
int (*modules_needed) (struct dm_pool *mem,
|
||||
const struct lv_segment *seg,
|
||||
struct list *modules);
|
||||
|
||||
@@ -336,7 +336,7 @@ static int _mirrored_add_target_line(struct dev_manager *dm, struct dm_pool *mem
|
||||
return add_areas_line(dm, seg, node, start_area, area_count);
|
||||
}
|
||||
|
||||
static int _mirrored_target_present(void)
|
||||
static int _mirrored_target_present(const struct lv_segment *seg __attribute((unused)))
|
||||
{
|
||||
static int _mirrored_checked = 0;
|
||||
static int _mirrored_present = 0;
|
||||
|
||||
@@ -244,3 +244,61 @@ void sync_dir(const char *file)
|
||||
out:
|
||||
dm_free(dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to obtain fcntl lock on a file, if necessary creating file first
|
||||
* or waiting.
|
||||
* Returns file descriptor on success, else -1.
|
||||
* mode is F_WRLCK or F_RDLCK
|
||||
*/
|
||||
int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only)
|
||||
{
|
||||
int lockfd;
|
||||
struct flock lock = {
|
||||
.l_type = lock_type,
|
||||
.l_whence = 0,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
|
||||
log_very_verbose("Locking %s (%s, %hd)", file,
|
||||
(lock_type == F_WRLCK) ? "F_WRLCK" : "F_RDLCK",
|
||||
lock_type);
|
||||
if ((lockfd = open(file, O_RDWR | O_CREAT, 0777)) < 0) {
|
||||
/* EACCES has been reported on NFS */
|
||||
if (warn_if_read_only || (errno != EROFS && errno != EACCES))
|
||||
log_sys_error("open", file);
|
||||
else
|
||||
stack;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(lockfd, F_SETLKW, &lock)) {
|
||||
log_sys_error("fcntl", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return lockfd;
|
||||
}
|
||||
|
||||
void fcntl_unlock_file(int lockfd)
|
||||
{
|
||||
struct flock lock = {
|
||||
.l_type = F_UNLCK,
|
||||
.l_whence = 0,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
|
||||
log_very_verbose("Unlocking fd %d", lockfd);
|
||||
|
||||
if (fcntl(lockfd, F_SETLK, &lock) == -1)
|
||||
log_error("fcntl unlock failed on fd %d: %s", lockfd,
|
||||
strerror(errno));
|
||||
|
||||
if (close(lockfd))
|
||||
log_error("lock file close failed on fd %d: %s", lockfd,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
@@ -48,4 +48,8 @@ int create_dir(const char *dir);
|
||||
/* Sync directory changes */
|
||||
void sync_dir(const char *file);
|
||||
|
||||
/* fcntl locking wrappers */
|
||||
int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only);
|
||||
void fcntl_unlock_file(int lockfd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -112,7 +112,7 @@ static int _snap_target_percent(void **target_state __attribute((unused)),
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _snap_target_present(void)
|
||||
static int _snap_target_present(const struct lv_segment *seg __attribute((unused)))
|
||||
{
|
||||
static int _snap_checked = 0;
|
||||
static int _snap_present = 0;
|
||||
|
||||
@@ -174,7 +174,7 @@ static int _striped_add_target_line(struct dev_manager *dm,
|
||||
return add_areas_line(dm, seg, node, 0u, seg->area_count);
|
||||
}
|
||||
|
||||
static int _striped_target_present(void)
|
||||
static int _striped_target_present(const struct lv_segment *seg __attribute((unused)))
|
||||
{
|
||||
static int _striped_checked = 0;
|
||||
static int _striped_present = 0;
|
||||
|
||||
@@ -49,7 +49,7 @@ static int _zero_add_target_line(struct dev_manager *dm __attribute((unused)),
|
||||
return dm_tree_node_add_zero_target(node, len);
|
||||
}
|
||||
|
||||
static int _zero_target_present(void)
|
||||
static int _zero_target_present(const struct lv_segment *seg __attribute((unused)))
|
||||
{
|
||||
static int _zero_checked = 0;
|
||||
static int _zero_present = 0;
|
||||
|
||||
@@ -18,8 +18,8 @@ VPATH = @srcdir@
|
||||
|
||||
MAN5=lvm.conf.5
|
||||
MAN8=lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 \
|
||||
lvmchange.8 \
|
||||
lvmdiskscan.8 lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
|
||||
lvmchange.8 lvmdiskscan.8 lvmdump.8 \
|
||||
lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
|
||||
lvscan.8 pvchange.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
|
||||
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
|
||||
vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
|
||||
|
||||
18
man/clvmd.8
18
man/clvmd.8
@@ -6,6 +6,7 @@ clvmd \- cluster LVM daemon
|
||||
[\-d] [\-h]
|
||||
[\-R]
|
||||
[\-t <timeout>]
|
||||
[\-T <start timeout>]
|
||||
[\-V]
|
||||
.SH DESCRIPTION
|
||||
clvmd is the daemon that distributes LVM metadata updates around a cluster.
|
||||
@@ -23,6 +24,23 @@ be so small that commands with many disk updates to do will fail, so you
|
||||
may need to increase this on systems with very large disk farms.
|
||||
The default is 30 seconds.
|
||||
.TP
|
||||
.I \-T <start timeout>
|
||||
Specifies the timeout for clvmd daemon startup. If the daemon does not report
|
||||
that it has started up within this time then the parent command will exit with
|
||||
status of 5. This does NOT mean that clvmd has not started! What it means is
|
||||
that the startup of clvmd has been delayed for some reason; the most likely
|
||||
cause of this is an inquorate cluster though it could be due to locking
|
||||
latencies on a cluster with large numbers of logical volumes. If you get the
|
||||
return code of 5 it is usually not necessary to restart clvmd - it will start
|
||||
as soon as that blockage has cleared. This flag is to allow startup scripts
|
||||
to exit in a timely fashion even if the cluster is stalled for some reason.
|
||||
<br>
|
||||
The default is 0 (no timeout) and the value is in seconds. Don't set this too
|
||||
small or you will experience spurious errors. 10 or 20 seconds might be
|
||||
sensible.
|
||||
<br>
|
||||
This timeout will be ignored if you start clvmd with the -d switch.
|
||||
.TP
|
||||
.I \-R
|
||||
Tells all the running clvmd in the cluster to reload their device cache and
|
||||
re-read the lvm configuration file. This command should be run whenever the
|
||||
|
||||
@@ -30,6 +30,9 @@ dmsetup \- low level logical volume management
|
||||
.B dmsetup rename
|
||||
.I device_name new_name
|
||||
.br
|
||||
.B dmsetup message
|
||||
.I device_name sector message
|
||||
.br
|
||||
.B dmsetup ls [--target target_type] [--exec command] [--tree [-o options]]
|
||||
.br
|
||||
.B dmsetup info
|
||||
@@ -58,6 +61,9 @@ dmsetup \- low level logical volume management
|
||||
.br
|
||||
.B dmsetup version
|
||||
.br
|
||||
.B dmsetup setgeometry
|
||||
.I device_name cyl head sect start
|
||||
.br
|
||||
|
||||
.B devmap_name
|
||||
.I major minor
|
||||
@@ -167,6 +173,10 @@ ascii, utf, vt100; compact, inverted, notrunc.
|
||||
.br
|
||||
Loads <table> or table_file into the inactive table slot for device_name.
|
||||
If neither is supplied, reads a table from standard input.
|
||||
.IP \fBmessage
|
||||
.I device_name sector message
|
||||
.br
|
||||
Send message to target. If sector not needed use 0.
|
||||
.IP \fBmknodes
|
||||
.I [device_name]
|
||||
.br
|
||||
@@ -205,6 +215,10 @@ Renames a device.
|
||||
Un-suspends a device.
|
||||
If an inactive table has been loaded, it becomes live.
|
||||
Postponed I/O then gets re-queued for processing.
|
||||
.IP \fBsetgeometry
|
||||
.I device_name cyl head sect start
|
||||
.br
|
||||
Sets the device geometry to C/H/S.
|
||||
.IP \fBstatus
|
||||
.I [--target target_type]
|
||||
.I [device_name]
|
||||
|
||||
@@ -7,6 +7,7 @@ lvchange \- change attributes of a logical volume
|
||||
[\-A/\-\-autobackup y/n] [\-a/\-\-available y/n/ey/en/ly/ln]
|
||||
[\-\-alloc AllocationPolicy]
|
||||
[\-C/\-\-contiguous y/n] [\-d/\-\-debug] [\-\-deltag Tag]
|
||||
[\-\-resync]
|
||||
[\-h/\-?/\-\-help]
|
||||
[\-\-ignorelockingfailure]
|
||||
[\-\-monitor {y|n}]
|
||||
@@ -40,6 +41,14 @@ logical volumes. It's only possible to change a non-contiguous
|
||||
logical volume's allocation policy to contiguous, if all of the
|
||||
allocated physical extents are already contiguous.
|
||||
.TP
|
||||
.I \-\-resync
|
||||
Forces the complete resynchronization of a mirror. In normal
|
||||
circumstances you should not need this option because synchronization
|
||||
happens automatically. Data is read from the primary mirror device
|
||||
and copied to the others, so this can take a considerable amount of
|
||||
time - and during this time you are without a complete redundant copy
|
||||
of your data.
|
||||
.TP
|
||||
.I \-\-minor minor
|
||||
Set the minor number.
|
||||
.TP
|
||||
|
||||
@@ -70,10 +70,11 @@ This can also be expressed as a percentage of the total space
|
||||
in the Volume Group with the suffix %VG or of the remaining free space
|
||||
with the suffix %FREE.
|
||||
.TP
|
||||
.I \-L, \-\-size LogicalVolumeSize[kKmMgGtT]
|
||||
.I \-L, \-\-size LogicalVolumeSize[kKmMgGtTpPeE]
|
||||
Gives the size to allocate for the new logical volume.
|
||||
A size suffix of K for kilobytes, M for megabytes,
|
||||
G for gigabytes or T for terabytes is optional.
|
||||
G for gigabytes, T for terabytes, P for petabytes
|
||||
or E for exabytes is optional.
|
||||
.br
|
||||
Default unit is megabytes.
|
||||
.TP
|
||||
|
||||
@@ -30,10 +30,12 @@ in the Volume Group with the suffix %VG or relative to the existing
|
||||
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
|
||||
free space in the Volume Group with the suffix %FREE.
|
||||
.TP
|
||||
.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtT]
|
||||
.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtTpPeE]
|
||||
Extend or set the logical volume size in units in units of megabytes.
|
||||
A size suffix of M for megabytes, G for gigabytes or T for terabytes is
|
||||
optional. With the + sign the value is added to the actual size
|
||||
A size suffix of M for megabytes,
|
||||
G for gigabytes, T for terabytes, P for petabytes
|
||||
or E for exabytes is optional.
|
||||
With the + sign the value is added to the actual size
|
||||
of the logical volume and without it, the value is taken as an absolute one.
|
||||
.TP
|
||||
.I \-i, \-\-stripes Stripes
|
||||
|
||||
50
man/lvmdump.8
Normal file
50
man/lvmdump.8
Normal file
@@ -0,0 +1,50 @@
|
||||
.TH LVMDUMP "8" "" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
lvmdump - create lvm2 information dumps for diagnostic purposes
|
||||
.SH SYNOPSIS
|
||||
\fBlvmdump\fP [options] [-d directory]
|
||||
.SH DESCRIPTION
|
||||
\fBlvmdump\fP is a tool to dump various information concerning LVM2. By default, it creates a tarball suitable for submission along with a problem report.
|
||||
.PP
|
||||
The content of the tarball is as follows:
|
||||
.br
|
||||
- dmsetup info
|
||||
.br
|
||||
- table of currently running processes
|
||||
.br
|
||||
- recent entries from /var/log/messages (containing system messages)
|
||||
.br
|
||||
- complete lvm configuration and cache
|
||||
.br
|
||||
- list of device nodes present under /dev
|
||||
.br
|
||||
- if enabled with -m, metadata dump will be also included
|
||||
.br
|
||||
- if enabled with -a, debug output of vgscan, pvscan and list of all available volume groups, physical volumes and logical volumes will be included
|
||||
.br
|
||||
- if enabled with -c, cluster status info
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-h\fR \(em print help message
|
||||
.TP
|
||||
\fB\-a\fR \(em advanced collection
|
||||
\fBWARNING\fR: if lvm is already hung, then this script may hang as well if \fB\-a\fR is used
|
||||
.TP
|
||||
\fB\-m\fR \(em gather LVM metadata from the PVs
|
||||
This option generates a 1:1 dump of the metadata area from all PVs visible to the system, which can cause the dump to increase in size considerably. However, the metadata dump may represent a valuable diagnostic resource.
|
||||
.TP
|
||||
\fB\-d\fR directory \(em dump into a directory instead of tarball
|
||||
By default, lvmdump will produce a single compressed tarball containing all the information. Using this option, it can be instructed to only produce the raw dump tree, rooted in \fBdirectory\fP.
|
||||
.TP
|
||||
\fB\-c\fR \(em if clvmd is running, gather cluster data as well
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.TP
|
||||
\fBLVM_BINARY\fP
|
||||
The LVM2 binary to use.
|
||||
Defaults to "lvm".
|
||||
Sometimes you might need to set this to "/sbin/lvm.static", for example.
|
||||
.TP
|
||||
\fBDMSETUP_BINARY\fP
|
||||
The dmsetup binary to use.
|
||||
Defaults to "dmsetup".
|
||||
.PP
|
||||
@@ -46,10 +46,11 @@ in the Volume Group with the suffix %VG or relative to the existing
|
||||
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
|
||||
free space in the Volume Group with the suffix %FREE.
|
||||
.TP
|
||||
.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtT]
|
||||
.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtTpPeE]
|
||||
Reduce or set the logical volume size in units of megabyte by default.
|
||||
A size suffix of k for kilobyte, m for megabyte, g for gigabyte or
|
||||
t for terabyte is optional.
|
||||
A size suffix of k for kilobyte, m for megabyte,
|
||||
g for gigabytes, t for terabytes, p for petabytes
|
||||
or e for exabytes is optional.
|
||||
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.
|
||||
|
||||
@@ -12,6 +12,10 @@ lvremove \- remove a logical volume
|
||||
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).
|
||||
.sp
|
||||
If the logical volume is clustered then it must be deactivated on all
|
||||
nodes in the cluster before it can be removed. A single lvchange command
|
||||
issued from one node can do this.
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP(8) for common options.
|
||||
.TP
|
||||
@@ -28,7 +32,8 @@ Remove all logical volumes in volume group vg00:
|
||||
\ \fBlvremove vg00\fP
|
||||
.SH SEE ALSO
|
||||
.BR lvcreate (8),
|
||||
.BR lvdisplay (8),
|
||||
.BR lvdisplay (8),
|
||||
.BR lvchange (8),
|
||||
.BR lvm (8),
|
||||
.BR lvs (8),
|
||||
.BR lvscan (8),
|
||||
|
||||
@@ -34,10 +34,12 @@ in the Volume Group with the suffix %VG or relative to the existing
|
||||
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
|
||||
free space in the Volume Group with the suffix %FREE.
|
||||
.TP
|
||||
.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtT]
|
||||
.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtTpPeE]
|
||||
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
|
||||
A size suffix of M for megabytes,
|
||||
G for gigabytes, T for terabytes, P for petabytes
|
||||
or E for exabytes 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
|
||||
absolute one.
|
||||
.TP
|
||||
|
||||
23
scripts/Makefile.in
Normal file
23
scripts/Makefile.in
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (C) 2006 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install:
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) lvm_dump.sh \
|
||||
$(sbindir)/lvmdump
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# chkconfig: 345 24 76
|
||||
# chkconfig: - 24 76
|
||||
# description: Starts and stops clvmd
|
||||
#
|
||||
#
|
||||
@@ -15,6 +15,7 @@ VGCHANGE="/usr/sbin/vgchange"
|
||||
VGSCAN="/usr/sbin/vgscan"
|
||||
VGDISPLAY="/usr/sbin/vgdisplay"
|
||||
VGS="/usr/sbin/vgs"
|
||||
CLVMDOPTS="-T20"
|
||||
|
||||
[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
|
||||
|
||||
@@ -27,7 +28,7 @@ start()
|
||||
if ! pidof clvmd > /dev/null
|
||||
then
|
||||
echo -n "Starting clvmd: "
|
||||
daemon clvmd
|
||||
daemon clvmd $CLVMDOPTS
|
||||
rtrn=$?
|
||||
echo
|
||||
if [ $rtrn -ne 0 ]
|
||||
@@ -73,7 +74,7 @@ stop()
|
||||
done
|
||||
else
|
||||
# Hack to only deactivate clustered volumes
|
||||
clustervgs=`$VGDISPLAY \`$VGS --noheadings -o name\` | awk 'BEGIN {RS="VG Name"} {if (/Clustered/) print $1;}'`
|
||||
clustervgs=`$VGDISPLAY 2> /dev/null | awk 'BEGIN {RS="VG Name"} {if (/Clustered/) print $1;}'`
|
||||
for vg in $clustervgs; do
|
||||
if ! action "Deactivating VG $vg:" $VGCHANGE -anl $vg
|
||||
then
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
# PATH entries to /sbin/init shell script so chroot works without /usr mounted. Remove
|
||||
# mkdir /initrd so we don't cause problems if root filesystem is corrupted. -- Jeff Layton
|
||||
# 15/05/2004 initial support for modules, create lvm.conf from lvm dumpconfig, other cleanups -- Jeff Layton
|
||||
# 14/11/2006 Update handling of ldd output to handle hardcoded library links and virtual dll linux-gate.
|
||||
# Add support for Gentoo-style MAKEDEV. Remove hardcoded BINUTILS paths -- Douglas Mayle
|
||||
#
|
||||
# Copyright Miguel Cabeca, Jeffrey Layton, 2004
|
||||
#
|
||||
@@ -52,7 +54,7 @@ TMPMNT=/tmp/mnt.$$
|
||||
DEVRAM=/tmp/initrd.$$
|
||||
|
||||
# set defaults
|
||||
BINFILES=${BINFILES:-"/lib/lvm-200/lvm /bin/bash /bin/busybox /sbin/pivot_root"}
|
||||
BINFILES=${BINFILES:-"`which lvm` `which bash` `which busybox` `which pivot_root`"}
|
||||
BASICDEVICES=${BASICDEVICES:-"std consoleonly fd"}
|
||||
BLOCKDEVICES=${BLOCKDEVICES:-"md hda hdb hdc hdd sda sdb sdc sdd"}
|
||||
MAKEDEV=${MAKEDEV:-"debian"}
|
||||
@@ -269,7 +271,27 @@ done
|
||||
# Figure out which shared libraries we actually need in our initrd
|
||||
echo "$cmd -- finding required shared libraries"
|
||||
verbose "BINFILES: `echo $BINFILES`"
|
||||
LIBFILES=`ldd $BINFILES 2>/dev/null | awk '{if (/=>/) { print $3 }}' | sort -u`
|
||||
|
||||
# We need to strip certain lines from ldd output. This is the full output of an example ldd:
|
||||
#lvmhost~ # ldd /sbin/lvm /bin/bash
|
||||
#/sbin/lvm:
|
||||
# not a dynamic executable
|
||||
#/bin/bash:
|
||||
# linux-gate.so.1 => (0xbfffe000)
|
||||
# libncurses.so.5 => /lib/libncurses.so.5 (0xb7ee3000)
|
||||
# libdl.so.2 => /lib/libdl.so.2 (0xb7edf000)
|
||||
# libc.so.6 => /lib/libc.so.6 (0xb7dc1000)
|
||||
# /lib/ld-linux.so.2 (0xb7f28000)
|
||||
#
|
||||
# 1) Lines with a ":" contain the name of the original binary we're examining, and so are unnecessary.
|
||||
# We need to strip them because they contain "/", and can be confused with links with a hardcoded path.
|
||||
# 2) The linux-gate library is a virtual dll that does not exist on disk, but is instead loaded automatically
|
||||
# into the process space, and can't be copied to the ramdisk
|
||||
#
|
||||
# After these lines have been stripped, we're interested in the lines remaining if they
|
||||
# 1) Contain "=>" because they are pathless links, and the value following the token is the path on the disk
|
||||
# 2) Contain "/" because it's a link with a hardcoded path, and so we're interested in the link itself.
|
||||
LIBFILES=`ldd $BINFILES 2>/dev/null |grep -v -E \(linux-gate\|:\) | awk '{if (/=>/) { print $3 } else if (/\//) { print $1 }}' | sort -u`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "$cmd -- ERROR figuring out needed shared libraries"
|
||||
exit 1
|
||||
@@ -356,6 +378,10 @@ redhat)
|
||||
(cd $TMPMNT/dev; /dev/MAKEDEV $OPT_Q -d $TMPMNT/dev -m 2)
|
||||
RETCODE=$?
|
||||
;;
|
||||
gentoo)
|
||||
(cd $TMPMNT/dev; /usr/sbin/MAKEDEV $OPT_Q $BASICDEVICES $BLOCKDEVICES)
|
||||
RETCODE=$?
|
||||
;;
|
||||
*)
|
||||
echo "$cmd -- ERROR: $MAKEDEV is not a known MAKEDEV style."
|
||||
RETCODE=1
|
||||
|
||||
@@ -1,8 +1,41 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# we use some bash-isms (getopts?)
|
||||
|
||||
# lvm_dump: This script is used to collect pertinent information for
|
||||
# the debugging of lvm issues.
|
||||
#
|
||||
|
||||
# following external commands are used throughout the script
|
||||
# which, echo and test are internal in bash at least
|
||||
MKDIR=mkdir # need -p
|
||||
TAR=tar # need czf
|
||||
RM=rm # need -rf
|
||||
CP=cp
|
||||
TAIL=tail # we need -n
|
||||
LS=ls # need -la
|
||||
PS=ps # need alx
|
||||
SED=sed
|
||||
DD=dd
|
||||
CUT=cut
|
||||
DATE=date
|
||||
BASENAME=basename
|
||||
|
||||
# user may override lvm and dmsetup location by setting LVM_BINARY
|
||||
# and DMSETUP_BINARY respectively
|
||||
LVM=${LVM_BINARY-lvm}
|
||||
DMSETUP=${DMSETUP_BINARY-dmsetup}
|
||||
|
||||
die() {
|
||||
code=$1; shift
|
||||
echo "$@" 1>&2
|
||||
exit $code
|
||||
}
|
||||
|
||||
# which should error out if the binary is not executable, although i
|
||||
# am not sure we can rely on this
|
||||
which $LVM >& /dev/null || die 2 "Fatal: could not find lvm binary '$LVM'"
|
||||
test -x `which $LVM` || die 2 "Fatal: lvm binary '$LVM' not executable"
|
||||
which $DMSETUP >& /dev/null || die 2 "Fatal: could not find dmsetup binary '$DMSETUP'"
|
||||
test -x `which $DMSETUP` || die 2 "Fatal: dmsetup binary '$DMSETUP' not executable"
|
||||
|
||||
function usage {
|
||||
echo "$0 [options]"
|
||||
@@ -10,7 +43,7 @@ function usage {
|
||||
echo " -a advanced collection - warning: if lvm is already hung,"
|
||||
echo " then this script may hang as well if -a is used"
|
||||
echo " -m gather LVM metadata from the PVs"
|
||||
echo " -d dump directory to place data in (default=/tmp/lvm_dump.\$\$)"
|
||||
echo " -d <directory> dump into a directory instead of tarball"
|
||||
echo " -c if running clvmd, gather cluster data as well"
|
||||
echo ""
|
||||
|
||||
@@ -22,9 +55,10 @@ clustered=0
|
||||
metadata=0
|
||||
while getopts :acd:hm opt; do
|
||||
case $opt in
|
||||
s) sysreport=1 ;;
|
||||
a) advanced=1 ;;
|
||||
c) clustered=1 ;;
|
||||
d) lvm_dir=$OPTARG ;;
|
||||
d) userdir=$OPTARG ;;
|
||||
h) usage ;;
|
||||
m) metadata=1 ;;
|
||||
:) echo "$0: $OPTARG requires a value:"; usage ;;
|
||||
@@ -33,86 +67,119 @@ while getopts :acd:hm opt; do
|
||||
esac
|
||||
done
|
||||
|
||||
dir=`mktemp -d -p /tmp lvm_dump.XXXXXX` || exit 2
|
||||
lvm_dir="$dir/lvm_dump"
|
||||
NOW=`$DATE -u +%G%m%d%k%M%S | /usr/bin/tr -d ' '`
|
||||
if test -n "$userdir"; then
|
||||
dir="$userdir"
|
||||
else
|
||||
dirbase="lvmdump-$HOSTNAME-$NOW"
|
||||
dir="$HOME/$dirbase"
|
||||
fi
|
||||
|
||||
test -e $dir && die 3 "Fatal: $dir already exists"
|
||||
$MKDIR -p $dir || die 4 "Fatal: could not create $dir"
|
||||
|
||||
log="$dir/lvmdump.log"
|
||||
|
||||
myecho() {
|
||||
echo "$@"
|
||||
echo "$@" >> $log
|
||||
}
|
||||
|
||||
log() {
|
||||
echo "$@" >> $log
|
||||
eval "$@"
|
||||
}
|
||||
|
||||
echo " "
|
||||
echo "Creating dump directory: $lvm_dir"
|
||||
myecho "Creating dump directory: $dir"
|
||||
echo " "
|
||||
|
||||
mkdir -p $lvm_dir || exit 3
|
||||
|
||||
if (( $advanced )); then
|
||||
echo "Gathering LVM volume info..."
|
||||
myecho "Gathering LVM volume info..."
|
||||
|
||||
echo " vgscan..."
|
||||
vgscan -vvvv > $lvm_dir/vgscan 2>&1
|
||||
myecho " vgscan..."
|
||||
log "$LVM vgscan -vvvv > $dir/vgscan 2>&1"
|
||||
|
||||
echo " pvscan..."
|
||||
pvscan -v >> $lvm_dir/pvscan 2>/dev/null
|
||||
myecho " pvscan..."
|
||||
log "$LVM pvscan -v >> $dir/pvscan 2>> $log"
|
||||
|
||||
echo " lvs..."
|
||||
lvs -a -o +devices >> $lvm_dir/lvs 2>/dev/null
|
||||
myecho " lvs..."
|
||||
log "$LVM lvs -a -o +devices >> $dir/lvs 2>> $log"
|
||||
|
||||
echo " pvs..."
|
||||
pvs -a -v > $lvm_dir/pvs 2>/dev/null
|
||||
myecho " pvs..."
|
||||
log "$LVM pvs -a -v > $dir/pvs 2>> $log"
|
||||
|
||||
echo " vgs..."
|
||||
vgs -v > $lvm_dir/vgs 2>/dev/null
|
||||
log "$LVM vgs -v > $dir/vgs 2>> $log"
|
||||
fi
|
||||
|
||||
if (( $clustered )); then
|
||||
echo "Gathering cluster info..."
|
||||
echo "STATUS: " > $lvm_dir/cluster_info
|
||||
echo "----------------------------------" >> $lvm_dir/cluster_info
|
||||
cman_tool status >> $lvm_dir/cluster_info
|
||||
echo " " >> $lvm_dir/lvm_info
|
||||
myecho "Gathering cluster info..."
|
||||
echo "STATUS: " > $dir/cluster_info
|
||||
echo "----------------------------------" >> $dir/cluster_info
|
||||
log "cman_tool status >> $dir/cluster_info 2>> $log"
|
||||
echo " " >> $dir/lvm_info
|
||||
|
||||
echo "SERVICES: " >> $lvm_dir/cluster_info
|
||||
echo "----------------------------------" >> $lvm_dir/cluster_info
|
||||
cman_tool services >> $lvm_dir/cluster_info
|
||||
echo " " >> $lvm_dir/lvm_info
|
||||
echo "SERVICES: " >> $dir/cluster_info
|
||||
echo "----------------------------------" >> $dir/cluster_info
|
||||
log "cman_tool services >> $dir/cluster_info 2>> $log"
|
||||
echo " " >> $dir/lvm_info
|
||||
fi
|
||||
|
||||
echo "Gathering LVM & device-mapper version info..."
|
||||
echo "LVM VERSION:" > $lvm_dir/versions
|
||||
lvs --version >> $lvm_dir/versions
|
||||
echo "DEVICE MAPPER VERSION:" >> $lvm_dir/versions
|
||||
dmsetup --version >> $lvm_dir/versions
|
||||
myecho "Gathering LVM & device-mapper version info..."
|
||||
echo "LVM VERSION:" > $dir/versions
|
||||
$LVM lvs --version >> $dir/versions 2>> $log
|
||||
echo "DEVICE MAPPER VERSION:" >> $dir/versions
|
||||
$DMSETUP --version >> $dir/versions 2>> $log
|
||||
|
||||
echo "Gathering dmsetup info..."
|
||||
dmsetup info -c > $lvm_dir/dmsetup_info
|
||||
dmsetup table > $lvm_dir/dmsetup_table
|
||||
dmsetup status > $lvm_dir/dmsetup_status
|
||||
myecho "Gathering dmsetup info..."
|
||||
log "$DMSETUP info -c > $dir/dmsetup_info 2>> $log"
|
||||
log "$DMSETUP table > $dir/dmsetup_table 2>> $log"
|
||||
log "$DMSETUP status > $dir/dmsetup_status 2>> $log"
|
||||
|
||||
echo "Gathering process info..."
|
||||
ps alx > $lvm_dir/ps_info
|
||||
myecho "Gathering process info..."
|
||||
log "$PS alx > $dir/ps_info 2>> $log"
|
||||
|
||||
echo "Gathering console messages..."
|
||||
tail -n 75 /var/log/messages > $lvm_dir/messages
|
||||
myecho "Gathering console messages..."
|
||||
log "$TAIL -n 75 /var/log/messages > $dir/messages 2>> $log"
|
||||
|
||||
echo "Gathering /etc/lvm info..."
|
||||
cp -a /etc/lvm $lvm_dir/lvm
|
||||
myecho "Gathering /etc/lvm info..."
|
||||
log "$CP -a /etc/lvm $dir/lvm 2>> $log"
|
||||
|
||||
echo "Gathering /dev listing..."
|
||||
ls -la /dev > $lvm_dir/dev_listing
|
||||
myecho "Gathering /dev listing..."
|
||||
log "$LS -la /dev > $dir/dev_listing 2>> $log"
|
||||
|
||||
if (( $metadata )); then
|
||||
echo "Gathering LVM metadata from Physical Volumes..."
|
||||
myecho "Gathering LVM metadata from Physical Volumes..."
|
||||
|
||||
mkdir -p $lvm_dir/metadata
|
||||
log "$MKDIR -p $dir/metadata"
|
||||
|
||||
for pv in `pvs --noheadings -o name`
|
||||
pvs="$($LVM pvs --separator , --noheadings --units s --nosuffix -o \
|
||||
name,pe_start 2>> $log | $SED -e 's/^ *//')"
|
||||
for line in "$pvs"
|
||||
do
|
||||
echo " $pv"
|
||||
name=`basename $pv`
|
||||
dd if=$pv of=$lvm_dir/metadata/$name bs=512 count=`pvs --noheadings --nosuffix --units s -o pe_start $pv | tr -d \ `
|
||||
done 2>/dev/null
|
||||
test -z "$line" && continue
|
||||
pv="$(echo $line | $CUT -d, -f1)"
|
||||
pe_start="$(echo $line | $CUT -d, -f2)"
|
||||
name="$($BASENAME $pv)"
|
||||
myecho " $pv"
|
||||
log "$DD if=$pv of=$dir/metadata/$name bs=512 count=$pe_start 2>> $log"
|
||||
done
|
||||
fi
|
||||
|
||||
lvm_dump=$lvm_dir.tgz
|
||||
echo "Creating tarball $lvm_dump..."
|
||||
tar czf $lvm_dump $lvm_dir 2>/dev/null
|
||||
if test -z "$userdir"; then
|
||||
lvm_dump="$dirbase.tgz"
|
||||
myecho "Creating report tarball in $HOME/$lvm_dump..."
|
||||
cd $HOME
|
||||
$TAR czf $lvm_dump $dirbase 2>/dev/null
|
||||
$RM -rf $dir
|
||||
fi
|
||||
|
||||
if test "$UID" != "0" && test "$EUID" != "0"; then
|
||||
myecho
|
||||
myecho "WARNING! Running as non-privileged user, dump is likely incomplete!"
|
||||
myecho
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
@@ -82,7 +82,8 @@ LVMLIBS = -llvm
|
||||
|
||||
CLEAN_TARGETS = liblvm2cmd.so liblvm2cmd.a liblvm2cmd-static.a lvm lvm.o \
|
||||
lvm2cmd.o lvm2cmd-static.o lvm2cmdlib.o lvm.static \
|
||||
lvm.cflow lvm.xref lvm.tree lvm.rxref lvm.rtree
|
||||
lvm.cflow lvm.xref lvm.tree lvm.rxref lvm.rtree \
|
||||
lvmcmdlib.o lvm-static.o
|
||||
|
||||
ifeq ("@CMDLIB@", "yes")
|
||||
TARGETS += liblvm2cmd.so
|
||||
|
||||
@@ -46,6 +46,7 @@ arg(alloc_ARG, '\0', "alloc", alloc_arg)
|
||||
arg(separator_ARG, '\0', "separator", string_arg)
|
||||
arg(mirrorsonly_ARG, '\0', "mirrorsonly", NULL)
|
||||
arg(nosync_ARG, '\0', "nosync", NULL)
|
||||
arg(resync_ARG, '\0', "resync", NULL)
|
||||
arg(corelog_ARG, '\0', "corelog", NULL)
|
||||
arg(monitor_ARG, '\0', "monitor", yes_no_arg)
|
||||
arg(config_ARG, '\0', "config", string_arg)
|
||||
|
||||
@@ -19,7 +19,7 @@ xx(e2fsadm,
|
||||
"e2fsadm "
|
||||
"[-d|--debug] " "[-h|--help] " "[-n|--nofsck]" "\n"
|
||||
"\t{[-l|--extents] [+|-]LogicalExtentsNumber |" "\n"
|
||||
"\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtT]}" "\n"
|
||||
"\t [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}" "\n"
|
||||
"\t[-t|--test] " "\n"
|
||||
"\t[-v|--verbose] " "\n"
|
||||
"\t[--version] " "\n"
|
||||
@@ -69,15 +69,17 @@ xx(lvchange,
|
||||
"\t[-p|--permission r|rw]\n"
|
||||
"\t[-r|--readahead ReadAheadSectors]\n"
|
||||
"\t[--refresh]\n"
|
||||
"\t[--resync]\n"
|
||||
"\t[-t|--test]\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[-y|--yes]\n"
|
||||
"\t[--version]" "\n"
|
||||
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
|
||||
|
||||
alloc_ARG, autobackup_ARG, available_ARG, contiguous_ARG, force_ARG,
|
||||
ignorelockingfailure_ARG, major_ARG, minor_ARG, monitor_ARG,
|
||||
partial_ARG, permission_ARG, persistent_ARG, readahead_ARG,
|
||||
refresh_ARG, addtag_ARG, deltag_ARG, test_ARG)
|
||||
partial_ARG, permission_ARG, persistent_ARG, readahead_ARG, resync_ARG,
|
||||
refresh_ARG, addtag_ARG, deltag_ARG, test_ARG, yes_ARG)
|
||||
|
||||
xx(lvconvert,
|
||||
"Change logical volume layout",
|
||||
@@ -115,7 +117,7 @@ xx(lvcreate,
|
||||
"\t[-h|-?|--help]\n"
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents LogicalExtentsNumber |\n"
|
||||
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
|
||||
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
|
||||
"\t[-m|--mirrors Mirrors [--nosync] [--corelog]]\n"
|
||||
"\t[-n|--name LogicalVolumeName]\n"
|
||||
@@ -139,7 +141,7 @@ xx(lvcreate,
|
||||
"\t[-h|-?|--help]\n"
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
|
||||
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t -L|--size LogicalVolumeSize[kKmMgGtTpPeE]}\n"
|
||||
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
|
||||
"\t[-n|--name LogicalVolumeName]\n"
|
||||
"\t[-p|--permission {r|rw}]\n"
|
||||
@@ -204,7 +206,7 @@ xx(lvextend,
|
||||
"\t[-h|--help]\n"
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents [+]LogicalExtentsNumber[%{VG|FREE}] |\n"
|
||||
"\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t -L|--size [+]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
|
||||
"\t[-m|--mirrors Mirrors]\n"
|
||||
"\t[-n|--nofsck]\n"
|
||||
"\t[-r|--resizefs]\n"
|
||||
@@ -269,11 +271,12 @@ xx(lvreduce,
|
||||
"\t[-f|--force]\n"
|
||||
"\t[-h|--help]\n"
|
||||
"\t{-l|--extents [-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
|
||||
"\t -L|--size [-]LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t -L|--size [-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
|
||||
"\t[-n|--nofsck]\n"
|
||||
"\t[-r|--resizefs]\n"
|
||||
"\t[-t|--test]\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[-y|--yes]\n"
|
||||
"\t[--version]" "\n"
|
||||
"\tLogicalVolume[Path]\n",
|
||||
|
||||
@@ -317,7 +320,7 @@ xx(lvresize,
|
||||
"\t[-h|--help]\n"
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
|
||||
"\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtTpPeE]}\n"
|
||||
"\t[-n|--nofsck]\n"
|
||||
"\t[-r|--resizefs]\n"
|
||||
"\t[-t|--test]\n"
|
||||
@@ -393,7 +396,7 @@ xx(pvresize,
|
||||
"pvresize " "\n"
|
||||
"\t[-d|--debug]" "\n"
|
||||
"\t[-h|-?|--help] " "\n"
|
||||
"\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtT]" "\n"
|
||||
"\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n"
|
||||
"\t[-t|--test] " "\n"
|
||||
"\t[-v|--verbose] " "\n"
|
||||
"\t[--version] " "\n"
|
||||
@@ -411,8 +414,8 @@ xx(pvcreate,
|
||||
"\t[--labelsector sector] " "\n"
|
||||
"\t[-M|--metadatatype 1|2]" "\n"
|
||||
"\t[--metadatacopies #copies]" "\n"
|
||||
"\t[--metadatasize MetadataSize[kKmMgGtT]]" "\n"
|
||||
"\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtT]" "\n"
|
||||
"\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n"
|
||||
"\t[--setphysicalvolumesize PhysicalVolumeSize[kKmMgGtTpPeE]" "\n"
|
||||
"\t[-t|--test] " "\n"
|
||||
"\t[-u|--uuid uuid] " "\n"
|
||||
"\t[-v|--verbose] " "\n"
|
||||
@@ -609,7 +612,7 @@ xx(vgchange,
|
||||
"\t -x|--resizeable {y|n} |" "\n"
|
||||
"\t -l|--logicalvolume MaxLogicalVolumes |" "\n"
|
||||
"\t -p|--maxphysicalvolumes MaxPhysicalVolumes |" "\n"
|
||||
"\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtT] |" "\n"
|
||||
"\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE] |" "\n"
|
||||
"\t --addtag Tag |\n"
|
||||
"\t --deltag Tag}\n"
|
||||
"\t[VolumeGroupName...]\n",
|
||||
@@ -636,7 +639,7 @@ xx(vgconvert,
|
||||
"\t[--labelsector sector] " "\n"
|
||||
"\t[-M|--metadatatype 1|2]" "\n"
|
||||
"\t[--metadatacopies #copies]" "\n"
|
||||
"\t[--metadatasize MetadataSize[kKmMgGtT]]" "\n"
|
||||
"\t[--metadatasize MetadataSize[kKmMgGtTpPeE]]" "\n"
|
||||
"\t[-t|--test] " "\n"
|
||||
"\t[-v|--verbose] " "\n"
|
||||
"\t[--version] " "\n"
|
||||
@@ -657,7 +660,7 @@ xx(vgcreate,
|
||||
"\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
|
||||
"\t[-M|--metadatatype 1|2] " "\n"
|
||||
"\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n"
|
||||
"\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtT]] " "\n"
|
||||
"\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtTpPeE]] " "\n"
|
||||
"\t[-t|--test] " "\n"
|
||||
"\t[-v|--verbose]" "\n"
|
||||
"\t[--version] " "\n"
|
||||
|
||||
@@ -114,6 +114,7 @@ enum {
|
||||
NOOPENCOUNT_ARG,
|
||||
NOTABLE_ARG,
|
||||
OPTIONS_ARG,
|
||||
SHOWKEYS_ARG,
|
||||
TABLE_ARG,
|
||||
TARGET_ARG,
|
||||
TREE_ARG,
|
||||
@@ -211,7 +212,11 @@ static int _parse_file(struct dm_task *dmt, const char *file)
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
#ifndef HAVE_GETLINE
|
||||
dm_free(buffer);
|
||||
#else
|
||||
free(buffer);
|
||||
#endif
|
||||
if (file)
|
||||
fclose(fp);
|
||||
return r;
|
||||
@@ -915,7 +920,7 @@ static int _status(int argc, char **argv, void *data)
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
char *params, *c;
|
||||
int cmd;
|
||||
struct dm_names *names = (struct dm_names *) data;
|
||||
const char *name = NULL;
|
||||
@@ -978,6 +983,17 @@ static int _status(int argc, char **argv, void *data)
|
||||
if (data && !_switches[VERBOSE_ARG])
|
||||
printf("%s: ", name);
|
||||
if (target_type) {
|
||||
|
||||
/* Suppress encryption key */
|
||||
if (!_switches[SHOWKEYS_ARG] &&
|
||||
!strcmp(target_type, "crypt")) {
|
||||
c = params;
|
||||
while (*c && *c != ' ')
|
||||
c++;
|
||||
c++;
|
||||
while (*c && *c != ' ')
|
||||
*c++ = '0';
|
||||
}
|
||||
printf("%" PRIu64 " %" PRIu64 " %s %s",
|
||||
start, length, target_type, params);
|
||||
}
|
||||
@@ -1522,7 +1538,7 @@ static struct command _commands[] = {
|
||||
{"info", "[<device>]", 0, 1, _info},
|
||||
{"deps", "[<device>]", 0, 1, _deps},
|
||||
{"status", "[<device>] [--target <target_type>]", 0, 1, _status},
|
||||
{"table", "[<device>] [--target <target_type>]", 0, 1, _status},
|
||||
{"table", "[<device>] [--target <target_type>] [--showkeys]", 0, 1, _status},
|
||||
{"wait", "<device> [<event_nr>]", 0, 2, _wait},
|
||||
{"mknodes", "[<device>]", 0, 1, _mknodes},
|
||||
{"targets", "", 0, 0, _targets},
|
||||
@@ -1868,6 +1884,7 @@ static int _process_switches(int *argc, char ***argv)
|
||||
{"noopencount", 0, &ind, NOOPENCOUNT_ARG},
|
||||
{"notable", 0, &ind, NOTABLE_ARG},
|
||||
{"options", 1, &ind, OPTIONS_ARG},
|
||||
{"showkeys", 0, &ind, SHOWKEYS_ARG},
|
||||
{"table", 1, &ind, TABLE_ARG},
|
||||
{"target", 1, &ind, TARGET_ARG},
|
||||
{"tree", 0, &ind, TREE_ARG},
|
||||
@@ -1988,6 +2005,8 @@ static int _process_switches(int *argc, char ***argv)
|
||||
_switches[NOLOCKFS_ARG]++;
|
||||
if ((ind == NOOPENCOUNT_ARG))
|
||||
_switches[NOOPENCOUNT_ARG]++;
|
||||
if ((ind == SHOWKEYS_ARG))
|
||||
_switches[SHOWKEYS_ARG]++;
|
||||
if ((ind == TABLE_ARG)) {
|
||||
_switches[TABLE_ARG]++;
|
||||
_table = optarg;
|
||||
|
||||
185
tools/lvchange.c
185
tools/lvchange.c
@@ -127,10 +127,10 @@ static int lvchange_availability(struct cmd_context *cmd,
|
||||
}
|
||||
} else {
|
||||
if (lockingfailed() && (lv->vg->status & CLUSTERED)) {
|
||||
log_verbose("Locking failed: ignoring clustered "
|
||||
log_verbose("Locking failed: ignoring clustered "
|
||||
"logical volume %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
|
||||
log_verbose("Activating logical volume \"%s\" "
|
||||
@@ -175,6 +175,159 @@ static int lvchange_refresh(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvchange_resync(struct cmd_context *cmd,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
int active = 0;
|
||||
struct lvinfo info;
|
||||
struct logical_volume *log_lv;
|
||||
|
||||
if (!(lv->status & MIRRORED)) {
|
||||
log_error("Unable to resync %s because it is not mirrored.",
|
||||
lv->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lv->status & PVMOVE) {
|
||||
log_error("Unable to resync pvmove volume %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lv->status & LOCKED) {
|
||||
log_error("Unable to resync locked volume %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lv_info(cmd, lv, &info, 1)) {
|
||||
if (info.open_count) {
|
||||
log_error("Can't resync open logical volume \"%s\"",
|
||||
lv->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (info.exists) {
|
||||
if (!arg_count(cmd, yes_ARG) &&
|
||||
yes_no_prompt("Do you really want to deactivate "
|
||||
"logical volume %s to resync it? [y/n]: ",
|
||||
lv->name) == 'n') {
|
||||
log_print("Logical volume \"%s\" not resynced",
|
||||
lv->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
active = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((lv->vg->status & CLUSTERED) && !activate_lv_excl(cmd, lv)) {
|
||||
log_error("Can't get exclusive access to clustered volume %s",
|
||||
lv->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Unable to deactivate %s for resync", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_lv = first_seg(lv)->log_lv;
|
||||
|
||||
log_very_verbose("Starting resync of %s%s%s mirror \"%s\"",
|
||||
(active) ? "active " : "",
|
||||
(lv->vg->status & CLUSTERED) ? "clustered " : "",
|
||||
(log_lv) ? "disk-logged" : "core-logged",
|
||||
lv->name);
|
||||
|
||||
/*
|
||||
* If this mirror has a core log (i.e. !log_lv),
|
||||
* then simply deactivating/activating will cause
|
||||
* it to reset the sync status. We only need to
|
||||
* worry about persistent logs.
|
||||
*/
|
||||
if (!log_lv && !(lv->status & MIRROR_NOTSYNCED)) {
|
||||
if (active && !activate_lv(cmd, lv)) {
|
||||
log_error("Failed to reactivate %s to resynchronize "
|
||||
"mirror", lv->name);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
lv->status &= ~MIRROR_NOTSYNCED;
|
||||
|
||||
if (log_lv) {
|
||||
/* Separate mirror log so we can clear it */
|
||||
first_seg(lv)->log_lv = NULL;
|
||||
log_lv->status &= ~MIRROR_LOG;
|
||||
log_lv->status |= VISIBLE_LV;
|
||||
|
||||
if (!vg_write(lv->vg)) {
|
||||
log_error("Failed to write intermediate VG metadata.");
|
||||
if (active) {
|
||||
first_seg(lv)->log_lv = log_lv;
|
||||
log_lv->status |= MIRROR_LOG;
|
||||
log_lv->status &= ~VISIBLE_LV;
|
||||
if (!activate_lv(cmd, lv))
|
||||
stack;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
backup(lv->vg);
|
||||
|
||||
if (!vg_commit(lv->vg)) {
|
||||
log_error("Failed to commit intermediate VG metadata.");
|
||||
if (active) {
|
||||
first_seg(lv)->log_lv = log_lv;
|
||||
log_lv->status |= MIRROR_LOG;
|
||||
log_lv->status &= ~VISIBLE_LV;
|
||||
if (!activate_lv(cmd, lv))
|
||||
stack;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!activate_lv(cmd, log_lv)) {
|
||||
log_error("Unable to activate %s for mirror log resync",
|
||||
log_lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Clearing log device %s", log_lv->name);
|
||||
if (!set_lv(cmd, log_lv, log_lv->size, 0)) {
|
||||
log_error("Unable to reset sync status for %s", lv->name);
|
||||
if (!deactivate_lv(cmd, log_lv))
|
||||
log_error("Failed to deactivate log LV after "
|
||||
"wiping failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!deactivate_lv(cmd, log_lv)) {
|
||||
log_error("Unable to deactivate log LV %s after wiping "
|
||||
"for resync", log_lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Put mirror log back in place */
|
||||
first_seg(lv)->log_lv = log_lv;
|
||||
log_lv->status |= MIRROR_LOG;
|
||||
log_lv->status &= ~VISIBLE_LV;
|
||||
}
|
||||
|
||||
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
|
||||
if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
|
||||
log_error("Failed to update metadata on disk.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (active && !activate_lv(cmd, lv)) {
|
||||
log_error("Failed to reactivate %s after resync", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvchange_alloc(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
{
|
||||
int want_contiguous = 0;
|
||||
@@ -294,16 +447,15 @@ static int lvchange_persistent(struct cmd_context *cmd,
|
||||
log_error("Major number must be specified with -My");
|
||||
return 0;
|
||||
}
|
||||
if (lv_info(cmd, lv, &info, 0) && info.exists &&
|
||||
!arg_count(cmd, force_ARG)) {
|
||||
if (yes_no_prompt("Logical volume %s will be "
|
||||
"deactivated temporarily. "
|
||||
"Continue? [y/n]: ", lv->name) == 'n') {
|
||||
log_print("%s device number not changed.",
|
||||
lv->name);
|
||||
return 0;
|
||||
}
|
||||
if (lv_info(cmd, lv, &info, 0) && info.exists)
|
||||
active = 1;
|
||||
if (active && !arg_count(cmd, force_ARG) &&
|
||||
yes_no_prompt("Logical volume %s will be "
|
||||
"deactivated temporarily. "
|
||||
"Continue? [y/n]: ", lv->name) == 'n') {
|
||||
log_print("%s device number not changed.",
|
||||
lv->name);
|
||||
return 0;
|
||||
}
|
||||
log_verbose("Ensuring %s is inactive.", lv->name);
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
@@ -496,6 +648,10 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (doit)
|
||||
log_print("Logical volume \"%s\" changed", lv->name);
|
||||
|
||||
if (arg_count(cmd, resync_ARG))
|
||||
if (!lvchange_resync(cmd, lv))
|
||||
return ECMD_FAILED;
|
||||
|
||||
/* availability change */
|
||||
if (arg_count(cmd, available_ARG)) {
|
||||
if (!lvchange_availability(cmd, lv))
|
||||
@@ -523,9 +679,10 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
&& !arg_count(cmd, minor_ARG) && !arg_count(cmd, major_ARG)
|
||||
&& !arg_count(cmd, persistent_ARG) && !arg_count(cmd, addtag_ARG)
|
||||
&& !arg_count(cmd, deltag_ARG) && !arg_count(cmd, refresh_ARG)
|
||||
&& !arg_count(cmd, alloc_ARG) && !arg_count(cmd, monitor_ARG)) {
|
||||
&& !arg_count(cmd, alloc_ARG) && !arg_count(cmd, monitor_ARG)
|
||||
&& !arg_count(cmd, resync_ARG)) {
|
||||
log_error("Need 1 or more of -a, -C, -j, -m, -M, -p, -r, "
|
||||
"--refresh, --alloc, --addtag, --deltag "
|
||||
"--resync, --refresh, --alloc, --addtag, --deltag "
|
||||
"or --monitor");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
if (activation() && lp->segtype->ops->target_present &&
|
||||
!lp->segtype->ops->target_present()) {
|
||||
!lp->segtype->ops->target_present(NULL)) {
|
||||
log_error("%s: Required device-mapper target(s) not "
|
||||
"detected in your kernel", lp->segtype->name);
|
||||
return 0;
|
||||
@@ -281,15 +281,8 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
if (lp->mirrors == existing_mirrors) {
|
||||
if (!seg->log_lv && !arg_count(cmd, corelog_ARG)) {
|
||||
/* No disk log present, add one. */
|
||||
/* FIXME: Why doesn't this work? Without
|
||||
it, we will probably put the log on the
|
||||
same device as a mirror leg.
|
||||
if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
parallel_areas = NULL;
|
||||
if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv)))
|
||||
return_0;
|
||||
if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) {
|
||||
log_error("Unable to determine mirror sync status.");
|
||||
return 0;
|
||||
@@ -297,7 +290,7 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
|
||||
segtype = get_segtype_from_string(cmd, "striped");
|
||||
|
||||
if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1,
|
||||
if (!(ah = allocate_extents(lv->vg, NULL, segtype, 0,
|
||||
0, 1, 0,
|
||||
NULL, 0, 0, lp->pvh,
|
||||
lp->alloc,
|
||||
@@ -455,7 +448,7 @@ static int lvconvert_snapshot(struct cmd_context *cmd,
|
||||
|
||||
if (!lp->zero)
|
||||
log_error("WARNING: \"%s\" not zeroed", lv->name);
|
||||
else if (!set_lv(cmd, lv, 0)) {
|
||||
else if (!set_lv(cmd, lv, 0, 0)) {
|
||||
log_error("Aborting. Failed to wipe snapshot "
|
||||
"exception store.");
|
||||
return 0;
|
||||
|
||||
@@ -386,7 +386,7 @@ static int _lvcreate_params(struct lvcreate_params *lp, struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
if (activation() && lp->segtype->ops->target_present &&
|
||||
!lp->segtype->ops->target_present()) {
|
||||
!lp->segtype->ops->target_present(NULL)) {
|
||||
log_error("%s: Required device-mapper target(s) not "
|
||||
"detected in your kernel", lp->segtype->name);
|
||||
return 0;
|
||||
@@ -556,7 +556,16 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
display_size(cmd, tmp_size));
|
||||
}
|
||||
|
||||
lp->extents = tmp_size / vg->extent_size;
|
||||
if (tmp_size > (uint64_t) UINT32_MAX * vg->extent_size) {
|
||||
log_error("Volume too large (%s) for extent size %s. "
|
||||
"Upper limit is %s.",
|
||||
display_size(cmd, tmp_size),
|
||||
display_size(cmd, vg->extent_size),
|
||||
display_size(cmd, (uint64_t) UINT32_MAX *
|
||||
vg->extent_size));
|
||||
return 0;
|
||||
}
|
||||
lp->extents = (uint64_t) tmp_size / vg->extent_size;
|
||||
}
|
||||
|
||||
switch(lp->percent) {
|
||||
@@ -618,8 +627,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
}
|
||||
|
||||
if (!lp->extents) {
|
||||
log_error("Unable to create logical volume %s with no extents",
|
||||
lp->lv_name);
|
||||
log_error("Unable to create new logical volume with no extents");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -761,18 +769,19 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
if (lp->snapshot)
|
||||
/* FIXME Remove the failed lv we just added */
|
||||
if (lp->snapshot) {
|
||||
if (!activate_lv_excl(cmd, lv)) {
|
||||
log_error("Aborting. Failed to activate snapshot "
|
||||
"exception store. Remove new LV and retry.");
|
||||
else
|
||||
log_error("Failed to activate new LV.");
|
||||
return 0;
|
||||
}
|
||||
} else if (!activate_lv(cmd, lv)) {
|
||||
log_error("Failed to activate new LV.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((lp->zero || lp->snapshot) && activation()) {
|
||||
if (!set_lv(cmd, lv, 0) && lp->snapshot) {
|
||||
if (!set_lv(cmd, lv, 0, 0) && lp->snapshot) {
|
||||
/* FIXME Remove the failed lv we just added */
|
||||
log_error("Aborting. Failed to wipe snapshot "
|
||||
"exception store. Remove new LV and retry.");
|
||||
@@ -787,10 +796,8 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
/* Reset permission after zeroing */
|
||||
if (!(lp->permission & LVM_WRITE))
|
||||
lv->status &= ~LVM_WRITE;
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_err("Couldn't deactivate new snapshot.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cow LV remains active and becomes snapshot LV */
|
||||
|
||||
if (!vg_add_snapshot(vg->fid, NULL, org, lv, NULL,
|
||||
org->le_count, lp->chunk_size)) {
|
||||
|
||||
@@ -186,7 +186,7 @@ static int _size_arg(struct cmd_context *cmd __attribute((unused)), struct arg *
|
||||
{
|
||||
char *ptr;
|
||||
int i;
|
||||
static const char *suffixes = "kmgt";
|
||||
static const char *suffixes = "kmgtpe";
|
||||
char *val;
|
||||
double v;
|
||||
|
||||
@@ -712,10 +712,8 @@ static int _get_settings(struct cmd_context *cmd)
|
||||
cmd->default_settings.activation);
|
||||
}
|
||||
|
||||
if (arg_count(cmd, autobackup_ARG)) {
|
||||
cmd->current_settings.archive = 1;
|
||||
cmd->current_settings.backup = 1;
|
||||
}
|
||||
cmd->current_settings.archive = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.archive);
|
||||
cmd->current_settings.backup = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.backup);
|
||||
|
||||
if (arg_count(cmd, partial_ARG)) {
|
||||
init_partial(1);
|
||||
|
||||
@@ -75,6 +75,16 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (!archive(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
/* If the VG is clustered then make sure no-one else is using the LV
|
||||
we are about to remove */
|
||||
if (vg->status & CLUSTERED) {
|
||||
if (!activate_lv_excl(cmd, lv)) {
|
||||
log_error("Can't get exclusive access to volume \"%s\"",
|
||||
lv->name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME Snapshot commit out of sequence if it fails after here? */
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Unable to deactivate logical volume \"%s\"",
|
||||
|
||||
@@ -29,7 +29,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
const char *pv_name = dev_name(pv->dev);
|
||||
const char *tag = NULL;
|
||||
const char *orig_vg_name;
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
int consistent = 1;
|
||||
int allocatable = 0;
|
||||
|
||||
@@ -19,10 +19,32 @@ static int _pvdisplay_single(struct cmd_context *cmd,
|
||||
struct volume_group *vg __attribute((unused)),
|
||||
struct physical_volume *pv, void *handle)
|
||||
{
|
||||
int consistent = 0;
|
||||
int ret = ECMD_PROCESSED;
|
||||
uint64_t size;
|
||||
|
||||
const char *pv_name = dev_name(pv->dev);
|
||||
|
||||
if (pv->vg_name) {
|
||||
if (!lock_vol(cmd, pv->vg_name, LCK_VG_READ)) {
|
||||
log_error("Can't lock %s: skipping", pv->vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg = vg_read(cmd, pv->vg_name, (char *)&pv->vgid, &consistent))) {
|
||||
log_error("Can't read %s: skipping", pv->vg_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
|
||||
!lockingfailed()) {
|
||||
log_error("Skipping clustered volume group %s",
|
||||
vg->name);
|
||||
ret = ECMD_FAILED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*pv->vg_name)
|
||||
size = pv->size;
|
||||
else
|
||||
@@ -31,7 +53,7 @@ static int _pvdisplay_single(struct cmd_context *cmd,
|
||||
if (arg_count(cmd, short_ARG)) {
|
||||
log_print("Device \"%s\" has a capacity of %s", pv_name,
|
||||
display_size(cmd, size));
|
||||
return ECMD_PROCESSED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pv->status & EXPORTED_VG)
|
||||
@@ -44,15 +66,19 @@ static int _pvdisplay_single(struct cmd_context *cmd,
|
||||
|
||||
if (arg_count(cmd, colon_ARG)) {
|
||||
pvdisplay_colons(pv);
|
||||
return ECMD_PROCESSED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pvdisplay_full(cmd, pv, handle);
|
||||
|
||||
if (!arg_count(cmd, maps_ARG))
|
||||
return ECMD_PROCESSED;
|
||||
goto out;
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
out:
|
||||
if (pv->vg_name)
|
||||
unlock_vg(cmd, pv->vg_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
@@ -38,8 +38,8 @@ static int pvremove_check(struct cmd_context *cmd, const char *name)
|
||||
if (!(pv = pv_read(cmd, name, NULL, NULL, 1))) {
|
||||
if (arg_count(cmd, force_ARG))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
log_error("Physical Volume %s not found", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* orphan ? */
|
||||
@@ -92,9 +92,9 @@ static int pvremove_single(struct cmd_context *cmd, const char *pv_name,
|
||||
}
|
||||
|
||||
if (!dev_test_excl(dev)) {
|
||||
log_error("Can't open %s exclusively. Mounted filesystem?",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
log_error("Can't open %s exclusively - not removing. "
|
||||
"Mounted filesystem?", dev_name(dev));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Wipe existing label(s) */
|
||||
|
||||
@@ -22,7 +22,7 @@ static void _pvscan_display_single(struct cmd_context *cmd,
|
||||
struct physical_volume *pv,
|
||||
void *handle __attribute((unused)))
|
||||
{
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
unsigned vg_name_len = 0;
|
||||
|
||||
char pv_tmp_name[NAME_LEN] = { 0, };
|
||||
|
||||
@@ -844,23 +844,24 @@ char *default_vgname(struct cmd_context *cmd)
|
||||
/*
|
||||
* Process physical extent range specifiers
|
||||
*/
|
||||
static int _add_pe_range(struct dm_pool *mem, struct list *pe_ranges,
|
||||
uint32_t start, uint32_t count)
|
||||
static int _add_pe_range(struct dm_pool *mem, const char *pvname,
|
||||
struct list *pe_ranges, uint32_t start, uint32_t count)
|
||||
{
|
||||
struct pe_range *per;
|
||||
|
||||
log_debug("Adding PE range: start PE %" PRIu32 " length %" PRIu32,
|
||||
start, count);
|
||||
log_debug("Adding PE range: start PE %" PRIu32 " length %" PRIu32
|
||||
" on %s", start, count, pvname);
|
||||
|
||||
/* Ensure no overlap with existing areas */
|
||||
list_iterate_items(per, pe_ranges) {
|
||||
if (((start < per->start) && (start + count - 1 >= per->start))
|
||||
|| ((start >= per->start) &&
|
||||
(per->start + per->count - 1) >= start)) {
|
||||
log_error("Overlapping PE ranges detected (%" PRIu32
|
||||
"-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")",
|
||||
log_error("Overlapping PE ranges specified (%" PRIu32
|
||||
"-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")"
|
||||
" on %s",
|
||||
start, start + count - 1, per->start,
|
||||
per->start + per->count - 1);
|
||||
per->start + per->count - 1, pvname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -878,14 +879,14 @@ static int _add_pe_range(struct dm_pool *mem, struct list *pe_ranges,
|
||||
}
|
||||
|
||||
static int _parse_pes(struct dm_pool *mem, char *c, struct list *pe_ranges,
|
||||
uint32_t size)
|
||||
const char *pvname, uint32_t size)
|
||||
{
|
||||
char *endptr;
|
||||
uint32_t start, end;
|
||||
|
||||
/* Default to whole PV */
|
||||
if (!c) {
|
||||
if (!_add_pe_range(mem, pe_ranges, UINT32_C(0), size)) {
|
||||
if (!_add_pe_range(mem, pvname, pe_ranges, UINT32_C(0), size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -935,7 +936,7 @@ static int _parse_pes(struct dm_pool *mem, char *c, struct list *pe_ranges,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_add_pe_range(mem, pe_ranges, start, end - start + 1)) {
|
||||
if (!_add_pe_range(mem, pvname, pe_ranges, start, end - start + 1)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -949,46 +950,56 @@ static int _parse_pes(struct dm_pool *mem, char *c, struct list *pe_ranges,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
|
||||
static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
|
||||
char *colon, int allocatable_only, struct list *r)
|
||||
{
|
||||
const char *pvname;
|
||||
struct pv_list *new_pvl;
|
||||
struct pv_list *new_pvl = NULL, *pvl2;
|
||||
struct list *pe_ranges;
|
||||
|
||||
pvname = dev_name(pvl->pv->dev);
|
||||
if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
|
||||
log_error("Physical volume %s not allocatable", pvname);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (allocatable_only &&
|
||||
(pvl->pv->pe_count == pvl->pv->pe_alloc_count)) {
|
||||
log_err("No free extents on physical volume \"%s\"", pvname);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(new_pvl = dm_pool_alloc(mem, sizeof(*new_pvl)))) {
|
||||
log_err("Unable to allocate physical volume list.");
|
||||
return;
|
||||
}
|
||||
list_iterate_items(pvl2, r)
|
||||
if (pvl->pv->dev == pvl2->pv->dev) {
|
||||
new_pvl = pvl2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!new_pvl) {
|
||||
if (!(new_pvl = dm_pool_alloc(mem, sizeof(*new_pvl)))) {
|
||||
log_err("Unable to allocate physical volume list.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(new_pvl, pvl, sizeof(*new_pvl));
|
||||
memcpy(new_pvl, pvl, sizeof(*new_pvl));
|
||||
|
||||
if (!(pe_ranges = dm_pool_alloc(mem, sizeof(*pe_ranges)))) {
|
||||
log_error("Allocation of pe_ranges list failed");
|
||||
return;
|
||||
if (!(pe_ranges = dm_pool_alloc(mem, sizeof(*pe_ranges)))) {
|
||||
log_error("Allocation of pe_ranges list failed");
|
||||
return 0;
|
||||
}
|
||||
list_init(pe_ranges);
|
||||
new_pvl->pe_ranges = pe_ranges;
|
||||
list_add(r, &new_pvl->list);
|
||||
}
|
||||
list_init(pe_ranges);
|
||||
|
||||
/* Determine selected physical extents */
|
||||
if (!_parse_pes(mem, colon, pe_ranges, pvl->pv->pe_count)) {
|
||||
if (!_parse_pes(mem, colon, pe_ranges, dev_name(pvl->pv->dev),
|
||||
pvl->pv->pe_count)) {
|
||||
stack;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
new_pvl->pe_ranges = pe_ranges;
|
||||
|
||||
list_add(r, &new_pvl->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int argc,
|
||||
@@ -1021,8 +1032,12 @@ struct list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int ar
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (str_list_match_item(&pvl->pv->tags,
|
||||
tagname)) {
|
||||
_create_pv_entry(mem, pvl, NULL,
|
||||
allocatable_only, r);
|
||||
if (!_create_pv_entry(mem, pvl, NULL,
|
||||
allocatable_only,
|
||||
r)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -1044,7 +1059,10 @@ struct list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int ar
|
||||
"Volume Group \"%s\"", pvname, vg->name);
|
||||
return NULL;
|
||||
}
|
||||
_create_pv_entry(mem, pvl, colon, allocatable_only, r);
|
||||
if (!_create_pv_entry(mem, pvl, colon, allocatable_only, r)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (list_empty(r))
|
||||
@@ -1170,7 +1188,8 @@ int generate_log_name_format(struct volume_group *vg __attribute((unused)),
|
||||
/*
|
||||
* Initialize the LV with 'value'.
|
||||
*/
|
||||
int set_lv(struct cmd_context *cmd, struct logical_volume *lv, int value)
|
||||
int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
uint64_t sectors, int value)
|
||||
{
|
||||
struct device *dev;
|
||||
char *name;
|
||||
@@ -1203,7 +1222,10 @@ int set_lv(struct cmd_context *cmd, struct logical_volume *lv, int value)
|
||||
if (!dev_open_quiet(dev))
|
||||
return 0;
|
||||
|
||||
dev_set(dev, UINT64_C(0), (size_t) 4096, value);
|
||||
dev_set(dev, UINT64_C(0),
|
||||
sectors ? (size_t) sectors << SECTOR_SHIFT : (size_t) 4096,
|
||||
value);
|
||||
dev_flush(dev);
|
||||
dev_close_immediate(dev);
|
||||
|
||||
return 1;
|
||||
@@ -1317,7 +1339,8 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (activation() && !set_lv(cmd, log_lv, in_sync)) {
|
||||
if (activation() && !set_lv(cmd, log_lv, log_lv->size,
|
||||
in_sync ? -1 : 0)) {
|
||||
log_error("Aborting. Failed to wipe mirror log. "
|
||||
"Remove new LV and retry.");
|
||||
goto error;
|
||||
|
||||
@@ -101,6 +101,7 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
|
||||
const char *lv_name,
|
||||
int in_sync);
|
||||
|
||||
int set_lv(struct cmd_context *cmd, struct logical_volume *lv, int value);
|
||||
int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
uint64_t sectors, int value);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -176,7 +176,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
|
||||
/* Fix up LVIDs */
|
||||
list_iterate_items(lvl1, &vg_to->lvs) {
|
||||
union lvid *lvid1 = &lvl1->lv->lvid;
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
list_iterate_items(lvl2, &vg_from->lvs) {
|
||||
union lvid *lvid2 = &lvl2->lv->lvid;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
static int _remove_pv(struct volume_group *vg, struct pv_list *pvl)
|
||||
{
|
||||
char uuid[64];
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (vg->pv_count == 1) {
|
||||
log_error("Volume Groups must always contain at least one PV");
|
||||
|
||||
Reference in New Issue
Block a user