mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-21 15:33:18 +03:00
Compare commits
116 Commits
dev-bmr-dm
...
v2_02_129
Author | SHA1 | Date | |
---|---|---|---|
|
a37fd93fbb | ||
|
8740b7cb77 | ||
|
746b1bcf2a | ||
|
34c956afc1 | ||
|
d0ff35c5a6 | ||
|
1307fafe0f | ||
|
9886fd236e | ||
|
a4fdfc098d | ||
|
cbe81ad393 | ||
|
8c09f12943 | ||
|
19ef3e0f31 | ||
|
463f59eca4 | ||
|
e4145ebc47 | ||
|
567189cc76 | ||
|
f4262026b6 | ||
|
82a27a85b5 | ||
|
ba898b9ab6 | ||
|
d827dd8b05 | ||
|
e53758c5f6 | ||
|
1f27c9f6a4 | ||
|
d310e1f907 | ||
|
81d4c4a84c | ||
|
1c811bfcd9 | ||
|
6d9e7d48fb | ||
|
c868609cff | ||
|
e4b9ac46d7 | ||
|
45f3e8bbef | ||
|
1fae121b22 | ||
|
180f92d3dc | ||
|
5476ee8655 | ||
|
3c396cf1e1 | ||
|
1ea1cb6dc9 | ||
|
8821cc416e | ||
|
92a4b5cc3c | ||
|
c0d6056870 | ||
|
23770214a9 | ||
|
386e91addb | ||
|
62a87c84ed | ||
|
ce2e60ab45 | ||
|
9c5a85ce24 | ||
|
c09dad71fb | ||
|
d08427030d | ||
|
7b570840cd | ||
|
c1bd76d6fc | ||
|
a7abade088 | ||
|
abb24370e9 | ||
|
6e1feb0f73 | ||
|
ef7264807f | ||
|
bc39506792 | ||
|
28b4fa3e27 | ||
|
b193809987 | ||
|
a8fd88463e | ||
|
3a3e17d603 | ||
|
40af31729f | ||
|
58f8f29c41 | ||
|
3d08a49790 | ||
|
55a9262bdb | ||
|
ba94d0f144 | ||
|
ae4db9f302 | ||
|
70db1d523d | ||
|
8e229cb7ea | ||
|
13d3eeb2ee | ||
|
dece918bc8 | ||
|
b091c37595 | ||
|
ca70770cfd | ||
|
5243a81c29 | ||
|
12acf852c5 | ||
|
074b5de771 | ||
|
69fa16048a | ||
|
b01e9651b0 | ||
|
8967776713 | ||
|
d1c65d1b28 | ||
|
be1db6b6c1 | ||
|
4227b2ebb4 | ||
|
15e20bb5c0 | ||
|
80bc87e377 | ||
|
77357081c8 | ||
|
4b28383b1c | ||
|
94c56559ca | ||
|
427d0a5e92 | ||
|
623b46a17d | ||
|
a606966029 | ||
|
79ea81b8a8 | ||
|
d4c024c836 | ||
|
b297d78367 | ||
|
4a6d5e2012 | ||
|
9d5cd4ca14 | ||
|
0b487802a0 | ||
|
f3891e90e3 | ||
|
0f3b81bb2e | ||
|
00ed523659 | ||
|
77fae3d852 | ||
|
16ff2d927f | ||
|
fc7a27bc3d | ||
|
666722324f | ||
|
bfb58b7e1c | ||
|
8852b25fc7 | ||
|
4d5b618d52 | ||
|
e6724f0303 | ||
|
37dd26e322 | ||
|
f10ad95c36 | ||
|
9b3dc72506 | ||
|
4534f0fbcf | ||
|
6a93206882 | ||
|
043fb32c4b | ||
|
b3cd5d2945 | ||
|
6b81ac5807 | ||
|
988ca74351 | ||
|
86adb6ca63 | ||
|
b22b7d7ba9 | ||
|
7995eedd35 | ||
|
098528513f | ||
|
829384f46d | ||
|
e96041e18f | ||
|
0f45aa7f31 | ||
|
2cf3336130 |
@@ -1 +1 @@
|
||||
1.02.105-git (2015-08-10)
|
||||
1.02.106-git (2015-08-26)
|
||||
|
22
WHATS_NEW
22
WHATS_NEW
@@ -1,10 +1,22 @@
|
||||
Version 2.02.128 -
|
||||
Version 2.02.129 - 26th August 2015
|
||||
===================================
|
||||
Drop error message when vgdisplay encounters an exported VG. (2.02.27)
|
||||
Fix shared library generation to stop exporting internal functions.(2.02.120)
|
||||
Accept --cachemode with lvconvert.
|
||||
Fix and improve reporting properties of cache-pool.
|
||||
Enable usage of --cachepolicy and --cachesetting with lvconvert.
|
||||
Don't allow to reduce size of thin-pool metadata.
|
||||
Fix debug buffer overflows in cmirrord logging.
|
||||
Add --foreground and --help to cmirrord.
|
||||
|
||||
Version 2.02.128 - 17th August 2015
|
||||
===================================
|
||||
Allocation setting cache_pool_cachemode is replaced by cache_mode.
|
||||
Don't attempt to close config file that couldn't be opened.
|
||||
Check for valid cache mode in validation of cache segment.
|
||||
Enhance internal API cache_set_mode() and cache_set_policy().
|
||||
Enhance toollib's get_cache_params().
|
||||
Runtime detect presence of cache smq policy.
|
||||
Add demo cache-mq and cache-smq profiles.
|
||||
Change internal interface handling cache mode and policy.
|
||||
When no cache policy specified, prefer smq (if available) over mq.
|
||||
Add demo cache-mq and cache-smq profiles.
|
||||
Add cmd profilable allocation/cache_policy,cache_settings,cache_mode.
|
||||
Require cache_check 0.5.4 for use of --clear-needs-check-flag.
|
||||
Fix lvmetad udev rules to not override SYSTEMD_WANTS, add the service instead.
|
||||
|
20
WHATS_NEW_DM
20
WHATS_NEW_DM
@@ -1,6 +1,24 @@
|
||||
Version 1.02.105 -
|
||||
Version 1.02.106 - 26th August 2015
|
||||
===================================
|
||||
Add 'precise' column to statistics reports.
|
||||
Add --precise switch to 'dmstats create' to request nanosecond counters.
|
||||
Add precise argument to dm_stats_create_region().
|
||||
Add support to libdm-stats for precise_timestamps
|
||||
|
||||
Version 1.02.105 - 17th August 2015
|
||||
===================================
|
||||
Fix 'dmstats list -o all' segfault.
|
||||
Separate dmstats statistics fields from region information fields.
|
||||
Add interval and interval_ns fields to dmstats reports.
|
||||
Do not include internal glibc headers in libdm-timestamp.c (1.02.104)
|
||||
Exit immediately if no device is supplied to dmsetup wipe_table.
|
||||
Suppress dmsetup report headings when no data is output. (1.02.104)
|
||||
Adjust dmsetup usage/help output selection to match command invoked.
|
||||
Fix dmsetup -o all to select correct fields in splitname report.
|
||||
Restructure internal dmsetup argument handling across all commands.
|
||||
Add dm_report_is_empty() to indicate there is no data awaiting output.
|
||||
Add more arg validation for dm_tree_node_add_cache_target().
|
||||
Add --alldevices switch to replace use of --force for stats create / delete.
|
||||
|
||||
Version 1.02.104 - 10th August 2015
|
||||
===================================
|
||||
|
1698
conf/example.conf.in
1698
conf/example.conf.in
File diff suppressed because it is too large
Load Diff
@@ -24,34 +24,33 @@ local {
|
||||
|
||||
# Configuration option local/system_id.
|
||||
# Defines the local system ID for lvmlocal mode.
|
||||
# This is used when global/system_id_source is set
|
||||
# to 'lvmlocal' in the main configuration file,
|
||||
# e.g. lvm.conf.
|
||||
# When used, it must be set to a unique value
|
||||
# among all hosts sharing access to the storage,
|
||||
# This is used when global/system_id_source is set to 'lvmlocal' in the
|
||||
# main configuration file, e.g. lvm.conf. When used, it must be set to
|
||||
# a unique value among all hosts sharing access to the storage,
|
||||
# e.g. a host name.
|
||||
# Example:
|
||||
# Set no system ID.
|
||||
#
|
||||
# Example
|
||||
# Set no system ID:
|
||||
# system_id = ""
|
||||
# Example:
|
||||
# Set the system_id to the string 'host1'.
|
||||
# Set the system_id to a specific name:
|
||||
# system_id = "host1"
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# system_id = ""
|
||||
|
||||
# Configuration option local/extra_system_ids.
|
||||
# A list of extra VG system IDs the local host can access.
|
||||
# VGs with the system IDs listed here (in addition
|
||||
# to the host's own system ID) can be fully accessed
|
||||
# by the local host. (These are system IDs that the
|
||||
# host sees in VGs, not system IDs that identify the
|
||||
# local host, which is determined by system_id_source.)
|
||||
# Use this only after consulting 'man lvmsystemid'
|
||||
# to be certain of correct usage and possible dangers.
|
||||
# VGs with the system IDs listed here (in addition to the host's own
|
||||
# system ID) can be fully accessed by the local host. (These are
|
||||
# system IDs that the host sees in VGs, not system IDs that identify
|
||||
# the local host, which is determined by system_id_source.)
|
||||
# Use this only after consulting 'man lvmsystemid' to be certain of
|
||||
# correct usage and possible dangers.
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option local/host_id.
|
||||
# The lvmlockd sanlock host_id.
|
||||
# This must be a unique among all hosts,
|
||||
# and must be between 1 and 2000.
|
||||
# This must be unique among all hosts, and must be between 1 and 2000.
|
||||
# This configuration option has an automatic default value.
|
||||
# host_id = 0
|
||||
}
|
||||
|
46
configure
vendored
46
configure
vendored
@@ -665,6 +665,7 @@ PYTHON_LIBDIRS
|
||||
PYTHON_INCDIRS
|
||||
PYTHON_BINDINGS
|
||||
PTHREAD_LIBS
|
||||
M_LIBS
|
||||
POOL
|
||||
PKGCONFIG
|
||||
OCFDIR
|
||||
@@ -12569,6 +12570,50 @@ if [ \( "$LVM1" = shared -o "$POOL" = shared -o "$CLUSTER" = shared \
|
||||
as_fn_error $? "Features cannot be 'shared' when building statically" "$LINENO" 5
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for log10 in -lm" >&5
|
||||
$as_echo_n "checking for log10 in -lm... " >&6; }
|
||||
if ${ac_cv_lib_m_log10+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lm $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char log10 ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return log10 ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_m_log10=yes
|
||||
else
|
||||
ac_cv_lib_m_log10=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_log10" >&5
|
||||
$as_echo "$ac_cv_lib_m_log10" >&6; }
|
||||
if test "x$ac_cv_lib_m_log10" = xyes; then :
|
||||
M_LIBS="-lm"
|
||||
else
|
||||
hard_bailout
|
||||
fi
|
||||
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_lock in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_mutex_lock in -lpthread... " >&6; }
|
||||
@@ -14151,6 +14196,7 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
|
@@ -1537,6 +1537,10 @@ if [[ \( "$LVM1" = shared -o "$POOL" = shared -o "$CLUSTER" = shared \
|
||||
AC_MSG_ERROR([Features cannot be 'shared' when building statically])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
AC_CHECK_LIB(m, log10,
|
||||
[M_LIBS="-lm"], hard_bailout)
|
||||
|
||||
################################################################################
|
||||
AC_CHECK_LIB([pthread], [pthread_mutex_lock],
|
||||
[PTHREAD_LIBS="-lpthread"], hard_bailout)
|
||||
@@ -1984,6 +1988,7 @@ AC_SUBST(OCF)
|
||||
AC_SUBST(OCFDIR)
|
||||
AC_SUBST(PKGCONFIG)
|
||||
AC_SUBST(POOL)
|
||||
AC_SUBST(M_LIBS)
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
AC_SUBST(PYTHON)
|
||||
AC_SUBST(PYTHON_BINDINGS)
|
||||
|
@@ -855,12 +855,12 @@ static void main_loop(int cmd_timeout)
|
||||
int quorate = clops->is_quorate();
|
||||
int client_count = 0;
|
||||
int max_fd = 0;
|
||||
struct local_client *lastfd = &local_client_head;
|
||||
struct local_client *nextfd = local_client_head.next;
|
||||
|
||||
/* Wait on the cluster FD and all local sockets/pipes */
|
||||
local_client_head.fd = clops->get_main_cluster_fd();
|
||||
FD_ZERO(&in);
|
||||
struct local_client *lastfd = &local_client_head;
|
||||
struct local_client *nextfd = local_client_head.next;
|
||||
|
||||
for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) {
|
||||
client_count++;
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "link_mon.h"
|
||||
#include "local.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -32,14 +33,49 @@ static void daemonize(void);
|
||||
static void init_all(void);
|
||||
static void cleanup_all(void);
|
||||
|
||||
int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||
static void usage (FILE *dest)
|
||||
{
|
||||
daemonize();
|
||||
fprintf (dest, "Usage: cmirrord [options]\n"
|
||||
" -f, --foreground stay in the foreground, log to the terminal\n"
|
||||
" -h, --help print this help\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int foreground_mode = 0;
|
||||
struct option longopts[] = {
|
||||
{ "foreground", no_argument, NULL, 'f' },
|
||||
{ "help" , no_argument, NULL, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt_long (argc, argv, "fh", longopts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
foreground_mode = 1;
|
||||
break;
|
||||
case 'h':
|
||||
usage (stdout);
|
||||
exit (0);
|
||||
default:
|
||||
usage (stderr);
|
||||
exit (2);
|
||||
}
|
||||
}
|
||||
if (optind < argc) {
|
||||
usage (stderr);
|
||||
exit (2);
|
||||
}
|
||||
|
||||
if (!foreground_mode)
|
||||
daemonize();
|
||||
|
||||
init_all();
|
||||
|
||||
/* Parent can now exit, we're ready to handle requests */
|
||||
kill(getppid(), SIGTERM);
|
||||
if (!foreground_mode)
|
||||
kill(getppid(), SIGTERM);
|
||||
|
||||
LOG_PRINT("Starting cmirrord:");
|
||||
LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
|
||||
@@ -209,6 +245,16 @@ static void daemonize(void)
|
||||
}
|
||||
|
||||
LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_all
|
||||
*
|
||||
* Initialize modules. Exit on failure.
|
||||
*/
|
||||
static void init_all(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
(void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG);
|
||||
if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
|
||||
@@ -227,16 +273,6 @@ static void daemonize(void)
|
||||
signal(SIGUSR2, &sig_handler);
|
||||
sigemptyset(&signal_mask);
|
||||
signal_received = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_all
|
||||
*
|
||||
* Initialize modules. Exit on failure.
|
||||
*/
|
||||
static void init_all(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = init_local()) ||
|
||||
(r = init_cluster())) {
|
||||
|
@@ -104,10 +104,11 @@ static SaVersionT version = { 'B', 1, 1 };
|
||||
#endif
|
||||
|
||||
#define DEBUGGING_HISTORY 100
|
||||
#define DEBUGGING_BUFLEN 128
|
||||
#define LOG_SPRINT(cc, f, arg...) do { \
|
||||
cc->idx++; \
|
||||
cc->idx = cc->idx % DEBUGGING_HISTORY; \
|
||||
sprintf(cc->debugging[cc->idx], f, ## arg); \
|
||||
snprintf(cc->debugging[cc->idx], DEBUGGING_BUFLEN, f, ## arg); \
|
||||
} while (0)
|
||||
|
||||
static int log_resp_rec = 0;
|
||||
@@ -150,7 +151,7 @@ struct clog_cpg {
|
||||
uint32_t checkpoint_requesters[MAX_CHECKPOINT_REQUESTERS];
|
||||
struct checkpoint_data *checkpoint_list;
|
||||
int idx;
|
||||
char debugging[DEBUGGING_HISTORY][128];
|
||||
char debugging[DEBUGGING_HISTORY][DEBUGGING_BUFLEN];
|
||||
};
|
||||
|
||||
static struct dm_list clog_cpg_list;
|
||||
@@ -1294,7 +1295,9 @@ static void cpg_join_callback(struct clog_cpg *match,
|
||||
uint32_t my_pid = (uint32_t)getpid();
|
||||
uint32_t lowest = match->lowest_id;
|
||||
struct clog_request *rq;
|
||||
char dbuf[32] = { 0 };
|
||||
char dbuf[64] = { 0 };
|
||||
char *dbuf_p = dbuf;
|
||||
size_t dbuf_rem = sizeof dbuf;
|
||||
|
||||
/* Assign my_cluster_id */
|
||||
if ((my_cluster_id == 0xDEAD) && (joined->pid == my_pid))
|
||||
@@ -1310,9 +1313,17 @@ static void cpg_join_callback(struct clog_cpg *match,
|
||||
if (joined->nodeid == my_cluster_id)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < member_list_entries - 1; i++)
|
||||
sprintf(dbuf+strlen(dbuf), "%u-", member_list[i].nodeid);
|
||||
sprintf(dbuf+strlen(dbuf), "(%u)", joined->nodeid);
|
||||
for (i = 0; i < member_list_entries - 1; i++) {
|
||||
int written = snprintf(dbuf_p, dbuf_rem, "%u-", member_list[i].nodeid);
|
||||
if (written < 0) continue; /* impossible */
|
||||
if ((unsigned)written >= dbuf_rem) {
|
||||
dbuf_rem = 0;
|
||||
break;
|
||||
}
|
||||
dbuf_rem -= written;
|
||||
dbuf_p += written;
|
||||
}
|
||||
snprintf(dbuf_p, dbuf_rem, "(%u)", joined->nodeid);
|
||||
LOG_COND(log_checkpoint, "[%s] Joining node, %u needs checkpoint [%s]",
|
||||
SHORT_UUID(match->name.value), joined->nodeid, dbuf);
|
||||
|
||||
|
@@ -32,12 +32,13 @@
|
||||
#define LOG_OFFSET 2
|
||||
|
||||
#define RESYNC_HISTORY 50
|
||||
#define RESYNC_BUFLEN 128
|
||||
//static char resync_history[RESYNC_HISTORY][128];
|
||||
//static int idx = 0;
|
||||
#define LOG_SPRINT(_lc, f, arg...) do { \
|
||||
lc->idx++; \
|
||||
lc->idx = lc->idx % RESYNC_HISTORY; \
|
||||
sprintf(lc->resync_history[lc->idx], f, ## arg); \
|
||||
snprintf(lc->resync_history[lc->idx], RESYNC_BUFLEN, f, ## arg); \
|
||||
} while (0)
|
||||
|
||||
struct log_header {
|
||||
@@ -88,7 +89,7 @@ struct log_c {
|
||||
size_t disk_size; /* size of disk_buffer in bytes */
|
||||
void *disk_buffer; /* aligned memory for O_DIRECT */
|
||||
int idx;
|
||||
char resync_history[RESYNC_HISTORY][128];
|
||||
char resync_history[RESYNC_HISTORY][RESYNC_BUFLEN];
|
||||
};
|
||||
|
||||
struct mark_entry {
|
||||
|
@@ -151,13 +151,12 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
|
||||
sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
|
||||
r_name, r_type, mode, sh_count, &ver);
|
||||
|
||||
/* when mode is not un, wait and print each lk line */
|
||||
strcpy(r_name_out, r_name);
|
||||
strcpy(r_type_out, r_type);
|
||||
|
||||
if (strcmp(mode, "un")) {
|
||||
strcpy(r_name_out, r_name);
|
||||
strcpy(r_type_out, r_type);
|
||||
/* when mode is not un, wait and print each lk line */
|
||||
if (strcmp(mode, "un"))
|
||||
return;
|
||||
}
|
||||
|
||||
/* when mode is un, there will be no lk lines, so print now */
|
||||
|
||||
@@ -229,7 +228,7 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
if (strcmp(op, "lock")) {
|
||||
printf("OP %s pid %u (%s)", op, pid, cl_name);
|
||||
printf("OP %s pid %u (%s)\n", op, pid, cl_name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -380,6 +379,7 @@ static int setup_dump_socket(void)
|
||||
|
||||
rv = bind(s, (struct sockaddr *) &dump_addr, dump_addrlen);
|
||||
if (rv < 0) {
|
||||
rv = -errno;
|
||||
if (!close(s))
|
||||
log_error("failed to close dump socket");
|
||||
return rv;
|
||||
@@ -393,6 +393,7 @@ static int do_dump(const char *req_name)
|
||||
daemon_reply reply;
|
||||
int result;
|
||||
int fd, rv = 0;
|
||||
int count = 0;
|
||||
|
||||
fd = setup_dump_socket();
|
||||
if (fd < 0) {
|
||||
@@ -423,13 +424,18 @@ static int do_dump(const char *req_name)
|
||||
|
||||
memset(dump_buf, 0, sizeof(dump_buf));
|
||||
|
||||
rv = recvfrom(fd, dump_buf, dump_len, MSG_WAITALL,
|
||||
retry:
|
||||
rv = recvfrom(fd, dump_buf + count, dump_len - count, MSG_WAITALL,
|
||||
(struct sockaddr *)&dump_addr, &dump_addrlen);
|
||||
if (rv < 0) {
|
||||
log_error("recvfrom error %d %d", rv, errno);
|
||||
rv = -errno;
|
||||
goto out;
|
||||
}
|
||||
count += rv;
|
||||
|
||||
if (count < dump_len)
|
||||
goto retry;
|
||||
|
||||
rv = 0;
|
||||
if ((info && dump) || !strcmp(req_name, "dump"))
|
||||
|
@@ -265,6 +265,10 @@ static int alloc_new_structs; /* used for initializing in setup_structs */
|
||||
static int add_lock_action(struct action *act);
|
||||
static int str_to_lm(const char *str);
|
||||
static int clear_lockspace_inactive(char *name);
|
||||
static int setup_dump_socket(void);
|
||||
static void send_dump_buf(int fd, int dump_len);
|
||||
static int dump_info(int *dump_len);
|
||||
static int dump_log(int *dump_len);
|
||||
|
||||
static int _syslog_name_to_num(const char *name)
|
||||
{
|
||||
@@ -739,6 +743,10 @@ static const char *op_str(int x)
|
||||
return "kill_vg";
|
||||
case LD_OP_DROP_VG:
|
||||
return "drop_vg";
|
||||
case LD_OP_DUMP_LOG:
|
||||
return "dump_log";
|
||||
case LD_OP_DUMP_INFO:
|
||||
return "dump_info";
|
||||
default:
|
||||
return "op_unknown";
|
||||
};
|
||||
@@ -1283,7 +1291,7 @@ static int res_unlock(struct lockspace *ls, struct resource *r,
|
||||
}
|
||||
|
||||
if (act->op != LD_OP_CLOSE)
|
||||
log_error("S %s R %s res_unlock no locks", ls->name, r->name);
|
||||
log_debug("S %s R %s res_unlock no locks", ls->name, r->name);
|
||||
return -ENOENT;
|
||||
|
||||
do_unlock:
|
||||
@@ -3414,6 +3422,8 @@ static void client_send_result(struct client *cl, struct action *act)
|
||||
{
|
||||
response res;
|
||||
char result_flags[128];
|
||||
int dump_len = 0;
|
||||
int dump_fd = -1;
|
||||
|
||||
if (cl->dead) {
|
||||
log_debug("client send %d skip dead", cl->id);
|
||||
@@ -3498,6 +3508,33 @@ static void client_send_result(struct client *cl, struct action *act)
|
||||
"lv_lock_args = %s", lv_args,
|
||||
"result_flags = %s", result_flags[0] ? result_flags : "none",
|
||||
NULL);
|
||||
|
||||
} else if (act->op == LD_OP_DUMP_LOG || act->op == LD_OP_DUMP_INFO) {
|
||||
/*
|
||||
* lvmlockctl creates the unix socket then asks us to write to it.
|
||||
* FIXME: move processing this to a new dedicated query thread to
|
||||
* avoid having a large data dump interfere with normal operation
|
||||
* of the client thread?
|
||||
*/
|
||||
|
||||
dump_fd = setup_dump_socket();
|
||||
if (dump_fd < 0)
|
||||
act->result = dump_fd;
|
||||
else if (act->op == LD_OP_DUMP_LOG)
|
||||
act->result = dump_log(&dump_len);
|
||||
else if (act->op == LD_OP_DUMP_INFO)
|
||||
act->result = dump_info(&dump_len);
|
||||
else
|
||||
act->result = -EINVAL;
|
||||
|
||||
log_debug("send %s[%d.%u] dump result %d dump_len %d",
|
||||
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
|
||||
act->result, dump_len);
|
||||
|
||||
res = daemon_reply_simple("OK",
|
||||
"result = %d", act->result,
|
||||
"dump_len = %d", dump_len,
|
||||
NULL);
|
||||
} else {
|
||||
/*
|
||||
* A normal reply.
|
||||
@@ -3521,6 +3558,12 @@ static void client_send_result(struct client *cl, struct action *act)
|
||||
buffer_destroy(&res.buffer);
|
||||
|
||||
client_resume(cl);
|
||||
|
||||
if (dump_fd >= 0) {
|
||||
/* To avoid deadlock, send data here after the reply. */
|
||||
send_dump_buf(dump_fd, dump_len);
|
||||
close(dump_fd);
|
||||
}
|
||||
}
|
||||
|
||||
/* called from client_thread */
|
||||
@@ -3529,6 +3572,13 @@ static void client_purge(struct client *cl)
|
||||
struct lockspace *ls;
|
||||
struct action *act;
|
||||
|
||||
/*
|
||||
* If the client made no lock requests, there can be
|
||||
* no locks to release for it.
|
||||
*/
|
||||
if (!cl->lock_ops)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&lockspaces_mutex);
|
||||
list_for_each_entry(ls, &lockspaces, list) {
|
||||
if (!(act = alloc_action()))
|
||||
@@ -3887,23 +3937,43 @@ static int setup_dump_socket(void)
|
||||
return s;
|
||||
}
|
||||
|
||||
static int send_dump_buf(int fd, int dump_len)
|
||||
#define MAX_SEND_LEN 65536
|
||||
#define RESEND_DELAY_US 1000
|
||||
#define RESEND_DELAY_US_MAX 500000
|
||||
|
||||
static void send_dump_buf(int fd, int dump_len)
|
||||
{
|
||||
int pos = 0;
|
||||
int ret;
|
||||
int send_len;
|
||||
int delay = 0;
|
||||
|
||||
retry:
|
||||
ret = sendto(fd, dump_buf + pos, dump_len - pos, MSG_DONTWAIT | MSG_NOSIGNAL,
|
||||
if (!dump_len)
|
||||
return;
|
||||
repeat:
|
||||
if (dump_len - pos < MAX_SEND_LEN)
|
||||
send_len = dump_len - pos;
|
||||
else
|
||||
send_len = MAX_SEND_LEN;
|
||||
|
||||
ret = sendto(fd, dump_buf + pos, send_len, MSG_NOSIGNAL | MSG_DONTWAIT,
|
||||
(struct sockaddr *)&dump_addr, dump_addrlen);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
if (ret < 0) {
|
||||
if ((errno == EAGAIN || errno == EINTR) && (delay < RESEND_DELAY_US_MAX)) {
|
||||
usleep(RESEND_DELAY_US);
|
||||
delay += RESEND_DELAY_US;
|
||||
goto repeat;
|
||||
}
|
||||
log_error("send_dump_buf delay %d errno %d", delay, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
pos += ret;
|
||||
|
||||
if (pos < dump_len)
|
||||
goto retry;
|
||||
goto repeat;
|
||||
|
||||
return 0;
|
||||
log_debug("send_dump_buf delay %d total %d", delay, pos);
|
||||
}
|
||||
|
||||
static int print_structs(const char *prefix, int pos, int len)
|
||||
@@ -4186,8 +4256,7 @@ static void client_recv_action(struct client *cl)
|
||||
return;
|
||||
}
|
||||
|
||||
if (op == LD_OP_HELLO || op == LD_OP_QUIT ||
|
||||
op == LD_OP_DUMP_INFO || op == LD_OP_DUMP_LOG) {
|
||||
if (op == LD_OP_HELLO || op == LD_OP_QUIT) {
|
||||
|
||||
/*
|
||||
* FIXME: add the client command name to the hello messages
|
||||
@@ -4208,37 +4277,11 @@ static void client_recv_action(struct client *cl)
|
||||
|
||||
buffer_init(&res.buffer);
|
||||
|
||||
if (op == LD_OP_DUMP_INFO || op == LD_OP_DUMP_LOG) {
|
||||
int dump_len = 0;
|
||||
int fd;
|
||||
|
||||
fd = setup_dump_socket();
|
||||
if (fd < 0)
|
||||
result = fd;
|
||||
else if (op == LD_OP_DUMP_INFO)
|
||||
result = dump_info(&dump_len);
|
||||
else if (op == LD_OP_DUMP_LOG)
|
||||
result = dump_log(&dump_len);
|
||||
else
|
||||
result = -EINVAL;
|
||||
|
||||
res = daemon_reply_simple("OK",
|
||||
"result = %d", result,
|
||||
"dump_len = %d", dump_len,
|
||||
NULL);
|
||||
if (fd >= 0) {
|
||||
send_dump_buf(fd, dump_len);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
} else {
|
||||
res = daemon_reply_simple("OK",
|
||||
res = daemon_reply_simple("OK",
|
||||
"result = %d", result,
|
||||
"protocol = %s", lvmlockd_protocol,
|
||||
"version = %d", lvmlockd_protocol_version,
|
||||
NULL);
|
||||
}
|
||||
|
||||
buffer_write(cl->fd, &res.buffer);
|
||||
buffer_destroy(&res.buffer);
|
||||
dm_config_destroy(req.cft);
|
||||
@@ -4345,6 +4388,9 @@ static void client_recv_action(struct client *cl)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (act->op == LD_OP_LOCK && act->mode != LD_LK_UN)
|
||||
cl->lock_ops = 1;
|
||||
|
||||
switch (act->op) {
|
||||
case LD_OP_START:
|
||||
rv = add_lockspace(act);
|
||||
@@ -4352,6 +4398,12 @@ static void client_recv_action(struct client *cl)
|
||||
case LD_OP_STOP:
|
||||
rv = rem_lockspace(act);
|
||||
break;
|
||||
case LD_OP_DUMP_LOG:
|
||||
case LD_OP_DUMP_INFO:
|
||||
/* The client thread reply will copy and send the dump. */
|
||||
add_client_result(act);
|
||||
rv = 0;
|
||||
break;
|
||||
case LD_OP_INIT:
|
||||
case LD_OP_START_WAIT:
|
||||
case LD_OP_STOP_ALL:
|
||||
|
@@ -85,6 +85,7 @@ struct client {
|
||||
unsigned int recv : 1;
|
||||
unsigned int dead : 1;
|
||||
unsigned int poll_ignore : 1;
|
||||
unsigned int lock_ops : 1;
|
||||
char name[MAX_NAME+1];
|
||||
};
|
||||
|
||||
|
@@ -585,12 +585,16 @@ static int spawn_detached_thread(struct lvmpolld_lv *pdlv)
|
||||
int r;
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
if (pthread_attr_init(&attr) != 0)
|
||||
return 0;
|
||||
|
||||
if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
|
||||
return 0;
|
||||
|
||||
r = pthread_create(&pdlv->tid, &attr, fork_and_poll, (void *)pdlv);
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
if (pthread_attr_destroy(&attr) != 0)
|
||||
return 0;
|
||||
|
||||
return !r;
|
||||
}
|
||||
|
@@ -23,7 +23,6 @@
|
||||
#include "toolcontext.h"
|
||||
#include "lvm-file.h"
|
||||
#include "memlock.h"
|
||||
#include "segtype.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -582,8 +581,11 @@ int config_file_read(struct dm_config_tree *cft)
|
||||
if (!(cf->dev = dev_create_file(filename, NULL, NULL, 1)))
|
||||
return_0;
|
||||
|
||||
if (!dev_open_readonly_buffered(cf->dev))
|
||||
if (!dev_open_readonly_buffered(cf->dev)) {
|
||||
dev_destroy_file(cf->dev);
|
||||
cf->dev = NULL;
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
r = config_file_read_fd(cft, cf->dev, 0, (size_t) info.st_size, 0, 0,
|
||||
@@ -1692,6 +1694,11 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
if (cfg_def->comment) {
|
||||
int pos = 0;
|
||||
while (_copy_one_line(cfg_def->comment, commentline, &pos, strlen(cfg_def->comment))) {
|
||||
if ((commentline[0] == '#') && (strlen(commentline) == 1)) {
|
||||
if (!out->tree_spec->withspaces)
|
||||
continue;
|
||||
commentline[0] = '\0';
|
||||
}
|
||||
fprintf(out->fp, "%s# %s\n", line, commentline);
|
||||
/* withsummary prints only the first comment line. */
|
||||
if (!out->tree_spec->withcomments)
|
||||
@@ -1714,6 +1721,9 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
if (cfg_def->flags & CFG_DEFAULT_UNDEFINED)
|
||||
fprintf(out->fp, "%s# This configuration %s does not have a default value defined.\n", line, node_type_name);
|
||||
|
||||
if (cfg_def->flags & CFG_DEFAULT_COMMENTED)
|
||||
fprintf(out->fp, "%s# This configuration %s has an automatic default value.\n", line, node_type_name);
|
||||
|
||||
if ((out->tree_spec->type == CFG_DEF_TREE_FULL) &&
|
||||
(out->tree_spec->check_status[cn->id] & CFG_USED))
|
||||
fprintf(out->fp, "%s# Value defined in existing configuration has been used for this setting.\n", line);
|
||||
@@ -2416,27 +2426,3 @@ int get_default_allocation_cache_pool_chunk_size_CFG(struct cmd_context *cmd, st
|
||||
{
|
||||
return DEFAULT_CACHE_POOL_CHUNK_SIZE * 2;
|
||||
}
|
||||
|
||||
const char *get_default_allocation_cache_policy_CFG(struct cmd_context *cmd, struct profile *profile)
|
||||
{
|
||||
const struct segment_type *segtype = get_segtype_from_string(cmd, "cache");
|
||||
unsigned attr = ~0;
|
||||
|
||||
if (!segtype ||
|
||||
!segtype->ops->target_present ||
|
||||
!segtype->ops->target_present(cmd, NULL, &attr)) {
|
||||
log_warn("WARNING: Cannot detect default cache policy, using \""
|
||||
DEFAULT_CACHE_POLICY "\".");
|
||||
return DEFAULT_CACHE_POLICY;
|
||||
}
|
||||
|
||||
if (attr & CACHE_FEATURE_POLICY_SMQ)
|
||||
return "smq";
|
||||
|
||||
if (attr & CACHE_FEATURE_POLICY_MQ)
|
||||
return "mq";
|
||||
|
||||
log_warn("WARNING: Default cache policy not available.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -71,6 +71,16 @@ static void _dev_init(struct device *dev, int max_error_count)
|
||||
dm_list_init(&dev->open_list);
|
||||
}
|
||||
|
||||
void dev_destroy_file(struct device *dev)
|
||||
{
|
||||
if (!(dev->flags & DEV_ALLOCED))
|
||||
return;
|
||||
|
||||
dm_free((void *) dm_list_item(dev->aliases.n, struct dm_str_list)->str);
|
||||
dm_free(dev->aliases.n);
|
||||
dm_free(dev);
|
||||
}
|
||||
|
||||
struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
struct dm_str_list *alias, int use_malloc)
|
||||
{
|
||||
|
@@ -586,12 +586,8 @@ static void _close(struct device *dev)
|
||||
|
||||
log_debug_devs("Closed %s", dev_name(dev));
|
||||
|
||||
if (dev->flags & DEV_ALLOCED) {
|
||||
dm_free((void *) dm_list_item(dev->aliases.n, struct dm_str_list)->
|
||||
str);
|
||||
dm_free(dev->aliases.n);
|
||||
dm_free(dev);
|
||||
}
|
||||
if (dev->flags & DEV_ALLOCED)
|
||||
dev_destroy_file(dev);
|
||||
}
|
||||
|
||||
static int _dev_close(struct device *dev, int immediate)
|
||||
|
@@ -123,6 +123,7 @@ void dev_flush(struct device *dev);
|
||||
|
||||
struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
struct dm_str_list *alias, int use_malloc);
|
||||
void dev_destroy_file(struct device *dev);
|
||||
|
||||
/* Return a valid device name from the alias list; NULL otherwise */
|
||||
const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
|
@@ -453,8 +453,9 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
"not match expected name %s.", vgname);
|
||||
|
||||
bad:
|
||||
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)))
|
||||
lvmcache_update_vgname_and_id(info, &vgsummary_orphan);
|
||||
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)) &&
|
||||
!lvmcache_update_vgname_and_id(info, &vgsummary_orphan))
|
||||
stack;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -105,7 +105,8 @@ static void _update_lvmcache_orphan(struct lvmcache_info *info)
|
||||
|
||||
memcpy(&vgsummary_orphan.vgid, lvmcache_fmt(info)->orphan_vg_name, strlen(lvmcache_fmt(info)->orphan_vg_name));
|
||||
|
||||
lvmcache_update_vgname_and_id(info, &vgsummary_orphan);
|
||||
if (!lvmcache_update_vgname_and_id(info, &vgsummary_orphan))
|
||||
stack;
|
||||
}
|
||||
|
||||
static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
|
@@ -434,6 +434,34 @@ int lv_is_cache_origin(const struct logical_volume *lv)
|
||||
return seg && lv_is_cache(seg->lv) && !lv_is_pending_delete(seg->lv) && (seg_lv(seg, 0) == lv);
|
||||
}
|
||||
|
||||
static const char *_get_default_cache_policy(struct cmd_context *cmd)
|
||||
{
|
||||
const struct segment_type *segtype = get_segtype_from_string(cmd, "cache");
|
||||
unsigned attr = ~0;
|
||||
const char *def = NULL;
|
||||
|
||||
if (!segtype ||
|
||||
!segtype->ops->target_present ||
|
||||
!segtype->ops->target_present(cmd, NULL, &attr)) {
|
||||
log_warn("WARNING: Cannot detect default cache policy, using \""
|
||||
DEFAULT_CACHE_POLICY "\".");
|
||||
return DEFAULT_CACHE_POLICY;
|
||||
}
|
||||
|
||||
if (attr & CACHE_FEATURE_POLICY_SMQ)
|
||||
def = "smq";
|
||||
else if (attr & CACHE_FEATURE_POLICY_MQ)
|
||||
def = "mq";
|
||||
else {
|
||||
log_error("Default cache policy is not available.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log_debug_metadata("Detected default cache_policy \"%s\".", def);
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
int cache_set_policy(struct lv_segment *seg, const char *name,
|
||||
const struct dm_config_tree *settings)
|
||||
{
|
||||
@@ -451,8 +479,11 @@ int cache_set_policy(struct lv_segment *seg, const char *name,
|
||||
log_error("Failed to duplicate policy name.");
|
||||
return 0;
|
||||
}
|
||||
} else if (!seg->policy_name && passed_seg_is_cache)
|
||||
seg->policy_name = find_config_tree_str(seg->lv->vg->cmd, allocation_cache_policy_CFG, NULL);
|
||||
} else if (!seg->policy_name && passed_seg_is_cache) {
|
||||
if (!(seg->policy_name = find_config_tree_str(seg->lv->vg->cmd, allocation_cache_policy_CFG, NULL)) &&
|
||||
!(seg->policy_name = _get_default_cache_policy(seg->lv->vg->cmd)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (settings) {
|
||||
if (!seg->policy_name) {
|
||||
|
@@ -5105,6 +5105,11 @@ static int _lvresize_check_type(struct cmd_context *cmd, const struct logical_vo
|
||||
}
|
||||
}
|
||||
|
||||
if ((lp->resize == LV_REDUCE) && lv_is_thin_pool_metadata(lv)) {
|
||||
log_error("Thin pool metadata volumes cannot be reduced.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv &&
|
||||
(lp->resize == LV_EXTEND)) {
|
||||
/* Validate thin target supports bigger size of thin volume then external origin */
|
||||
@@ -5296,7 +5301,7 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
*/
|
||||
inactive = 1;
|
||||
if (!activate_lv_excl(cmd, lock_lv)) {
|
||||
log_error("Failed to activate %s.", lock_lv->name);
|
||||
log_error("Failed to activate %s.", display_lvname(lock_lv));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -5317,12 +5322,12 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
backup(vg);
|
||||
|
||||
if (inactive && !deactivate_lv(cmd, lock_lv)) {
|
||||
log_error("Problem deactivating %s.", lock_lv->name);
|
||||
log_error("Problem deactivating %s.", display_lvname(lock_lv));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
log_print_unless_silent("Logical volume %s successfully resized", lp->lv_name);
|
||||
log_print_unless_silent("Logical volume %s successfully resized.", lp->lv_name);
|
||||
|
||||
if (lp->resizefs && (lp->resize == LV_EXTEND) &&
|
||||
!_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE, NULL))
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#include "activate.h"
|
||||
#include "lv_alloc.h"
|
||||
#include "lvm-string.h"
|
||||
#include "lvmlockd.h"
|
||||
|
||||
static int _lv_is_raid_with_tracking(const struct logical_volume *lv,
|
||||
struct logical_volume **tracking)
|
||||
|
@@ -63,6 +63,10 @@ int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
|
||||
|
||||
tmsg->type = type;
|
||||
|
||||
/* If the 1st message is add in non-read-only mode, modify transaction_id */
|
||||
if (!no_update && dm_list_empty(&pool_seg->thin_messages))
|
||||
pool_seg->transaction_id++;
|
||||
|
||||
dm_list_add(&pool_seg->thin_messages, &tmsg->list);
|
||||
|
||||
log_debug_metadata("Added %s message.",
|
||||
@@ -476,9 +480,6 @@ int update_pool_lv(struct logical_volume *lv, int activate)
|
||||
|
||||
dm_list_init(&(first_seg(lv)->thin_messages));
|
||||
|
||||
/* thin-pool target transaction is finished, increase lvm2 TID */
|
||||
first_seg(lv)->transaction_id++;
|
||||
|
||||
if (!vg_write(lv->vg) || !vg_commit(lv->vg))
|
||||
return_0;
|
||||
|
||||
|
@@ -20,7 +20,6 @@
|
||||
#include "toolcontext.h"
|
||||
#include "lvmcache.h"
|
||||
#include "archiver.h"
|
||||
#include "lvmlockd.h"
|
||||
|
||||
struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
|
||||
const char *vg_name)
|
||||
|
@@ -25,14 +25,57 @@
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
/*
|
||||
* Symbol export control macros
|
||||
*
|
||||
* DM_EXPORT_SYMBOL(func,ver)
|
||||
* DM_EXPORT_SYMBOL_BASE(func,ver)
|
||||
*
|
||||
* For functions that have multiple implementations these macros control
|
||||
* symbol export and versioning.
|
||||
*
|
||||
* Function definitions that exist in only one version never need to use
|
||||
* these macros.
|
||||
*
|
||||
* Backwards compatible implementations must include a version tag of
|
||||
* the form "_v1_02_104" as a suffix to the function name and use the
|
||||
* macro DM_EXPORT_SYMBOL to export the function and bind it to the
|
||||
* specified version string.
|
||||
*
|
||||
* Since versioning is only available when compiling with GCC the entire
|
||||
* compatibility version should be enclosed in '#if defined(__GNUC__)',
|
||||
* for example:
|
||||
*
|
||||
* int dm_foo(int bar)
|
||||
* {
|
||||
* return bar;
|
||||
* }
|
||||
*
|
||||
* #if defined(__GNUC__)
|
||||
* // Backward compatible dm_foo() version 1.02.104
|
||||
* int dm_foo_v1_02_104(void);
|
||||
* int dm_foo_v1_02_104(void)
|
||||
* {
|
||||
* return 0;
|
||||
* }
|
||||
* DM_EXPORT_SYMBOL(dm_foo,1_02_104)
|
||||
* #endif
|
||||
*
|
||||
* A prototype for the compatibility version is required as these
|
||||
* functions must not be declared static.
|
||||
*
|
||||
* The DM_EXPORT_SYMBOL_BASE macro is only used to export the base
|
||||
* versions of library symbols prior to the introduction of symbol
|
||||
* versioning: it must never be used for new symbols.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
#define DM_EXPORTED_SYMBOL(func, ver) \
|
||||
__asm__(".symver " #func "_v" #ver ", " #func "@@DM_" #ver )
|
||||
#define DM_EXPORTED_SYMBOL_BASE(func) \
|
||||
#define DM_EXPORT_SYMBOL(func, ver) \
|
||||
__asm__(".symver " #func "_v" #ver ", " #func "@DM_" #ver )
|
||||
#define DM_EXPORT_SYMBOL_BASE(func) \
|
||||
__asm__(".symver " #func "_base, " #func "@Base" )
|
||||
#else
|
||||
#define DM_EXPORTED_SYMBOL(func, ver)
|
||||
#define DM_EXPORTED_SYMBOL_BASE(func)
|
||||
#define DM_EXPORT_SYMBOL(func, ver)
|
||||
#define DM_EXPORT_SYMBOL_BASE(func)
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -37,11 +37,13 @@
|
||||
|
||||
/* Define some portable printing types */
|
||||
#define PRIsize_t "zu"
|
||||
#define PRIssize_t "zd"
|
||||
#define PRIptrdiff_t "td"
|
||||
#define PRIpid_t PRId32
|
||||
|
||||
/* For convenience */
|
||||
#define FMTsize_t "%" PRIsize_t
|
||||
#define FMTssize_t "%" PRIssize_t
|
||||
#define FMTptrdiff_t "%" PRIptrdiff_t
|
||||
#define FMTpid_t "%" PRIpid_t
|
||||
|
||||
|
@@ -1344,7 +1344,7 @@ static int _cache_settings_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
|
||||
if (seg_is_cache(seg))
|
||||
seg = first_seg(seg->pool_lv);
|
||||
else {
|
||||
else if (!seg_is_cache_pool(seg)) {
|
||||
dm_list_init(&dummy_list);
|
||||
return _field_set_string_list(rh, field, &dummy_list, private, 0);
|
||||
/* TODO: once we have support for STR_LIST reserved values, replace with:
|
||||
@@ -1384,7 +1384,7 @@ static int _cache_policy_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
|
||||
if (seg_is_cache(seg))
|
||||
seg = first_seg(seg->pool_lv);
|
||||
else
|
||||
else if (!seg_is_cache_pool(seg) || !seg->policy_name)
|
||||
return _field_set_value(field, GET_FIRST_RESERVED_NAME(cache_policy_undef),
|
||||
GET_FIELD_RESERVED_VALUE(cache_policy_undef));
|
||||
|
||||
@@ -2078,7 +2078,7 @@ static int _cachemode_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
if (seg_is_cache(seg))
|
||||
seg = first_seg(seg->pool_lv);
|
||||
|
||||
if (seg_is_cache_pool(seg)) {
|
||||
if (seg_is_cache_pool(seg) && cache_mode_is_set(seg)) {
|
||||
if (!(cachemode_str = get_cache_mode_name(seg)))
|
||||
return_0;
|
||||
|
||||
|
@@ -295,7 +295,7 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
|
||||
}
|
||||
|
||||
if (!dm_tree_node_add_thin_pool_target(node, len,
|
||||
seg->transaction_id + (laopts->send_messages ? 1 : 0),
|
||||
seg->transaction_id,
|
||||
metadata_dlid, pool_dlid,
|
||||
seg->chunk_size, seg->low_water_mark,
|
||||
seg->zero_new_blocks ? 0 : 1))
|
||||
@@ -345,7 +345,7 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
|
||||
*/
|
||||
if (!lv_thin_pool_transaction_id(seg->lv, &transaction_id))
|
||||
return_0; /* Thin pool should exist and work */
|
||||
if (transaction_id != seg->transaction_id) {
|
||||
if ((transaction_id + 1) != seg->transaction_id) {
|
||||
log_error("Can't create snapshot %s as origin %s is not suspended.",
|
||||
lmsg->u.lv->name, origin->name);
|
||||
return 0;
|
||||
@@ -373,11 +373,11 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
|
||||
|
||||
if (!dm_list_empty(&seg->thin_messages)) {
|
||||
/* Messages were passed, modify transaction_id as the last one */
|
||||
log_debug_activation("Thin pool set transaction id %" PRIu64 ".", seg->transaction_id + 1);
|
||||
log_debug_activation("Thin pool set transaction id %" PRIu64 ".", seg->transaction_id);
|
||||
if (!dm_tree_node_add_thin_pool_message(node,
|
||||
DM_THIN_MESSAGE_SET_TRANSACTION_ID,
|
||||
seg->transaction_id,
|
||||
seg->transaction_id + 1))
|
||||
seg->transaction_id - 1,
|
||||
seg->transaction_id))
|
||||
return_0;
|
||||
}
|
||||
|
||||
|
@@ -539,6 +539,7 @@ void daemon_start(daemon_state s)
|
||||
log_state _log = { { 0 } };
|
||||
thread_state _threads = { .next = NULL };
|
||||
unsigned timeout_count = 0;
|
||||
fd_set in;
|
||||
|
||||
/*
|
||||
* Switch to C locale to avoid reading large locale-archive file used by
|
||||
@@ -623,7 +624,6 @@ void daemon_start(daemon_state s)
|
||||
|
||||
while (!_shutdown_requested && !failed) {
|
||||
_reset_timeout(s);
|
||||
fd_set in;
|
||||
FD_ZERO(&in);
|
||||
FD_SET(s.socket_fd, &in);
|
||||
if (select(FD_SETSIZE, &in, NULL, NULL, _get_timeout(s)) < 0 && errno != EINTR)
|
||||
|
@@ -179,7 +179,6 @@ dm_task_destroy
|
||||
dm_task_enable_checks
|
||||
dm_task_get_deps
|
||||
dm_task_get_driver_version
|
||||
dm_task_get_info
|
||||
dm_task_get_info_with_deferred_remove
|
||||
dm_task_get_message_response
|
||||
dm_task_get_name
|
||||
|
@@ -6,7 +6,6 @@ dm_stats_bind_uuid
|
||||
dm_stats_buffer_destroy
|
||||
dm_stats_clear_region
|
||||
dm_stats_create
|
||||
dm_stats_create_region
|
||||
dm_stats_delete_region
|
||||
dm_stats_destroy
|
||||
dm_stats_get_area_start
|
||||
@@ -72,7 +71,6 @@ dm_task_get_ioctl_timestamp
|
||||
dm_task_set_record_timestamp
|
||||
dm_timestamp_alloc
|
||||
dm_timestamp_compare
|
||||
dm_timestamp_copy
|
||||
dm_timestamp_delta
|
||||
dm_timestamp_destroy
|
||||
dm_timestamp_get
|
||||
|
4
libdm/.exported_symbols.DM_1_02_105
Normal file
4
libdm/.exported_symbols.DM_1_02_105
Normal file
@@ -0,0 +1,4 @@
|
||||
dm_report_is_empty
|
||||
dm_stats_get_area_offset
|
||||
dm_stats_get_current_area_offset
|
||||
dm_timestamp_copy
|
5
libdm/.exported_symbols.DM_1_02_106
Normal file
5
libdm/.exported_symbols.DM_1_02_106
Normal file
@@ -0,0 +1,5 @@
|
||||
dm_message_supports_precise_timestamps
|
||||
dm_stats_create_region
|
||||
dm_stats_driver_supports_precise
|
||||
dm_stats_get_current_region_precise_timestamps
|
||||
dm_stats_get_region_precise_timestamps
|
@@ -55,7 +55,7 @@ include $(top_builddir)/make.tmpl
|
||||
|
||||
CFLAGS += $(UDEV_CFLAGS) $(VALGRIND_CFLAGS)
|
||||
|
||||
LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS)
|
||||
LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS) $(M_LIBS)
|
||||
|
||||
device-mapper: all
|
||||
|
||||
|
@@ -604,6 +604,20 @@ static int dm_inactive_supported(void)
|
||||
return inactive_supported;
|
||||
}
|
||||
|
||||
int dm_message_supports_precise_timestamps(void)
|
||||
{
|
||||
/*
|
||||
* 4.32.0 supports "precise_timestamps" and "histogram:" options
|
||||
* to @stats_create messages but lacks the ability to report
|
||||
* these properties via a subsequent @stats_list: require at
|
||||
* least 4.33.0 in order to use these features.
|
||||
*/
|
||||
if (dm_check_version() && _dm_version >= 4)
|
||||
if (_dm_version_minor >= 33)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *dm_get_next_target(struct dm_task *dmt, void *next,
|
||||
uint64_t *start, uint64_t *length,
|
||||
char **target_type, char **params)
|
||||
@@ -667,13 +681,7 @@ int dm_format_dev(char *buf, int bufsize, uint32_t dev_major,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
int dm_task_get_info_v1_02_97(struct dm_task *dmt, struct dm_info *info);
|
||||
DM_EXPORTED_SYMBOL(dm_task_get_info, 1_02_97);
|
||||
int dm_task_get_info_v1_02_97(struct dm_task *dmt, struct dm_info *info)
|
||||
#else
|
||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
|
||||
#endif
|
||||
{
|
||||
if (!dmt->dmi.v4)
|
||||
return 0;
|
||||
@@ -2126,12 +2134,12 @@ void dm_lib_exit(void)
|
||||
*/
|
||||
|
||||
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info);
|
||||
DM_EXPORTED_SYMBOL_BASE(dm_task_get_info);
|
||||
DM_EXPORT_SYMBOL_BASE(dm_task_get_info);
|
||||
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info)
|
||||
{
|
||||
struct dm_info new_info;
|
||||
|
||||
if (!dm_task_get_info_v1_02_97(dmt, &new_info))
|
||||
if (!dm_task_get_info(dmt, &new_info))
|
||||
return 0;
|
||||
|
||||
memcpy(info, &new_info, offsetof(struct dm_info, deferred_remove));
|
||||
@@ -2144,7 +2152,7 @@ int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *i
|
||||
{
|
||||
struct dm_info new_info;
|
||||
|
||||
if (!dm_task_get_info_v1_02_97(dmt, &new_info))
|
||||
if (!dm_task_get_info(dmt, &new_info))
|
||||
return 0;
|
||||
|
||||
memcpy(info, &new_info, offsetof(struct dm_info, internal_suspend));
|
||||
|
@@ -464,6 +464,38 @@ int dm_stats_bind_name(struct dm_stats *dms, const char *name);
|
||||
*/
|
||||
int dm_stats_bind_uuid(struct dm_stats *dms, const char *uuid);
|
||||
|
||||
/*
|
||||
* Test whether the running kernel supports the precise_timestamps
|
||||
* feature. Presence of this feature also implies histogram support.
|
||||
* The library will check this call internally and fails any attempt
|
||||
* to use nanosecond counters or histograms on kernels that fail to
|
||||
* meet this check.
|
||||
*/
|
||||
int dm_message_supports_precise_timestamps(void);
|
||||
|
||||
/*
|
||||
* Precise timetamps support.
|
||||
*
|
||||
* Test for the presence of precise_timestamps support.
|
||||
*/
|
||||
int dm_stats_driver_supports_precise(void);
|
||||
|
||||
/*
|
||||
* Returns 1 if the specified region has the precise_timestamps feature
|
||||
* enabled (i.e. produces nanosecond-precision counter values) or 0 for
|
||||
* a region using the default milisecond precision.
|
||||
*/
|
||||
int dm_stats_get_region_precise_timestamps(const struct dm_stats *dms,
|
||||
uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Returns 1 if the region at the current cursor location has the
|
||||
* precise_timestamps feature enabled (i.e. produces
|
||||
* nanosecond-precision counter values) or 0 for a region using the
|
||||
* default milisecond precision.
|
||||
*/
|
||||
int dm_stats_get_current_region_precise_timestamps(const struct dm_stats *dms);
|
||||
|
||||
#define DM_STATS_ALL_PROGRAMS ""
|
||||
/*
|
||||
* Parse the response from a @stats_list message. dm_stats_list will
|
||||
@@ -526,6 +558,9 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id,
|
||||
*
|
||||
* dm_stats_create_region(dms, 1024, 1 << 11, -2, p, a);
|
||||
*
|
||||
* If precise is non-zero attempt to create a region with nanosecond
|
||||
* precision counters using the kernel precise_timestamps feature.
|
||||
*
|
||||
* program_id is an optional string argument that identifies the
|
||||
* program creating the region. If program_id is NULL or the empty
|
||||
* string the default program_id stored in the handle will be used.
|
||||
@@ -539,6 +574,7 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id,
|
||||
*/
|
||||
int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
||||
uint64_t start, uint64_t len, int64_t step,
|
||||
int precise,
|
||||
const char *program_id, const char *aux_data);
|
||||
|
||||
/*
|
||||
@@ -697,26 +733,36 @@ int dm_stats_set_program_id(struct dm_stats *dms, int allow_empty,
|
||||
*
|
||||
* All values are returned in units of 512b sectors.
|
||||
*/
|
||||
uint64_t dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id);
|
||||
uint64_t dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
|
||||
uint64_t region_id);
|
||||
uint64_t dm_stats_get_region_area_len(const struct dm_stats *dms,
|
||||
uint64_t *area_len, uint64_t region_id);
|
||||
int dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id);
|
||||
|
||||
int dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
|
||||
uint64_t region_id);
|
||||
|
||||
int dm_stats_get_region_area_len(const struct dm_stats *dms,
|
||||
uint64_t *len, uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Area properties: start and length.
|
||||
* Area properties: start, offset and length.
|
||||
*
|
||||
* The area length is always equal to the area length of the region
|
||||
* that contains it and is obtained from dm_stats_get_region_area_len().
|
||||
*
|
||||
* The start offset of an area is a function of the area_id and the
|
||||
* containing region's start and area length.
|
||||
* The start of an area is a function of the area_id and the containing
|
||||
* region's start and area length: it gives the absolute offset into the
|
||||
* containing device of the beginning of the area.
|
||||
*
|
||||
* The offset expresses the area's relative offset into the current
|
||||
* region. I.e. the area start minus the start offset of the containing
|
||||
* region.
|
||||
*
|
||||
* All values are returned in units of 512b sectors.
|
||||
*/
|
||||
uint64_t dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
int dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_area_offset(const struct dm_stats *dms, uint64_t *offset,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
/*
|
||||
* Retrieve program_id and aux_data for a specific region. Only valid
|
||||
@@ -856,14 +902,14 @@ uint64_t dm_stats_get_current_area(const struct dm_stats *dms);
|
||||
*
|
||||
* All values are returned in units of 512b sectors.
|
||||
*/
|
||||
uint64_t dm_stats_get_current_region_start(const struct dm_stats *dms,
|
||||
uint64_t *start);
|
||||
int dm_stats_get_current_region_start(const struct dm_stats *dms,
|
||||
uint64_t *start);
|
||||
|
||||
uint64_t dm_stats_get_current_region_len(const struct dm_stats *dms,
|
||||
uint64_t *len);
|
||||
int dm_stats_get_current_region_len(const struct dm_stats *dms,
|
||||
uint64_t *len);
|
||||
|
||||
uint64_t dm_stats_get_current_region_area_len(const struct dm_stats *dms,
|
||||
uint64_t *area_len);
|
||||
int dm_stats_get_current_region_area_len(const struct dm_stats *dms,
|
||||
uint64_t *area_len);
|
||||
|
||||
/*
|
||||
* Current area properties: start and length.
|
||||
@@ -873,10 +919,13 @@ uint64_t dm_stats_get_current_region_area_len(const struct dm_stats *dms,
|
||||
*
|
||||
* All values are returned in units of 512b sectors.
|
||||
*/
|
||||
uint64_t dm_stats_get_current_area_start(const struct dm_stats *dms,
|
||||
uint64_t *start);
|
||||
int dm_stats_get_current_area_start(const struct dm_stats *dms,
|
||||
uint64_t *start);
|
||||
|
||||
uint64_t dm_stats_get_current_area_len(const struct dm_stats *dms,
|
||||
int dm_stats_get_current_area_offset(const struct dm_stats *dms,
|
||||
uint64_t *offset);
|
||||
|
||||
int dm_stats_get_current_area_len(const struct dm_stats *dms,
|
||||
uint64_t *start);
|
||||
|
||||
/*
|
||||
@@ -2396,6 +2445,11 @@ int dm_report_object_is_selected(struct dm_report *rh, void *object, int do_outp
|
||||
*/
|
||||
int dm_report_compact_fields(struct dm_report *rh);
|
||||
|
||||
/*
|
||||
* Returns 1 if there is no data waiting to be output.
|
||||
*/
|
||||
int dm_report_is_empty(struct dm_report *rh);
|
||||
|
||||
int dm_report_output(struct dm_report *rh);
|
||||
|
||||
/*
|
||||
|
@@ -1586,7 +1586,7 @@ static int _node_send_messages(struct dm_tree_node *dnode,
|
||||
}
|
||||
|
||||
/* Error if there are no stacked messages or id mismatches */
|
||||
if (trans_id != (seg->transaction_id - have_messages)) {
|
||||
if ((trans_id + 1) != seg->transaction_id) {
|
||||
log_error("Thin pool %s transaction_id is %" PRIu64 ", while expected %" PRIu64 ".",
|
||||
_node_name(dnode), trans_id, seg->transaction_id - have_messages);
|
||||
return 0;
|
||||
|
@@ -257,7 +257,7 @@ static int _selected_disp(struct dm_report *rh,
|
||||
const void *data,
|
||||
void *private __attribute__((unused)))
|
||||
{
|
||||
struct row *row = (struct row *)data;
|
||||
const struct row *row = (const struct row *)data;
|
||||
return dm_report_field_int(rh, field, &row->selected);
|
||||
}
|
||||
|
||||
@@ -1387,11 +1387,11 @@ static int _dbl_less_or_equal(double d1, double d2)
|
||||
return _dbl_less(d1, d2) || _dbl_equal(d1, d2);
|
||||
}
|
||||
|
||||
#define _uint64 *(uint64_t *)
|
||||
#define _uint64arr(var,index) ((uint64_t *)var)[index]
|
||||
#define _uint64 *(const uint64_t *)
|
||||
#define _uint64arr(var,index) ((const uint64_t *)var)[index]
|
||||
#define _str (const char *)
|
||||
#define _dbl *(double *)
|
||||
#define _dblarr(var,index) ((double *)var)[index]
|
||||
#define _dbl *(const double *)
|
||||
#define _dblarr(var,index) ((const double *)var)[index]
|
||||
|
||||
static int _do_check_value_is_strictly_reserved(unsigned type, const void *res_val, int res_range,
|
||||
const void *val, struct field_selection *fs)
|
||||
@@ -1790,7 +1790,7 @@ static int _compare_selection_field(struct dm_report *rh,
|
||||
r = _cmp_field_int(rh, f->props->field_num, field_id, *(const uint64_t *) f->sort_value, fs);
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_SIZE:
|
||||
r = _cmp_field_double(rh, f->props->field_num, field_id, *(double *) f->sort_value, fs);
|
||||
r = _cmp_field_double(rh, f->props->field_num, field_id, *(const double *) f->sort_value, fs);
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_STRING:
|
||||
r = _cmp_field_string(rh, f->props->field_num, field_id, (const char *) f->sort_value, fs);
|
||||
@@ -2446,8 +2446,8 @@ static const char *_tok_value_regex(struct dm_report *rh,
|
||||
|
||||
static int _str_list_item_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct dm_str_list **item_a = (const struct dm_str_list **) a;
|
||||
const struct dm_str_list **item_b = (const struct dm_str_list **) b;
|
||||
const struct dm_str_list * const *item_a = (const struct dm_str_list * const *) a;
|
||||
const struct dm_str_list * const *item_b = (const struct dm_str_list * const *) b;
|
||||
|
||||
return strcmp((*item_a)->str, (*item_b)->str);
|
||||
}
|
||||
@@ -3357,7 +3357,7 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
memcpy(s, v, len);
|
||||
s[len] = '\0';
|
||||
|
||||
fs->value->v.r = dm_regex_create(rh->selection->mem, (const char **) &s, 1);
|
||||
fs->value->v.r = dm_regex_create(rh->selection->mem, (const char * const *) &s, 1);
|
||||
dm_free(s);
|
||||
if (!fs->value->v.r) {
|
||||
log_error("dm_report: failed to create regex "
|
||||
@@ -3377,7 +3377,7 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
if (rvw->value) {
|
||||
fs->value->v.s = (const char *) rvw->value;
|
||||
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
|
||||
fs->value->next->v.s = (((const char **) rvw->value)[1]);
|
||||
fs->value->next->v.s = (((const char * const *) rvw->value)[1]);
|
||||
dm_pool_free(rh->selection->mem, s);
|
||||
} else {
|
||||
fs->value->v.s = s;
|
||||
@@ -3389,9 +3389,9 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_NUMBER:
|
||||
if (rvw->value) {
|
||||
fs->value->v.i = *(uint64_t *) rvw->value;
|
||||
fs->value->v.i = *(const uint64_t *) rvw->value;
|
||||
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
|
||||
fs->value->next->v.i = (((uint64_t *) rvw->value)[1]);
|
||||
fs->value->next->v.i = (((const uint64_t *) rvw->value)[1]);
|
||||
} else {
|
||||
if (((fs->value->v.i = strtoull(s, NULL, 10)) == ULLONG_MAX) &&
|
||||
(errno == ERANGE)) {
|
||||
@@ -3407,16 +3407,16 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_SIZE:
|
||||
if (rvw->value) {
|
||||
fs->value->v.d = *(double *) rvw->value;
|
||||
fs->value->v.d = *(const double *) rvw->value;
|
||||
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
|
||||
fs->value->next->v.d = (((double *) rvw->value)[1]);
|
||||
fs->value->next->v.d = (((const double *) rvw->value)[1]);
|
||||
} else {
|
||||
fs->value->v.d = strtod(s, NULL);
|
||||
if (errno == ERANGE) {
|
||||
log_error(_out_of_range_msg, s, field_id);
|
||||
goto error;
|
||||
}
|
||||
if (custom && (factor = *((uint64_t *)custom)))
|
||||
if (custom && (factor = *((const uint64_t *)custom)))
|
||||
fs->value->v.d *= factor;
|
||||
fs->value->v.d /= 512; /* store size in sectors! */
|
||||
if (_check_value_is_strictly_reserved(rh, field_num, DM_REPORT_FIELD_TYPE_SIZE, &fs->value->v.d, NULL)) {
|
||||
@@ -3428,9 +3428,9 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_PERCENT:
|
||||
if (rvw->value) {
|
||||
fs->value->v.i = *(uint64_t *) rvw->value;
|
||||
fs->value->v.i = *(const uint64_t *) rvw->value;
|
||||
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
|
||||
fs->value->next->v.i = (((uint64_t *) rvw->value)[1]);
|
||||
fs->value->next->v.i = (((const uint64_t *) rvw->value)[1]);
|
||||
} else {
|
||||
fs->value->v.d = strtod(s, NULL);
|
||||
if ((errno == ERANGE) || (fs->value->v.d < 0) || (fs->value->v.d > 100)) {
|
||||
@@ -3455,9 +3455,9 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_TIME:
|
||||
if (rvw->value) {
|
||||
fs->value->v.t = *(time_t *) rvw->value;
|
||||
fs->value->v.t = *(const time_t *) rvw->value;
|
||||
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
|
||||
fs->value->next->v.t = (((time_t *) rvw->value)[1]);
|
||||
fs->value->next->v.t = (((const time_t *) rvw->value)[1]);
|
||||
} else {
|
||||
tval = (struct time_value *) custom;
|
||||
fs->value->v.t = tval->t1;
|
||||
@@ -4305,6 +4305,11 @@ static int _output_as_columns(struct dm_report *rh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_report_is_empty(struct dm_report *rh)
|
||||
{
|
||||
return dm_list_empty(&rh->rows) ? 1 : 0;
|
||||
}
|
||||
|
||||
int dm_report_output(struct dm_report *rh)
|
||||
{
|
||||
if (dm_list_empty(&rh->rows))
|
||||
|
@@ -13,14 +13,14 @@
|
||||
*/
|
||||
|
||||
#include "dmlib.h"
|
||||
#include "libdm-targets.h"
|
||||
#include "libdm-common.h"
|
||||
|
||||
#define DM_STATS_REGION_NOT_PRESENT UINT64_MAX
|
||||
|
||||
#define NSEC_PER_MSEC 1000000L
|
||||
#define NSEC_PER_SEC 1000000000L
|
||||
|
||||
#define PRECISE_ARG "precise_timestamps"
|
||||
|
||||
/*
|
||||
* See Documentation/device-mapper/statistics.txt for full descriptions
|
||||
* of the device-mapper statistics counter fields.
|
||||
@@ -63,7 +63,8 @@ struct dm_stats {
|
||||
uint64_t nr_regions; /* total number of present regions */
|
||||
uint64_t max_region; /* size of the regions table */
|
||||
uint64_t interval_ns; /* sampling interval in nanoseconds */
|
||||
uint64_t timescale; /* sample value multiplier */
|
||||
uint64_t timescale; /* default sample value multiplier */
|
||||
int precise; /* use precise_timestamps when creating regions */
|
||||
struct dm_stats_region *regions;
|
||||
/* statistics cursor */
|
||||
uint64_t cur_region;
|
||||
@@ -111,8 +112,9 @@ struct dm_stats *dm_stats_create(const char *program_id)
|
||||
dms->name = NULL;
|
||||
dms->uuid = NULL;
|
||||
|
||||
/* all regions currently use msec precision */
|
||||
/* by default all regions use msec precision */
|
||||
dms->timescale = NSEC_PER_MSEC;
|
||||
dms->precise = 0;
|
||||
|
||||
dms->nr_regions = DM_STATS_REGION_NOT_PRESENT;
|
||||
dms->max_region = DM_STATS_REGION_NOT_PRESENT;
|
||||
@@ -227,6 +229,19 @@ int dm_stats_bind_uuid(struct dm_stats *dms, const char *uuid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _stats_check_precise_timestamps(const struct dm_stats *dms)
|
||||
{
|
||||
/* Already checked? */
|
||||
if (dms && dms->precise)
|
||||
return 1;
|
||||
return dm_message_supports_precise_timestamps();
|
||||
}
|
||||
|
||||
int dm_stats_driver_supports_precise(void)
|
||||
{
|
||||
return _stats_check_precise_timestamps(NULL);
|
||||
}
|
||||
|
||||
static struct dm_task *_stats_send_message(struct dm_stats *dms, char *msg)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
@@ -251,24 +266,55 @@ out:
|
||||
|
||||
static int _stats_parse_list_region(struct dm_stats_region *region, char *line)
|
||||
{
|
||||
/* FIXME: the kernel imposes no length limit here */
|
||||
char program_id[256], aux_data[256];
|
||||
char *p = NULL, string_data[4096]; /* FIXME: add dm_sscanf with %ms? */
|
||||
const char *program_id, *aux_data, *stats_args;
|
||||
const char *empty_string = "";
|
||||
int r;
|
||||
|
||||
/* line format:
|
||||
* <region_id>: <start_sector>+<length> <step> <program_id> <aux_data>
|
||||
*/
|
||||
r = sscanf(line, FMTu64 ": " FMTu64 "+" FMTu64 " " FMTu64 "%255s %255s",
|
||||
®ion->region_id, ®ion->start, ®ion->len, ®ion->step,
|
||||
program_id, aux_data);
|
||||
memset(string_data, 0, sizeof(string_data));
|
||||
|
||||
if (r != 6)
|
||||
/*
|
||||
* Parse fixed fields, line format:
|
||||
*
|
||||
* <region_id>: <start_sector>+<length> <step> <string data>
|
||||
*
|
||||
* Maximum string data size is 4096 - 1 bytes.
|
||||
*/
|
||||
r = sscanf(line, FMTu64 ": " FMTu64 "+" FMTu64 " " FMTu64 " %4095c",
|
||||
®ion->region_id, ®ion->start, ®ion->len,
|
||||
®ion->step, string_data);
|
||||
|
||||
if (r != 5)
|
||||
return_0;
|
||||
|
||||
if (!strcmp(program_id, "-"))
|
||||
program_id[0] = '\0';
|
||||
if (!strcmp(aux_data, "-"))
|
||||
aux_data[0] = '\0';
|
||||
/* program_id is guaranteed to be first. */
|
||||
program_id = string_data;
|
||||
|
||||
/*
|
||||
* FIXME: support embedded '\ ' in string data:
|
||||
* s/strchr/_find_unescaped_space()/
|
||||
*/
|
||||
if ((p = strchr(string_data, ' '))) {
|
||||
/* terminate program_id string. */
|
||||
*p = '\0';
|
||||
if (!strcmp(program_id, "-"))
|
||||
program_id = empty_string;
|
||||
aux_data = p + 1;
|
||||
if ((p = strchr(aux_data, ' '))) {
|
||||
/* terminate aux_data string. */
|
||||
*p = '\0';
|
||||
if (!strcmp(aux_data, "-"))
|
||||
aux_data = empty_string;
|
||||
stats_args = p + 1;
|
||||
} else
|
||||
stats_args = empty_string;
|
||||
} else
|
||||
aux_data = stats_args = empty_string;
|
||||
|
||||
if (strstr(stats_args, PRECISE_ARG))
|
||||
region->timescale = 1;
|
||||
else
|
||||
region->timescale = NSEC_PER_MSEC;
|
||||
|
||||
if (!(region->program_id = dm_strdup(program_id)))
|
||||
return_0;
|
||||
@@ -504,14 +550,16 @@ out:
|
||||
|
||||
static uint64_t _nr_areas(uint64_t len, uint64_t step)
|
||||
{
|
||||
/* Default is one area. */
|
||||
if (!len || !step)
|
||||
return 1;
|
||||
/*
|
||||
* drivers/md/dm-stats.c::message_stats_create()
|
||||
* A region may be sub-divided into areas with their own counters.
|
||||
* If step is non-zero, divide len into that many areas, otherwise
|
||||
* treat the entire region as a single area. Any partial area at the
|
||||
* end of the region is treated as an additional complete area.
|
||||
* Any partial area at the end of the region is treated as an
|
||||
* additional complete area.
|
||||
*/
|
||||
return (len / (step ? : len)) + !!(len % step);
|
||||
return (len + step - 1) / step;
|
||||
}
|
||||
|
||||
static uint64_t _nr_areas_region(struct dm_stats_region *region)
|
||||
@@ -621,14 +669,17 @@ uint64_t dm_stats_get_nr_areas(const struct dm_stats *dms)
|
||||
return nr_areas;
|
||||
}
|
||||
|
||||
int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
||||
uint64_t start, uint64_t len, int64_t step,
|
||||
const char *program_id, const char *aux_data)
|
||||
static int _stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
||||
uint64_t start, uint64_t len, int64_t step,
|
||||
int precise,
|
||||
const char *program_id, const char *aux_data)
|
||||
{
|
||||
struct dm_task *dmt = NULL;
|
||||
char msg[1024], range[64];
|
||||
const char *err_fmt = "Could not prepare @stats_create %s.";
|
||||
const char *resp;
|
||||
const char *precise_str = PRECISE_ARG;
|
||||
const char *resp, *opt_args = NULL;
|
||||
int nr_opt = 0, r = 0; /* number of optional args. */
|
||||
|
||||
if (!_stats_bound(dms))
|
||||
return_0;
|
||||
@@ -640,16 +691,35 @@ int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
||||
if (!dm_snprintf(range, sizeof(range), FMTu64 "+" FMTu64,
|
||||
start, len)) {
|
||||
log_error(err_fmt, "range");
|
||||
goto out;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dm_snprintf(msg, sizeof(msg), "@stats_create %s %s" FMTu64 " %s %s",
|
||||
(start || len) ? range : "-",
|
||||
if (precise < 0)
|
||||
precise = dms->precise;
|
||||
|
||||
if (precise)
|
||||
nr_opt++;
|
||||
else
|
||||
precise_str = "";
|
||||
|
||||
if (nr_opt) {
|
||||
if ((dm_asprintf((char **)&opt_args, "%d %s", nr_opt,
|
||||
precise_str)) < 0) {
|
||||
log_error(err_fmt, PRECISE_ARG " option.");
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
opt_args = dm_strdup("");
|
||||
|
||||
if (!dm_snprintf(msg, sizeof(msg), "@stats_create %s %s" FMTu64
|
||||
" %s %s %s", (start || len) ? range : "-",
|
||||
(step < 0) ? "/" : "",
|
||||
(uint64_t)llabs(step), program_id, aux_data)) {
|
||||
(uint64_t)llabs(step),
|
||||
opt_args, program_id, aux_data)) {
|
||||
log_error(err_fmt, "message");
|
||||
goto out;
|
||||
dm_free((void *) opt_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dmt = _stats_send_message(dms, msg)))
|
||||
@@ -668,15 +738,46 @@ int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
||||
goto_out;
|
||||
}
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
r = 1;
|
||||
|
||||
return 1;
|
||||
out:
|
||||
if(dmt)
|
||||
dm_task_destroy(dmt);
|
||||
return 0;
|
||||
dm_free((void *) opt_args);
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
||||
uint64_t start, uint64_t len, int64_t step,
|
||||
int precise,
|
||||
const char *program_id,
|
||||
const char *aux_data)
|
||||
{
|
||||
/* Nanosecond counters need precise_timestamps. */
|
||||
if (precise && !_stats_check_precise_timestamps(dms))
|
||||
return 0;
|
||||
|
||||
return _stats_create_region(dms, region_id, start, len, step,
|
||||
precise,
|
||||
program_id, aux_data);
|
||||
}
|
||||
|
||||
/* Backward compatible dm_stats_create_region() */
|
||||
#if defined(__GNUC__)
|
||||
int dm_stats_create_region_v1_02_104(struct dm_stats *dms, uint64_t *region_id,
|
||||
uint64_t start, uint64_t len, int64_t step,
|
||||
const char *program_id, const char *aux_data);
|
||||
int dm_stats_create_region_v1_02_104(struct dm_stats *dms, uint64_t *region_id,
|
||||
uint64_t start, uint64_t len, int64_t step,
|
||||
const char *program_id, const char *aux_data)
|
||||
{
|
||||
return _stats_create_region(dms, region_id, start, len, step,
|
||||
dms->precise,
|
||||
program_id, aux_data);
|
||||
}
|
||||
DM_EXPORT_SYMBOL(dm_stats_create_region, 1_02_104);
|
||||
#endif
|
||||
|
||||
int dm_stats_delete_region(struct dm_stats *dms, uint64_t region_id)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
@@ -815,7 +916,7 @@ static int _dm_stats_populate_region(struct dm_stats *dms, uint64_t region_id,
|
||||
if (!_stats_bound(dms))
|
||||
return_0;
|
||||
|
||||
if (!_stats_parse_region(dms->mem, resp, region, dms->timescale)) {
|
||||
if (!_stats_parse_region(dms->mem, resp, region, region->timescale)) {
|
||||
log_error("Could not parse @stats_print message response.");
|
||||
return 0;
|
||||
}
|
||||
@@ -1280,7 +1381,7 @@ uint64_t dm_stats_get_current_area(const struct dm_stats *dms)
|
||||
return dms->cur_area;
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
|
||||
int dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id)
|
||||
{
|
||||
if (!dms || !dms->regions)
|
||||
@@ -1289,7 +1390,7 @@ uint64_t dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
|
||||
int dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
|
||||
uint64_t region_id)
|
||||
{
|
||||
if (!dms || !dms->regions)
|
||||
@@ -1298,51 +1399,69 @@ uint64_t dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_region_area_len(const struct dm_stats *dms, uint64_t *step,
|
||||
uint64_t region_id)
|
||||
int dm_stats_get_region_area_len(const struct dm_stats *dms, uint64_t *len,
|
||||
uint64_t region_id)
|
||||
{
|
||||
if (!dms || !dms->regions)
|
||||
return_0;
|
||||
*step = dms->regions[region_id].step;
|
||||
*len = dms->regions[region_id].step;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_current_region_start(const struct dm_stats *dms,
|
||||
uint64_t *start)
|
||||
int dm_stats_get_current_region_start(const struct dm_stats *dms,
|
||||
uint64_t *start)
|
||||
{
|
||||
return dm_stats_get_region_start(dms, start, dms->cur_region);
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_current_region_len(const struct dm_stats *dms,
|
||||
uint64_t *len)
|
||||
int dm_stats_get_current_region_len(const struct dm_stats *dms,
|
||||
uint64_t *len)
|
||||
{
|
||||
return dm_stats_get_region_len(dms, len, dms->cur_region);
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_current_region_area_len(const struct dm_stats *dms,
|
||||
uint64_t *step)
|
||||
int dm_stats_get_current_region_area_len(const struct dm_stats *dms,
|
||||
uint64_t *step)
|
||||
{
|
||||
return dm_stats_get_region_area_len(dms, step, dms->cur_region);
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id, uint64_t area_id)
|
||||
int dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id, uint64_t area_id)
|
||||
{
|
||||
struct dm_stats_region *region;
|
||||
if (!dms || !dms->regions)
|
||||
return_0;
|
||||
*start = dms->regions[region_id].step * area_id;
|
||||
region = &dms->regions[region_id];
|
||||
*start = region->start + region->step * area_id;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_current_area_start(const struct dm_stats *dms,
|
||||
uint64_t *start)
|
||||
int dm_stats_get_area_offset(const struct dm_stats *dms, uint64_t *offset,
|
||||
uint64_t region_id, uint64_t area_id)
|
||||
{
|
||||
if (!dms || !dms->regions)
|
||||
return_0;
|
||||
*offset = dms->regions[region_id].step * area_id;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_stats_get_current_area_start(const struct dm_stats *dms,
|
||||
uint64_t *start)
|
||||
{
|
||||
return dm_stats_get_area_start(dms, start,
|
||||
dms->cur_region, dms->cur_area);
|
||||
}
|
||||
|
||||
uint64_t dm_stats_get_current_area_len(const struct dm_stats *dms,
|
||||
uint64_t *len)
|
||||
int dm_stats_get_current_area_offset(const struct dm_stats *dms,
|
||||
uint64_t *offset)
|
||||
{
|
||||
return dm_stats_get_area_offset(dms, offset,
|
||||
dms->cur_region, dms->cur_area);
|
||||
}
|
||||
|
||||
int dm_stats_get_current_area_len(const struct dm_stats *dms,
|
||||
uint64_t *len)
|
||||
{
|
||||
return dm_stats_get_region_area_len(dms, len, dms->cur_region);
|
||||
}
|
||||
@@ -1370,3 +1489,15 @@ const char *dm_stats_get_current_region_aux_data(const struct dm_stats *dms)
|
||||
{
|
||||
return dm_stats_get_region_aux_data(dms, dms->cur_region);
|
||||
}
|
||||
|
||||
int dm_stats_get_region_precise_timestamps(const struct dm_stats *dms,
|
||||
uint64_t region_id)
|
||||
{
|
||||
struct dm_stats_region *region = &dms->regions[region_id];
|
||||
return region->timescale == 1;
|
||||
}
|
||||
|
||||
int dm_stats_get_current_region_precise_timestamps(const struct dm_stats *dms)
|
||||
{
|
||||
return dm_stats_get_region_precise_timestamps(dms, dms->cur_region);
|
||||
}
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#ifdef HAVE_REALTIME
|
||||
|
||||
#include <time.h>
|
||||
#include <bits/time.h>
|
||||
|
||||
struct dm_timestamp {
|
||||
struct timespec t;
|
||||
|
@@ -54,6 +54,7 @@ LDDEPS += @LDDEPS@
|
||||
LIB_SUFFIX = @LIB_SUFFIX@
|
||||
LVMINTERNAL_LIBS = -llvm-internal $(DAEMON_LIBS) $(UDEV_LIBS) $(DL_LIBS) $(BLKID_LIBS)
|
||||
DL_LIBS = @DL_LIBS@
|
||||
M_LIBS = @M_LIBS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
READLINE_LIBS = @READLINE_LIBS@
|
||||
SELINUX_LIBS = @SELINUX_LIBS@
|
||||
@@ -501,10 +502,10 @@ else
|
||||
set -e;\
|
||||
R=$$(sort $^ | uniq -u);\
|
||||
test -z "$$R" || { echo "Mismatch between symbols in shared library and lists in .exported_symbols.* files: $$R"; false; } ;\
|
||||
for i in $(EXPORTED_SYMBOLS); do\
|
||||
for i in $$(echo $(EXPORTED_SYMBOLS) | tr ' ' '\n' | sort -rnt_ -k5 ); do\
|
||||
echo "$${i##*.} {"; echo " global:";\
|
||||
$(SED) "s/^/ /;s/$$/;/" $$i;\
|
||||
test "$$i" = Base && { echo " local:"; echo " *;"; };\
|
||||
test "$${i##*.}" = Base && { echo " local:"; echo " *;"; };\
|
||||
echo "};";\
|
||||
done > $@
|
||||
endif
|
||||
|
@@ -3,7 +3,7 @@
|
||||
cmirrord \(em cluster mirror log daemon
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B cmirrord
|
||||
\fBcmirrord\fR [\fB\-f\fR] [\fB\-h\fR]
|
||||
|
||||
.SH DESCRIPTION
|
||||
cmirrord is the daemon that tracks mirror log information in a cluster.
|
||||
@@ -24,6 +24,12 @@ there are still active cluster mirrors, however, the signal will be
|
||||
ignored. Active cluster mirrors should be shutdown before stopping the
|
||||
cluster mirror log daemon.
|
||||
|
||||
.SH OPTIONS
|
||||
.IP "\fB\-f\fR, \fB\-\-foreground\fR" 4
|
||||
Do not fork and log to the terminal.
|
||||
.IP "\fB\-h\fR, \fB\-\-help\fR" 4
|
||||
Print usage.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8)
|
||||
.BR clvmd (8)
|
||||
|
@@ -27,10 +27,12 @@ dmstats \(em device-mapper statistics management
|
||||
.br
|
||||
.B dmstats create
|
||||
.I device_name
|
||||
.RB [ \-\-alldevices ]
|
||||
.RB [[ \-\-areas
|
||||
.IR nr_areas ]
|
||||
.RB |[ \-\-areasize
|
||||
.IR area_size ]]
|
||||
.RB [ \-\-precise ]
|
||||
.RB [[ \-\-start
|
||||
.IR start_sector ]
|
||||
.RB [ \-\-length
|
||||
@@ -43,7 +45,7 @@ dmstats \(em device-mapper statistics management
|
||||
.br
|
||||
.B dmstats delete
|
||||
.I device_name
|
||||
.RB [ \-\-force ]
|
||||
.RB [ \-\-alldevices ]
|
||||
.RB [ \-\-allregions
|
||||
.RB | \-\-regionid
|
||||
.IR id ]
|
||||
@@ -62,6 +64,8 @@ dmstats \(em device-mapper statistics management
|
||||
.RB [ \-\-units
|
||||
.IR units ]
|
||||
.RB [ \-\-nosuffix ]
|
||||
.RB [ \-\-nosuffix ]
|
||||
.RB [ \-v | \-\-verbose \ [ \-v | \-\-verbose ]
|
||||
.br
|
||||
.B dmstats print
|
||||
.RI [ device_name ]
|
||||
@@ -115,10 +119,14 @@ when run as 'dmsetup stats'.
|
||||
|
||||
When no device argument is given dmstats will by default operate on all
|
||||
device-mapper devices present. The \fBcreate\fP and \fBdelete\fP
|
||||
commands require the use of \fB--force\fP when used in this way.
|
||||
commands require the use of \fB--alldevices\fP when used in this way.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-\-alldevices
|
||||
If no device arguments are given allow operation on all devices when
|
||||
creating or deleting regions.
|
||||
.TP
|
||||
.B \-\-allprograms
|
||||
Include regions from all program IDs for list and report operations.
|
||||
.TP
|
||||
@@ -174,6 +182,10 @@ Specify which report fields to display.
|
||||
Sort output according to the list of fields given. Precede any
|
||||
sort_field with - for a reverse sort on that column.
|
||||
.TP
|
||||
.BR \-\-precise
|
||||
Attempt to use nanosecond precision counters when creating new
|
||||
statistics regions.
|
||||
.TP
|
||||
.B \-\-programid \fIid
|
||||
Specify a program ID string. When creating new statistics regions this
|
||||
string is stored with the region. Subsequent operations may supply a
|
||||
@@ -233,6 +245,7 @@ regions (with the exception of in-flight IO counters).
|
||||
.IR nr_areas ]
|
||||
.RB [ \-\-areasize
|
||||
.IR area_size ]
|
||||
.RB [ \-\-precise ]
|
||||
.RB [[ \-\-start
|
||||
.IR start_sector ]
|
||||
.RB [ \-\-length
|
||||
@@ -252,6 +265,9 @@ at an arbitrary offset into the device. The \fB\-\-segments\fP option
|
||||
causes a new region to be created for each target in the corresponding
|
||||
device-mapper device's table.
|
||||
|
||||
If the \fB\-\-precise\fP option is used the command will attempt to
|
||||
create a region using nanosecond precision counters.
|
||||
|
||||
An optional \fBprogram_id\fP or \fBaux_data\fP string may be associated
|
||||
with the region. A \fBprogram_id\fP may then be used to select regions
|
||||
for subsequent list, print, and report operations. The \fBaux_data\fP
|
||||
@@ -259,7 +275,7 @@ stores an arbitrary string and is not used by dmstats or the
|
||||
device-mapper kernel statistics subsystem.
|
||||
|
||||
By default dmstats creates regions with a \fBprogram_id\fP of
|
||||
"DMSTATS1".
|
||||
"dmstats".
|
||||
|
||||
On success the \fBregion_id\fP of the newly created region is printed to
|
||||
stdout.
|
||||
@@ -267,7 +283,7 @@ stdout.
|
||||
.TP
|
||||
.B delete
|
||||
.I [ device_name ]
|
||||
.RB [ \-\-force ]
|
||||
.RB [ \-\-alldevices ]
|
||||
.RB [ \-\-allregions
|
||||
.RB | \-\-regionid
|
||||
.IR id ]
|
||||
@@ -282,7 +298,8 @@ of subsequent list, print, or report operations.
|
||||
All regions registered on a device may be removed using
|
||||
\fB\-\-allregions\fP.
|
||||
|
||||
To remove all regions on all devices \fB\-\-force\fP must be used.
|
||||
To remove all regions on all devices both \fB--allregions\fP and
|
||||
\fB\-\-alldevices\fP must be used.
|
||||
.br
|
||||
.TP
|
||||
.B help
|
||||
@@ -296,11 +313,15 @@ the list of report fields.
|
||||
.RI [ device_name ]
|
||||
.RB [ \-\-allprograms ]
|
||||
.RB [ \-\-programid
|
||||
.RB [ \-v | \-\-verbose \ [ \-v | \-\-verbose ]]
|
||||
.IR id ]
|
||||
.br
|
||||
List the statistics regions registered on the device. If the
|
||||
\fB\-\-allprograms\fP switch is given all regions will be listed
|
||||
regardless of region program ID values.
|
||||
|
||||
If \fB\-v\fP or \fB\-\-verbose\fP is given the report will include
|
||||
a row of information for each area contained in each region displayed.
|
||||
.br
|
||||
.TP
|
||||
.B print
|
||||
@@ -495,6 +516,20 @@ The program ID value associated with this region.
|
||||
.br
|
||||
The auxiliary data value associated with this region.
|
||||
.br
|
||||
.HP
|
||||
.B interval_ns
|
||||
.br
|
||||
The estimated interval over which the current counter values have
|
||||
accumulated. The vaulue is reported as an interger expressed in units
|
||||
of nanoseconds.
|
||||
.br
|
||||
.HP
|
||||
.B interval
|
||||
.br
|
||||
The estimated interval over which the current counter values have
|
||||
accumulated. The value is reported as a real number in units of
|
||||
seconds.
|
||||
.br
|
||||
.SS Basic counters
|
||||
Basic counters provide access to the raw counter data from the kernel,
|
||||
allowing further processing to be carried out by another program.
|
||||
@@ -565,7 +600,7 @@ Create a whole-device region with one area on vg00/lvol1
|
||||
.br
|
||||
# dmstats create vg00/lvol1
|
||||
.br
|
||||
Created region: 0
|
||||
vg00/lvol1: Created new region with 1 area(s) as region ID 0
|
||||
.br
|
||||
.br
|
||||
|
||||
@@ -575,7 +610,7 @@ Create a 32M region 1G into device d0
|
||||
.br
|
||||
# dmstats create --start 1G --length 32M d0
|
||||
.br
|
||||
Created region: 2
|
||||
d0: Created new region with 1 area(s) as region ID 0
|
||||
.br
|
||||
|
||||
|
||||
@@ -584,24 +619,24 @@ Create a whole-device region with 8 areas on every device
|
||||
.br
|
||||
# dmstats create --areas 8
|
||||
.br
|
||||
Created region: 0
|
||||
vg00/lvol1: Created new region with 8 area(s) as region ID 0
|
||||
.br
|
||||
Created region: 0
|
||||
vg00/lvol2: Created new region with 8 area(s) as region ID 0
|
||||
.br
|
||||
Created region: 0
|
||||
vg00/lvol3: Created new region with 8 area(s) as region ID 0
|
||||
.br
|
||||
Created region: 2
|
||||
vg01/lvol0: Created new region with 8 area(s) as region ID 2
|
||||
.br
|
||||
Created region: 0
|
||||
vg01/lvol1: Created new region with 8 area(s) as region ID 0
|
||||
.br
|
||||
Created region: 0
|
||||
vg00/lvol2: Created new region with 8 area(s) as region ID 1
|
||||
.br
|
||||
.br
|
||||
|
||||
Delete all regions on all devices
|
||||
.br
|
||||
.br
|
||||
# dmstats delete --allregions --force
|
||||
# dmstats delete --alldevices --allregions
|
||||
.br
|
||||
.br
|
||||
|
||||
@@ -611,7 +646,7 @@ using dmsetup
|
||||
.br
|
||||
# dmsetup stats create --areasize 10G vg00/lvol1
|
||||
.br
|
||||
Created region: 1
|
||||
vg00/lvol1: Created new region with 5 area(s) as region ID 1
|
||||
.br
|
||||
.br
|
||||
|
||||
@@ -619,7 +654,7 @@ Create a 1GiB region with 16 areas at the start of vg00/lvol1
|
||||
.br
|
||||
# dmstats create --start 0 --len 1G --areas=16 vg00/lvol1
|
||||
.br
|
||||
Created region: 2
|
||||
vg00/lvol1: Created new region with 16 area(s) as region ID 0
|
||||
.br
|
||||
.br
|
||||
|
||||
@@ -627,13 +662,13 @@ List the statistics regions registered on vg00/lvol1
|
||||
.br
|
||||
# dmstats list vg00/lvol1
|
||||
.br
|
||||
RegionID RegStart RegLen AreaSize ProgramID AuxData
|
||||
Name RgID RStart RSize #Areas ASize ProgID
|
||||
.br
|
||||
0 0 104857600 20971520 dmstats
|
||||
vg00-lvol1 0 0 61.00g 1 61.00g dmstats
|
||||
.br
|
||||
1 0 104857600 20971520 dmstats
|
||||
vg00-lvol1 1 61.00g 19.20g 1 19.20g dmstats
|
||||
.br
|
||||
2 0 2097152 131072 dmstats
|
||||
vg00-lvol1 2 80.20g 2.14g 1 2.14g dmstats
|
||||
.br
|
||||
.br
|
||||
|
||||
@@ -642,19 +677,15 @@ Display five statistics reports for vg00/lvol1 at an interval of one second
|
||||
.br
|
||||
# dmstats report --interval 1 --count 5 vg00/lvol1
|
||||
.br
|
||||
Name RgID ArID RRqM/s WRqM/s R/s W/s RSz/s WSz/s AvRqSz QSize SvcTm Util% AWait
|
||||
# dmstats report
|
||||
.br
|
||||
vg00-lvol1 0 0 0.00 0.00 8.00 0.00 48.00k 0 6.00k 0.00 5.50 4.40 6.62
|
||||
Name RgID ArID AStart ASize RRqM/s WRqM/s R/s W/s RSz/s WSz/s AvRqSz QSize Util% AWait RdAWa WrAWa
|
||||
.br
|
||||
vg00-lvol1 0 1 0.00 0.00 22.00 0.00 624.00k 0 28.00k 0.00 5.23 11.50 5.36
|
||||
vg_hex-lv_home 0 0 0 61.00g 0.00 0.00 0.00 218.00 0 1.04m 4.50k 2.97 81.70 13.62 0.00 13.62
|
||||
.br
|
||||
vg00-lvol1 0 2 0.00 0.00 353.00 0.00 1.84m 0 5.00k 0.00 1.34 47.40 1.33
|
||||
vg_hex-lv_home 1 0 61.00g 19.20g 0.00 0.00 0.00 5.00 0 548.00k 109.50k 0.14 11.00 27.40 0.00 27.40
|
||||
.br
|
||||
vg00-lvol1 0 3 0.00 0.00 73.00 0.00 592.00k 0 8.00k 0.00 2.10 15.30 2.10
|
||||
.br
|
||||
vg00-lvol1 0 4 0.00 0.00 5.00 0.00 52.00k 0 10.00k 0.00 4.00 2.00 4.00
|
||||
.br
|
||||
[...]
|
||||
vg_hex-lv_home 2 0 80.20g 2.14g 0.00 0.00 0.00 14.00 0 1.15m 84.00k 0.39 18.70 27.71 0.00 27.71
|
||||
.br
|
||||
.br
|
||||
|
||||
@@ -663,11 +694,11 @@ Create one region for reach target contained in device vg00/lvol1
|
||||
.br
|
||||
# dmstats create --segments vg00/lvol1
|
||||
.br
|
||||
Created region: 0
|
||||
Created new region with 1 area(s) as region ID 0
|
||||
.br
|
||||
Created region: 1
|
||||
Created new region with 1 area(s) as region ID 1
|
||||
.br
|
||||
Created region: 2
|
||||
Created new region with 1 area(s) as region ID 2
|
||||
.br
|
||||
.br
|
||||
|
||||
|
@@ -228,7 +228,7 @@ For more information on cache pool LVs and cache LVs, see \fBlvmcache\fP(7).
|
||||
.TP
|
||||
.B \-\-cachepolicy \fIpolicy
|
||||
Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
|
||||
the cache policy. \fImq\fP is the basic policy name. \fIsqm\fP is more advanced
|
||||
the cache policy. \fImq\fP is the basic policy name. \fIsmq\fP is more advanced
|
||||
version available in newer kernels.
|
||||
.TP
|
||||
.BR \-\-cachepool " " \fICachePoolLV
|
||||
@@ -326,7 +326,7 @@ operation from its arguments.
|
||||
Separates \fICacheLogicalVolume\fP from cache pool.
|
||||
Before the logical volume becomes uncached, cache is flushed.
|
||||
The cache pool volume is then left unused and
|
||||
could be used e.g. to caching another volume.
|
||||
could be used e.g. for caching another volume.
|
||||
See also the option \fB\-\-uncache\fP for uncaching and removing
|
||||
cache pool with one command.
|
||||
.TP
|
||||
|
@@ -200,7 +200,7 @@ cache pool LV.
|
||||
.TP
|
||||
.B \-\-cachepolicy \fIpolicy
|
||||
Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
|
||||
the cache policy. \fImq\fP is the basic policy name. \fIsqm\fP is more advanced
|
||||
the cache policy. \fImq\fP is the basic policy name. \fIsmq\fP is more advanced
|
||||
version available in newer kernels.
|
||||
.TP
|
||||
.IR \fB\-\-cachepool " " CachePoolLogicalVolume { Name | Path }
|
||||
|
@@ -164,6 +164,8 @@ fi
|
||||
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/metadata_profile_template.profile
|
||||
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/thin-generic.profile
|
||||
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/thin-performance.profile
|
||||
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/cache-mq.profile
|
||||
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/cache-smq.profile
|
||||
%dir %{_sysconfdir}/lvm/backup
|
||||
%dir %{_sysconfdir}/lvm/cache
|
||||
%dir %{_sysconfdir}/lvm/archive
|
||||
|
@@ -308,6 +308,12 @@ lv_field() {
|
||||
die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
|
||||
}
|
||||
|
||||
lva_field() {
|
||||
local actual=$(get lva_field "$1" "$2" "${@:4}")
|
||||
test "$actual" = "$3" || \
|
||||
die "lva_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
|
||||
}
|
||||
|
||||
lv_attr_bit() {
|
||||
local actual=$(get lv_field "$2" lv_attr "${@:4}")
|
||||
local offset=$1
|
||||
|
@@ -42,6 +42,11 @@ lv_field() {
|
||||
trim_ "$r"
|
||||
}
|
||||
|
||||
lva_field() {
|
||||
local r=$(lvs -a --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1")
|
||||
trim_ "$r"
|
||||
}
|
||||
|
||||
lv_devices() {
|
||||
lv_field "$1" devices -a "${@:2}" | sed 's/([^)]*)//g; s/,/\n/g'
|
||||
}
|
||||
|
@@ -15,6 +15,10 @@ test_description='Remove the dlm test setup'
|
||||
|
||||
[ -z "$LVM_TEST_LOCK_TYPE_DLM" ] && skip;
|
||||
|
||||
# FIXME: collect debug logs (only if a test failed?)
|
||||
# lvmlockctl -d > lvmlockd-debug.txt
|
||||
# dlm_tool dump > dlm-debug.txt
|
||||
|
||||
systemctl stop dlm
|
||||
systemctl stop corosync
|
||||
killall lvmlockd
|
||||
|
32
test/shell/lvconvert-cache-smq.sh
Normal file
32
test/shell/lvconvert-cache-smq.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2014 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# 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
|
||||
|
||||
# Exercise conversion of cache and cache pool
|
||||
|
||||
. lib/inittest
|
||||
|
||||
test -e LOCAL_LVMPOLLD && skip
|
||||
|
||||
aux have_cache 1 8 0 || skip
|
||||
|
||||
aux prepare_vg 5 80
|
||||
|
||||
lvcreate --type cache-pool -an -v -L 2 -n cpool $vg
|
||||
|
||||
lvcreate -H --cachepolicy smq -L 4 -n corigin --cachepool $vg/cpool
|
||||
|
||||
check lv_field $vg/corigin cache_policy "smq"
|
||||
|
||||
lvconvert --splitcache $vg/corigin
|
||||
|
||||
lvs -o+cache_policy -a $vg
|
||||
|
||||
vgremove -f $vg
|
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2014 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2014-2015 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
@@ -37,11 +37,25 @@ lvcreate -an -Zn -L 8 -n $lv3 $vg
|
||||
lvcreate -an -Zn -L 8 -n $lv4 $vg
|
||||
lvcreate -an -Zn -L 16 -n $lv5 $vg
|
||||
|
||||
lvconvert --yes --type cache-pool --cachepool $vg/$lv1
|
||||
# check validation of cachemode arg works
|
||||
fail lvconvert --yes --type cache-pool --cachemode writethroughX --cachepool $vg/$lv1
|
||||
|
||||
# by default no cache settings are attached to converted cache-pool
|
||||
lvconvert --yes --type cache-pool --chunksize 256 $vg/$lv1
|
||||
check inactive $vg ${lv1}_cdata
|
||||
lvconvert --yes --type cache-pool --chunksize 256 $vg/$lv2
|
||||
check lv_field $vg/$lv1 cache_mode ""
|
||||
check lv_field $vg/$lv1 cache_policy ""
|
||||
check lv_field $vg/$lv1 cache_settings ""
|
||||
check lv_field $vg/$lv1 chunk_size "256.00k"
|
||||
|
||||
# but allow to set them when specified explicitely on command line
|
||||
lvconvert --yes --type cache-pool --cachemode writeback --cachepolicy mq \
|
||||
--cachesettings sequential_threshold=1234 --cachesettings random_threshold=56 \
|
||||
--cachepool $vg/$lv2
|
||||
check inactive $vg ${lv2}_cdata
|
||||
check lv_field $vg/$lv2 chunk_size "256.00k"
|
||||
check lv_field $vg/$lv2 cache_mode "writeback"
|
||||
check lv_field $vg/$lv2 cache_policy "mq"
|
||||
check lv_field $vg/$lv2 cache_settings "random_threshold=56,sequential_threshold=1234"
|
||||
|
||||
# Check swap of cache pool metadata
|
||||
lvconvert --yes --type cache-pool --poolmetadata $lv4 $vg/$lv3
|
||||
@@ -58,7 +72,8 @@ lvremove -ff $vg
|
||||
|
||||
lvcreate -L 2 -n $lv1 $vg
|
||||
lvcreate --type cache-pool -l 1 -n ${lv1}_cachepool $vg
|
||||
lvconvert --cache --cachepool $vg/${lv1}_cachepool $vg/$lv1
|
||||
lvconvert --cache --cachepool $vg/${lv1}_cachepool --cachemode writeback $vg/$lv1
|
||||
check lv_field $vg/$lv1 cache_mode "writeback"
|
||||
dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel
|
||||
|
||||
#lvconvert --cachepool $vg/${lv1}_cachepool $vg/$lv1
|
||||
|
@@ -63,8 +63,9 @@ vgcreate -s 1M $vg $(cat DEVICES)
|
||||
# Testing dmeventd autoresize
|
||||
lvcreate -L200M -V500M -n thin -T $vg/pool 2>&1 | tee out
|
||||
not grep "WARNING: Sum" out
|
||||
lvcreate -V2M -n thin2 $vg/pool
|
||||
lvcreate -L2M -n $lv1 $vg
|
||||
lvchange -an $vg/thin $vg/pool
|
||||
lvchange -an $vg/thin $vg/thin2 $vg/pool
|
||||
|
||||
# Prepare some fake metadata with unmatching id
|
||||
# Transaction_id is lower by 1 and there are no message -> ERROR
|
||||
@@ -86,7 +87,7 @@ grep expected out
|
||||
check inactive $vg pool_tmeta
|
||||
|
||||
# Prepare some fake metadata prefilled to ~81% (>70%)
|
||||
fake_metadata_ 400 1 >data
|
||||
fake_metadata_ 400 2 >data
|
||||
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
|
||||
|
||||
# Swap volume with restored fake metadata
|
||||
|
164
test/shell/lvmlockd-lv-types.sh
Normal file
164
test/shell/lvmlockd-lv-types.sh
Normal file
@@ -0,0 +1,164 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2008-2012 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# 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
|
||||
|
||||
test_description='Check lvmlockd lock_args for different LV types'
|
||||
|
||||
. lib/inittest
|
||||
|
||||
[ -z "$LVM_TEST_LVMLOCKD" ] && skip;
|
||||
|
||||
if test -n "$LVM_TEST_LOCK_TYPE_SANLOCK" ; then
|
||||
LOCKARGS1="1.0.0:70254592"
|
||||
LOCKARGS2="1.0.0:71303168"
|
||||
LOCKARGS3="1.0.0:72351744"
|
||||
fi
|
||||
|
||||
if test -n "$LVM_TEST_LOCK_TYPE_DLM" ; then
|
||||
LOCKARGS1="dlm"
|
||||
LOCKARGS2="dlm"
|
||||
LOCKARGS3="dlm"
|
||||
fi
|
||||
|
||||
aux prepare_devs 5
|
||||
|
||||
vgcreate --shared $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
|
||||
|
||||
#
|
||||
# thin pool, thin lv, thin snap
|
||||
#
|
||||
|
||||
lvcreate -L 8M -n pool1 $vg
|
||||
check lva_field $vg/pool1 lockargs $LOCKARGS1
|
||||
|
||||
lvcreate -L 8M -n pool1_meta $vg
|
||||
check lva_field $vg/pool1_meta lockargs $LOCKARGS2
|
||||
|
||||
lvconvert -y --type thin-pool --poolmetadata $vg/pool1_meta $vg/pool1
|
||||
check lva_field $vg/pool1 lockargs $LOCKARGS3
|
||||
check lva_field $vg/pool1_tdata lockargs ""
|
||||
check lva_field $vg/pool1_tmeta lockargs ""
|
||||
|
||||
lvcreate -n thin1 -V 1G --thinpool $vg/pool1
|
||||
check lva_field $vg/thin1 lockargs ""
|
||||
|
||||
lvcreate -s -n snap1 $vg/thin1
|
||||
check lva_field $vg/snap1 lockargs ""
|
||||
|
||||
lvchange -ay -K $vg/snap1
|
||||
|
||||
lvchange -an $vg/snap1
|
||||
lvchange -an $vg/thin1
|
||||
lvchange -an $vg/pool1
|
||||
lvremove $vg/snap1
|
||||
lvremove $vg/thin1
|
||||
lvremove $vg/pool1
|
||||
|
||||
# the first sanlock lock should be found and reused
|
||||
lvcreate -L 8M -n lv1 $vg
|
||||
check lva_field $vg/lv1 lockargs $LOCKARGS1
|
||||
|
||||
lvchange -an $vg/lv1
|
||||
lvremove $vg/lv1
|
||||
|
||||
|
||||
#
|
||||
# with automatic metadata lv
|
||||
#
|
||||
|
||||
lvcreate -L 8M -n pool2 $vg
|
||||
check lva_field $vg/pool2 lockargs $LOCKARGS1
|
||||
|
||||
lvconvert -y --type thin-pool $vg/pool2
|
||||
check lva_field $vg/pool2 lockargs $LOCKARGS2
|
||||
check lva_field $vg/pool2_tdata lockargs ""
|
||||
check lva_field $vg/pool2_tmeta lockargs ""
|
||||
|
||||
lvcreate -n thin2 -V 1G --thinpool $vg/pool2
|
||||
check lva_field $vg/thin2 lockargs ""
|
||||
|
||||
lvchange -an $vg/thin2
|
||||
lvchange -an $vg/pool2
|
||||
lvremove $vg/thin2
|
||||
lvremove $vg/pool2
|
||||
|
||||
|
||||
#
|
||||
# cache pool, cache lv
|
||||
#
|
||||
|
||||
lvcreate -L 8M -n cache1 $vg
|
||||
check lva_field $vg/cache1 lockargs $LOCKARGS1
|
||||
|
||||
lvcreate -L 8M -n cache1_meta $vg
|
||||
check lva_field $vg/cache1_meta lockargs $LOCKARGS2
|
||||
|
||||
lvconvert -y --type cache-pool --poolmetadata $vg/cache1_meta $vg/cache1
|
||||
check lva_field $vg/cache1 lockargs ""
|
||||
check lva_field $vg/cache1_cdata lockargs ""
|
||||
check lva_field $vg/cache1_cmeta lockargs ""
|
||||
|
||||
lvcreate -n lv1 -L 8M $vg
|
||||
check lva_field $vg/lv1 lockargs $LOCKARGS1
|
||||
|
||||
lvconvert -y --type cache --cachepool $vg/cache1 $vg/lv1
|
||||
check lva_field $vg/lv1 lockargs $LOCKARGS1
|
||||
check lva_field $vg/cache1 lockargs ""
|
||||
check lva_field $vg/cache1_cdata lockargs ""
|
||||
check lva_field $vg/cache1_cmeta lockargs ""
|
||||
|
||||
lvconvert --splitcache $vg/lv1
|
||||
check lva_field $vg/lv1 lockargs $LOCKARGS1
|
||||
check lva_field $vg/cache1 lockargs ""
|
||||
check lva_field $vg/cache1_cdata lockargs ""
|
||||
check lva_field $vg/cache1_cmeta lockargs ""
|
||||
|
||||
lvchange -an $vg/cache1
|
||||
lvchange -an $vg/lv1
|
||||
lvremove $vg/cache1
|
||||
lvremove $vg/lv1
|
||||
|
||||
#
|
||||
# cow snap
|
||||
#
|
||||
|
||||
lvcreate -n lv2 -L 8M $vg
|
||||
check lva_field $vg/lv2 lockargs $LOCKARGS1
|
||||
|
||||
lvcreate -s -n lv2snap -L 8M $vg/lv2
|
||||
check lva_field $vg/lv2 lockargs $LOCKARGS1
|
||||
check lva_field $vg/lv2snap lockargs ""
|
||||
|
||||
lvchange -y -an $vg/lv2
|
||||
lvremove $vg/lv2snap
|
||||
lvremove $vg/lv2
|
||||
|
||||
#
|
||||
# mirror
|
||||
#
|
||||
|
||||
lvcreate --type mirror -m 1 -n lv3 -L 8M $vg
|
||||
check lva_field $vg/lv3 lockargs $LOCKARGS1
|
||||
|
||||
lvchange -an $vg/lv3
|
||||
lvremove $vg/lv3
|
||||
|
||||
#
|
||||
# raid1
|
||||
#
|
||||
|
||||
lvcreate --type raid1 -m 1 -n lv4 -L 8M $vg
|
||||
check lva_field $vg/lv4 lockargs $LOCKARGS1
|
||||
|
||||
lvchange -an $vg/lv4
|
||||
lvremove $vg/lv4
|
||||
|
||||
vgremove $vg
|
||||
|
@@ -13,8 +13,6 @@ test_description='Test process_each_pv with zero mda'
|
||||
|
||||
. lib/inittest
|
||||
|
||||
test -e LOCAL_LVMPOLLD && skip
|
||||
|
||||
aux prepare_devs 14
|
||||
|
||||
# for vg1
|
||||
@@ -41,9 +39,9 @@ pvcreate "$dev14" --metadatacopies 0
|
||||
# dev12
|
||||
# dev13
|
||||
|
||||
vgcreate $vg1 "$dev10"
|
||||
vgcreate $vg2 "$dev2" "$dev3" "$dev4" "$dev5"
|
||||
vgcreate $vg3 "$dev6" "$dev7" "$dev8" "$dev9"
|
||||
vgcreate $SHARED $vg1 "$dev10"
|
||||
vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5"
|
||||
vgcreate $SHARED $vg3 "$dev6" "$dev7" "$dev8" "$dev9"
|
||||
|
||||
pvs -a | tee err
|
||||
grep "$dev10" err
|
||||
@@ -59,3 +57,5 @@ grep "$dev11" err
|
||||
grep "$dev12" err
|
||||
grep "$dev13" err
|
||||
grep "$dev14" err
|
||||
|
||||
vgremove $vg1 $vg2 $vg3
|
||||
|
@@ -13,15 +13,15 @@ test_description='Test process_each_pv with zero mda'
|
||||
|
||||
. lib/inittest
|
||||
|
||||
test -e LOCAL_LVMPOLLD && skip
|
||||
|
||||
aux prepare_devs 2
|
||||
|
||||
pvcreate "$dev1" --metadatacopies 0
|
||||
pvcreate "$dev2"
|
||||
|
||||
vgcreate $vg1 "$dev1" "$dev2"
|
||||
vgcreate $SHARED $vg1 "$dev1" "$dev2"
|
||||
|
||||
pvdisplay -a -C | tee err
|
||||
grep "$dev1" err
|
||||
grep "$dev2" err
|
||||
|
||||
vgremove $vg1
|
||||
|
@@ -73,6 +73,7 @@ prepare_lvmlockd_sanlock() {
|
||||
|
||||
GL_DEV="/dev/mapper/GL_DEV"
|
||||
GL_FILE="$PWD/gl_file.img"
|
||||
dmsetup remove GL_DEV || true
|
||||
rm -f "$GL_FILE"
|
||||
dd if=/dev/zero of="$GL_FILE" bs=$((1024*1024)) count=1024 2> /dev/null
|
||||
GL_LOOP=$(losetup -f "$GL_FILE" --show)
|
||||
@@ -80,7 +81,7 @@ echo "0 `blockdev --getsize $GL_LOOP` linear $GL_LOOP 0" | dmsetup create GL_DEV
|
||||
|
||||
prepare_lvmlockd_sanlock
|
||||
|
||||
vgcreate --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' --lock-type sanlock --lock-gl enable --lock-opt wait glvg $GL_DEV
|
||||
vgcreate --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' --lock-type sanlock glvg $GL_DEV
|
||||
|
||||
vgs --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' -o+locktype,lockargs glvg
|
||||
|
||||
|
@@ -15,14 +15,25 @@ test_description='Remove the sanlock test setup'
|
||||
|
||||
[ -z "$LVM_TEST_LOCK_TYPE_SANLOCK" ] && skip;
|
||||
|
||||
# FIMXME: get this to run after a test fails
|
||||
|
||||
# Removes the VG with the global lock that was created by
|
||||
# the corresponding create script.
|
||||
|
||||
vgremove --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' glvg
|
||||
|
||||
# FIXME: collect debug logs (only if a test failed?)
|
||||
# lvmlockctl -d > lvmlockd-debug.txt
|
||||
# sanlock log_dump > sanlock-debug.txt
|
||||
|
||||
killall lvmlockd
|
||||
killall sanlock
|
||||
|
||||
dmsetup remove GL_DEV
|
||||
# dmsetup remove glvg-lvmlock
|
||||
killall -9 lvmlockd
|
||||
killall -9 sanlock
|
||||
|
||||
# FIXME: dmsetup remove LVMTEST*-lvmlock
|
||||
|
||||
dmsetup remove glvg-lvmlock || true
|
||||
dmsetup remove GL_DEV || true
|
||||
|
||||
|
@@ -29,8 +29,11 @@ lvcreate -T -L8M $vg/pool -V10M -n $lv1
|
||||
# skip $vg from activation
|
||||
aux lvmconf "activation/volume_list = [ \"$vg1\" ]"
|
||||
|
||||
# We cannot pass - pool volume cannot be manipulated
|
||||
not lvcreate -V10 -n $lv2 -T $vg/pool
|
||||
# We still could pass - since pool is still active
|
||||
lvcreate -V10 -n $lv2 -T $vg/pool
|
||||
|
||||
# but $lv2 is not active
|
||||
check inactive $vg $lv2
|
||||
|
||||
vgchange -an $vg
|
||||
|
||||
|
@@ -275,6 +275,8 @@ xx(lvconvert,
|
||||
"[--type cache[-pool]|-H|--cache]\n"
|
||||
"\t[--cachepool CacheDataLogicalVolume[Path]]\n"
|
||||
"\t[--cachemode CacheMode]\n"
|
||||
"\t[--cachepolicy policy]\n"
|
||||
"\t[--cachesettings key=value]\n"
|
||||
"\t[--chunksize size]\n"
|
||||
"\t[--poolmetadataspare {y|n}]]\n"
|
||||
"\t[{--poolmetadata CacheMetadataLogicalVolume[Path] |\n"
|
||||
@@ -282,7 +284,8 @@ xx(lvconvert,
|
||||
COMMON_OPTS
|
||||
"\t[Cache|CacheDataPool]LogicalVolume[Path] [PhysicalVolumePath...]\n\n",
|
||||
|
||||
alloc_ARG, background_ARG, cache_ARG, cachemode_ARG, cachepool_ARG, chunksize_ARG,
|
||||
alloc_ARG, background_ARG, cache_ARG, cachemode_ARG,
|
||||
cachepool_ARG, cachepolicy_ARG, cachesettings_ARG, chunksize_ARG,
|
||||
corelog_ARG, discards_ARG, force_ARG, interval_ARG, merge_ARG, mirrorlog_ARG,
|
||||
mirrors_ARG, name_ARG, noudevsync_ARG, originname_ARG, poolmetadata_ARG,
|
||||
poolmetadatasize_ARG, poolmetadataspare_ARG, readahead_ARG, regionsize_ARG,
|
||||
@@ -301,6 +304,8 @@ xx(lvcreate,
|
||||
"\t[--alloc AllocationPolicy]\n"
|
||||
"\t[-H|--cache\n"
|
||||
"\t [--cachemode {writeback|writethrough}]\n"
|
||||
"\t [--cachepolicy policy]\n"
|
||||
"\t [--cachesettings key=value]\n"
|
||||
"\t[--cachepool CachePoolLogicalVolume{Name|Path}]\n"
|
||||
"\t[-c|--chunksize ChunkSize]\n"
|
||||
"\t[-C|--contiguous {y|n}]\n"
|
||||
|
1006
tools/dmsetup.c
1006
tools/dmsetup.c
File diff suppressed because it is too large
Load Diff
@@ -2002,7 +2002,7 @@ static int _lvconvert_uncache(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_remove_single(cmd, first_seg(lv)->pool_lv, lp->force, 0))
|
||||
if (!lv_remove_single(cmd, first_seg(lv)->pool_lv, (force_t) lp->force, 0))
|
||||
return_0;
|
||||
|
||||
log_print_unless_silent("Logical volume %s is not cached.", display_lvname(lv));
|
||||
@@ -2430,7 +2430,7 @@ static int _lvconvert_pool_repair(struct cmd_context *cmd,
|
||||
* Scan only the 1st. line for transation id.
|
||||
* Watch out, if the thin_dump format changes
|
||||
*/
|
||||
if ((fgets(meta_path, sizeof(meta_path), f) > 0) &&
|
||||
if (fgets(meta_path, sizeof(meta_path), f) &&
|
||||
(trans_id_str = strstr(meta_path, "transaction=\"")) &&
|
||||
(sscanf(trans_id_str + 13, FMTu64, &trans_id) == 1) &&
|
||||
(trans_id != first_seg(pool_lv)->transaction_id) &&
|
||||
@@ -2828,7 +2828,7 @@ static int _lvconvert_pool(struct cmd_context *cmd,
|
||||
|
||||
if (!metadata_lv) {
|
||||
if (arg_from_list_is_set(cmd, "is invalid with existing pool",
|
||||
cachemode_ARG, chunksize_ARG, discards_ARG,
|
||||
chunksize_ARG, discards_ARG,
|
||||
zero_ARG, poolmetadatasize_ARG, -1))
|
||||
return_0;
|
||||
|
||||
@@ -3069,6 +3069,10 @@ mda_write:
|
||||
seg->discards = lp->discards;
|
||||
seg->zero_new_blocks = lp->zero ? 1 : 0;
|
||||
|
||||
if (lp->cache_mode &&
|
||||
!cache_set_mode(seg, lp->cache_mode))
|
||||
return_0;
|
||||
|
||||
if ((lp->policy_name || lp->policy_settings) &&
|
||||
!cache_set_policy(seg, lp->policy_name, lp->policy_settings))
|
||||
return_0;
|
||||
@@ -3450,7 +3454,8 @@ bad:
|
||||
unlock_vg(cmd, lp->vg_name);
|
||||
|
||||
/* Unlock here so it's not held during polling. */
|
||||
lockd_vg(cmd, lp->vg_name, "un", 0, &lockd_state);
|
||||
if (!lockd_vg(cmd, lp->vg_name, "un", 0, &lockd_state))
|
||||
stack;
|
||||
|
||||
release_vg(vg);
|
||||
out:
|
||||
|
@@ -574,7 +574,7 @@ static int _read_cache_params(struct cmd_context *cmd,
|
||||
&lp->cache_mode,
|
||||
&lp->policy_name,
|
||||
&lp->policy_settings))
|
||||
return_NULL;
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -202,7 +202,8 @@ int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
|
||||
|
||||
unlock_and_release_vg(cmd, vg, vg->name);
|
||||
|
||||
lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state);
|
||||
if (!lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
|
||||
stack;
|
||||
|
||||
/*
|
||||
* FIXME Sleeping after testing, while preferred, also works around
|
||||
@@ -225,7 +226,9 @@ int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
|
||||
out:
|
||||
if (vg)
|
||||
unlock_and_release_vg(cmd, vg, vg->name);
|
||||
lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state);
|
||||
if (!lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
|
||||
stack;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -712,7 +712,8 @@ out_ret:
|
||||
* for some time monitoring the progress, and we don not want
|
||||
* or need the lockd lock held over that.
|
||||
*/
|
||||
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
|
||||
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -762,7 +763,8 @@ static int _read_poll_id_from_pvname(struct cmd_context *cmd, const char *pv_nam
|
||||
|
||||
unlock_and_release_vg(cmd, vg, vg_name);
|
||||
out:
|
||||
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
|
||||
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
|
||||
stack;
|
||||
free_pv_fid(pv);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -1957,7 +1957,8 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
|
||||
unlock_vg(cmd, vg_name);
|
||||
endvg:
|
||||
release_vg(vg);
|
||||
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
|
||||
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
|
||||
stack;
|
||||
}
|
||||
|
||||
/* the VG is selected if at least one LV is selected */
|
||||
@@ -2438,7 +2439,8 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
|
||||
unlock_vg(cmd, vg_name);
|
||||
endvg:
|
||||
release_vg(vg);
|
||||
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
|
||||
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
|
||||
stack;
|
||||
}
|
||||
|
||||
return ret_max;
|
||||
@@ -2942,7 +2944,8 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
|
||||
unlock_vg(cmd, vg->name);
|
||||
endvg:
|
||||
release_vg(vg);
|
||||
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
|
||||
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
|
||||
stack;
|
||||
|
||||
/* Quit early when possible. */
|
||||
if (!process_all_pvs && dm_list_empty(arg_tags) && dm_list_empty(arg_devices))
|
||||
|
@@ -1227,7 +1227,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
if (arg_is_set(cmd, lockstart_ARG)) {
|
||||
const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL);
|
||||
|
||||
lockd_gl(cmd, "un", 0);
|
||||
if (!lockd_gl(cmd, "un", 0))
|
||||
stack;
|
||||
|
||||
if (!start_opt || !strcmp(start_opt, "auto")) {
|
||||
log_print_unless_silent("Starting locking. Waiting until locks are ready...");
|
||||
|
@@ -22,8 +22,6 @@ static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name,
|
||||
if (arg_count(cmd, activevolumegroups_ARG) && !lvs_in_vg_activated(vg))
|
||||
return ECMD_PROCESSED;
|
||||
|
||||
vg_check_status(vg, EXPORTED_VG);
|
||||
|
||||
if (arg_count(cmd, colon_ARG)) {
|
||||
vgdisplay_colons(vg);
|
||||
return ECMD_PROCESSED;
|
||||
|
@@ -47,7 +47,7 @@ BLKID_RULE=IMPORT{program}=\"${SBIN}\/blkid -o udev -p \$$tempnode\"
|
||||
endif
|
||||
|
||||
ifeq ("@UDEV_SYSTEMD_BACKGROUND_JOBS@", "yes")
|
||||
PVSCAN_RULE=ACTION\!=\"remove\", ENV{LVM_PV_GONE}==\"1\", RUN\+=\"@bindir@/systemd-run $(LVM_EXEC)\/lvm pvscan --cache \$$major\:\$$minor\", GOTO=\"lvm_end\"\nENV{SYSTEMD_ALIAS}=\"\/dev\/block\/\$$major:\$$minor\"\nENV{ID_MODEL}=\"LVM PV \$$env{ID_FS_UUID_ENC} on \/dev\/\$$name\"\nENV{SYSTEMD_WANTS}+=\"lvm2-pvscan@\$$major:\$$minor.service\"
|
||||
PVSCAN_RULE=ACTION\!=\"remove\", ENV{LVM_PV_GONE}==\"1\", RUN\+=\"@bindir@/systemd-run $(LVM_EXEC)\/lvm pvscan --cache \$$major\:\$$minor\", GOTO=\"lvm_end\"\nENV{SYSTEMD_ALIAS}=\"\/dev\/block\/\$$major:\$$minor\"\nENV{ID_MODEL}=\"LVM PV \$$env{ID_FS_UUID_ENC} on \/dev\/\$$name\"\nENV{SYSTEMD_WANTS}\+=\"lvm2-pvscan@\$$major:\$$minor.service\"
|
||||
else
|
||||
PVSCAN_RULE=RUN\+\=\"$(LVM_EXEC)/lvm pvscan --background --cache --activate ay --major \$$major --minor \$$minor\", ENV{LVM_SCANNED}=\"1\"
|
||||
endif
|
||||
|
Reference in New Issue
Block a user