mirror of
git://sourceware.org/git/lvm2.git
synced 2025-08-20 21:49:28 +03:00
Compare commits
217 Commits
sourceware
...
origin
Author | SHA1 | Date | |
---|---|---|---|
4d35fe452c | |||
5c5df43ea3 | |||
60eb74a27a | |||
7e9bc77865 | |||
f536c53aee | |||
1dc1a1cedb | |||
531d7c97e7 | |||
23d59c6fc1 | |||
5942fd18db | |||
88b05391ff | |||
c891918174 | |||
ca905681cc | |||
38292ca1d0 | |||
49cd54fc3a | |||
46b735c937 | |||
5f2c942000 | |||
77a7ed065f | |||
9b0aba5fe9 | |||
66760f9673 | |||
09ad36fb9b | |||
c8671f6f79 | |||
164d4a309c | |||
15682270f4 | |||
5d3e870946 | |||
53f5cf0af0 | |||
a11b875074 | |||
d11b8eef89 | |||
52935b5834 | |||
4d2b1a0660 | |||
7b748b7cb8 | |||
0a9b52f7a4 | |||
64d3f05aa1 | |||
825c16e57e | |||
518b814cdb | |||
4a394f410d | |||
bb20fac4ab | |||
ddd5a76801 | |||
bf79fb1a33 | |||
edf5e43f9a | |||
c717011f8e | |||
a9b78d26b1 | |||
21c265adcf | |||
4d0793f0ec | |||
7c52d550e9 | |||
1cfc1be85d | |||
07c24736e0 | |||
46820bfff3 | |||
298d12c459 | |||
f24a1f06b2 | |||
36003df7e3 | |||
dcf038c7a6 | |||
c598e65de9 | |||
861992d874 | |||
2d11fc695e | |||
4184331965 | |||
b8cd0f4808 | |||
8c72878cf2 | |||
acfc82ae29 | |||
375e4bb3da | |||
50441f2433 | |||
f221ba97c9 | |||
fb38426d28 | |||
7ad57d55af | |||
dd2881f277 | |||
2fcbe34fe8 | |||
43388f1220 | |||
a9341b18ef | |||
b17eb054cd | |||
5e6ea4b784 | |||
8c6b8e90e3 | |||
c713745314 | |||
d28a50ec76 | |||
93644be44b | |||
bc3bec6c54 | |||
59e57be54f | |||
1f7ac54bc4 | |||
6a0f597727 | |||
146b2582b0 | |||
97b6486b27 | |||
ee7946ed82 | |||
957e283de8 | |||
075f8e658c | |||
00143753ee | |||
28754145d8 | |||
e06e4d9355 | |||
43d0fbeba2 | |||
92b7c329ee | |||
0c0002d765 | |||
11cfc58976 | |||
e53454d6de | |||
470a1f1c50 | |||
f2d7a48418 | |||
d2aae8cff4 | |||
1ba11aa7ee | |||
0104fd6c66 | |||
af7a11bc57 | |||
66fff1d774 | |||
76f6951c3e | |||
67ddc0c292 | |||
b5c8accdf2 | |||
baa8a9be4a | |||
044f92e466 | |||
8b78982297 | |||
c98868181f | |||
fab088cbc7 | |||
716c345334 | |||
43bcd7393c | |||
aa31272223 | |||
6dfe1ce251 | |||
6b1b66c266 | |||
4b0ae266c2 | |||
413164765f | |||
3d1df10af3 | |||
d250aa7208 | |||
7fbe6ef16b | |||
8daad11666 | |||
90ed3d5e8c | |||
921b496fff | |||
00b8c2bebc | |||
b4e78b26f5 | |||
4d0172ff15 | |||
3d5182c819 | |||
14c7912f45 | |||
a6a2788e7c | |||
7f25fbe154 | |||
11f1556d5d | |||
690f604733 | |||
f48e6b2690 | |||
ed58672029 | |||
3a5561e5ab | |||
aedac100f9 | |||
18bbeec825 | |||
9ed11e9191 | |||
05aceaffbd | |||
f4b30b0dae | |||
43fb4aa69b | |||
872932a0fb | |||
0b019c5406 | |||
ef97360866 | |||
17838e6439 | |||
11589891d7 | |||
b6c4b7cfb0 | |||
c5b6c9ad44 | |||
6dea1ed5ae | |||
e4ef3d04ad | |||
547bdb63e1 | |||
9a50df291a | |||
e7ee89d80b | |||
2a5e24580a | |||
191a2517be | |||
1a0d57f895 | |||
9a62767f2d | |||
5d39927f22 | |||
9b23d9bfe4 | |||
f350283398 | |||
af7c8e7106 | |||
ca859b5149 | |||
d3bcec5993 | |||
910918d1c2 | |||
6360ba3d2d | |||
b7831fc14a | |||
70c1fa3764 | |||
8df3f300ba | |||
b76852bf35 | |||
26ca308ba9 | |||
7b0371e74e | |||
83249f3327 | |||
4c89d3794c | |||
10c3d94159 | |||
157948b5a5 | |||
c25b95e2ef | |||
51dfbf1fb3 | |||
daf1d4cadc | |||
fb42874a4f | |||
48778bc503 | |||
62abae1525 | |||
eb9586bd3b | |||
d6dd700bf7 | |||
7a064303fe | |||
964114950c | |||
1828822bd8 | |||
ce1e5b9991 | |||
80a6de616a | |||
21456dcf7f | |||
89661981e8 | |||
4a14617dc4 | |||
f9d28f1aec | |||
998151e83e | |||
8d0df0c011 | |||
27384c52cf | |||
c41e999488 | |||
4f7631b4ad | |||
5f6bdf707d | |||
84cceaf9b9 | |||
74ba326007 | |||
189fa64793 | |||
3bdc4045c2 | |||
d768fbe010 | |||
76f60cc430 | |||
2574d3257a | |||
64a2fad5d6 | |||
34caf83172 | |||
f79bd30a8b | |||
1784cc990e | |||
2d74de3f05 | |||
34a8d3c2fd | |||
932db3db53 | |||
fe18e5e77a | |||
929cf4b73c | |||
4de0e692db | |||
7d39b4d5e7 | |||
92691e345d | |||
c1865b0a86 | |||
b499d96215 | |||
e2354ea344 | |||
ffe3ca26e0 | |||
3fd3c9430d |
@ -100,7 +100,7 @@ CLEAN_DIRS += autom4te.cache
|
||||
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all
|
||||
$(MAKE) -C test $(@)
|
||||
|
||||
conf.generate: tools
|
||||
conf.generate man.generate: tools
|
||||
|
||||
# how to use parenthesis in makefiles
|
||||
leftparen:=(
|
||||
@ -130,8 +130,9 @@ rpm: dist
|
||||
$(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc
|
||||
rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
|
||||
|
||||
generate: conf.generate
|
||||
generate: conf.generate man.generate
|
||||
$(MAKE) -C conf generate
|
||||
$(MAKE) -C man generate
|
||||
|
||||
all_man:
|
||||
$(MAKE) -C man all_man
|
||||
|
5
README
5
README
@ -6,11 +6,12 @@ Installation instructions are in INSTALL.
|
||||
There is no warranty - see COPYING and COPYING.LIB.
|
||||
|
||||
Tarballs are available from:
|
||||
ftp://sourceware.org/pub/lvm2/
|
||||
ftp://sources.redhat.com/pub/lvm2/
|
||||
|
||||
The source code is stored in git:
|
||||
http://git.fedorahosted.org/git/lvm2.git
|
||||
git clone git://git.fedorahosted.org/git/lvm2.git
|
||||
https://sourceware.org/git/?p=lvm2.git
|
||||
git clone git://sourceware.org/git/lvm2.git
|
||||
|
||||
Mailing list for general discussion related to LVM2:
|
||||
linux-lvm@redhat.com
|
||||
|
11
WHATS_NEW
11
WHATS_NEW
@ -1,5 +1,16 @@
|
||||
Version 2.02.169 -
|
||||
=====================================
|
||||
Lvdisplay [-m] shows more informations for cached volumes.
|
||||
Add option for lvcreate/lvconvert --cachemetadataformat auto|1|2.
|
||||
Support cache segment with configurable metadata format.
|
||||
Add allocation/cache_metadata_format profilable setttings.
|
||||
Use function cache_set_params() for both lvcreate and lvconvert.
|
||||
Skip rounding on cache chunk size boudary when create cache LV.
|
||||
Improve cache_set_params support for chunk_size selection.
|
||||
Fix metadata profile allocation/cache_[mode|policy] setting.
|
||||
Fix missing support for using allocation/cache_pool_chunk_size setting.
|
||||
Upstream git moved to https://sourceware.org/git/?p=lvm2
|
||||
Support conversion of raid type, stripesize and number of disks
|
||||
Reject writemostly/writebehind in lvchange during resynchronization.
|
||||
Deactivate active origin first before removal for improved workflow.
|
||||
Fix regression of accepting options --type and -m with lvresize (2.02.158).
|
||||
|
@ -1,5 +1,9 @@
|
||||
Version 1.02.138 -
|
||||
=====================================
|
||||
Provide dm_tree_node_add_cache_target@base compatible symbol.
|
||||
Support DM_CACHE_FEATURE_METADATA2, new cache metadata format 2.
|
||||
Improve code to handle mode mask for cache nodes.
|
||||
Cache status check for passthrough also require trailing space.
|
||||
Add extra memory page when limiting pthread stack size in dmeventd.
|
||||
Avoids immediate resume when preloaded device is smaller.
|
||||
Do not suppress kernel key description in dmsetup table output.
|
||||
|
@ -9,6 +9,6 @@ allocation {
|
||||
cache_mode = "writethrough"
|
||||
cache_policy = "smq"
|
||||
cache_settings {
|
||||
# currently no settins for "smq" policy
|
||||
# currently no settings for "smq" policy
|
||||
}
|
||||
}
|
||||
|
@ -403,9 +403,20 @@ allocation {
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_mode = "writethrough"
|
||||
|
||||
# Configuration option allocation/cache_metadata_format.
|
||||
# Sets default metadata format for new cache.
|
||||
#
|
||||
# Accepted values:
|
||||
# 0 Automatically detected best available format
|
||||
# 1 Original format
|
||||
# 2 Improved 2nd. generation format
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_metadata_format = 0
|
||||
|
||||
# Configuration option allocation/cache_policy.
|
||||
# The default cache policy used for new cache volume.
|
||||
# Since kernel 4.2 the default policy is smq (Stochastic multique),
|
||||
# Since kernel 4.2 the default policy is smq (Stochastic multiqueue),
|
||||
# otherwise the older mq (Multiqueue) policy is selected.
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
@ -1013,7 +1024,7 @@ global {
|
||||
# Configuration option global/cache_disabled_features.
|
||||
# Features to not use in the cache driver.
|
||||
# This can be helpful for testing, or to avoid using a feature that is
|
||||
# causing problems. Features include: policy_mq, policy_smq.
|
||||
# causing problems. Features include: policy_mq, policy_smq, metadata2.
|
||||
#
|
||||
# Example
|
||||
# cache_disabled_features = [ "policy_smq" ]
|
||||
@ -1277,8 +1288,9 @@ activation {
|
||||
|
||||
# Configuration option activation/raid_region_size.
|
||||
# Size in KiB of each raid or mirror synchronization region.
|
||||
# For raid or mirror segment types, this is the amount of data that is
|
||||
# copied at once when initializing, or moved at once by pvmove.
|
||||
# The clean/dirty state of data is tracked for each region.
|
||||
# The value is rounded down to a power of two if necessary, and
|
||||
# is ignored if it is not a multiple of the machine memory page size.
|
||||
raid_region_size = 512
|
||||
|
||||
# Configuration option activation/error_when_full.
|
||||
|
52
configure
vendored
52
configure
vendored
@ -702,6 +702,7 @@ BLKDEACTIVATE
|
||||
FSADM
|
||||
ELDFLAGS
|
||||
DM_LIB_PATCHLEVEL
|
||||
DMFILEMAPD
|
||||
DMEVENTD_PATH
|
||||
DMEVENTD
|
||||
DL_LIBS
|
||||
@ -737,6 +738,7 @@ CLDNOWHOLEARCHIVE
|
||||
CLDFLAGS
|
||||
CACHE
|
||||
BUILD_NOTIFYDBUS
|
||||
BUILD_DMFILEMAPD
|
||||
BUILD_LOCKDDLM
|
||||
BUILD_LOCKDSANLOCK
|
||||
BUILD_LVMLOCKD
|
||||
@ -960,6 +962,7 @@ enable_use_lvmetad
|
||||
with_lvmetad_pidfile
|
||||
enable_use_lvmpolld
|
||||
with_lvmpolld_pidfile
|
||||
enable_dmfilemapd
|
||||
enable_notify_dbus
|
||||
enable_blkid_wiping
|
||||
enable_udev_systemd_background_jobs
|
||||
@ -1694,6 +1697,7 @@ Optional Features:
|
||||
--disable-use-lvmlockd disable usage of LVM lock daemon
|
||||
--disable-use-lvmetad disable usage of LVM Metadata Daemon
|
||||
--disable-use-lvmpolld disable usage of LVM Poll Daemon
|
||||
--enable-dmfilemapd enable the dmstats filemap daemon
|
||||
--enable-notify-dbus enable LVM notification using dbus
|
||||
--disable-blkid_wiping disable libblkid detection of signatures when wiping
|
||||
and use native code instead
|
||||
@ -12074,6 +12078,32 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build dmfilemapd" >&5
|
||||
$as_echo_n "checking whether to build dmfilemapd... " >&6; }
|
||||
# Check whether --enable-dmfilemapd was given.
|
||||
if test "${enable_dmfilemapd+set}" = set; then :
|
||||
enableval=$enable_dmfilemapd; DMFILEMAPD=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DMFILEMAPD" >&5
|
||||
$as_echo "$DMFILEMAPD" >&6; }
|
||||
BUILD_DMFILEMAPD=$DMFILEMAPD
|
||||
|
||||
$as_echo "#define DMFILEMAPD 1" >>confdefs.h
|
||||
|
||||
|
||||
if test "$DMFILEMAPD" = yes; then
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "linux/fiemap.h" "ac_cv_header_linux_fiemap_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_linux_fiemap_h" = xyes; then :
|
||||
|
||||
else
|
||||
as_fn_error $? "--enable-dmfilemapd requires fiemap.h" "$LINENO" 5
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build notifydbus" >&5
|
||||
$as_echo_n "checking whether to build notifydbus... " >&6; }
|
||||
@ -15123,6 +15153,23 @@ done
|
||||
|
||||
fi
|
||||
|
||||
if test "$DMFILEMAPD" = yes; then
|
||||
for ac_header in sys/inotify.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "sys/inotify.h" "ac_cv_header_sys_inotify_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_sys_inotify_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_SYS_INOTIFY_H 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
hard_bailout
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}modprobe", so it can be a program name with args.
|
||||
@ -15582,11 +15629,13 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
@ -16294,6 +16343,7 @@ do
|
||||
"daemons/dmeventd/plugins/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/mirror/Makefile" ;;
|
||||
"daemons/dmeventd/plugins/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/snapshot/Makefile" ;;
|
||||
"daemons/dmeventd/plugins/thin/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/thin/Makefile" ;;
|
||||
"daemons/dmfilemapd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmfilemapd/Makefile" ;;
|
||||
"daemons/lvmdbusd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/Makefile" ;;
|
||||
"daemons/lvmdbusd/path.py") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/path.py" ;;
|
||||
"daemons/lvmetad/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmetad/Makefile" ;;
|
||||
|
22
configure.in
22
configure.in
@ -1271,6 +1271,21 @@ fi
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMPOLLD, [$DEFAULT_USE_LVMPOLLD],
|
||||
[Use lvmpolld by default.])
|
||||
|
||||
################################################################################
|
||||
dnl -- Check dmfilemapd
|
||||
AC_MSG_CHECKING(whether to build dmfilemapd)
|
||||
AC_ARG_ENABLE(dmfilemapd, AC_HELP_STRING([--enable-dmfilemapd],
|
||||
[enable the dmstats filemap daemon]),
|
||||
DMFILEMAPD=$enableval)
|
||||
AC_MSG_RESULT($DMFILEMAPD)
|
||||
BUILD_DMFILEMAPD=$DMFILEMAPD
|
||||
AC_DEFINE([DMFILEMAPD], 1, [Define to 1 to enable the device-mapper filemap daemon.])
|
||||
|
||||
dnl -- dmfilemapd requires FIEMAP
|
||||
if test "$DMFILEMAPD" = yes; then
|
||||
AC_CHECK_HEADER([linux/fiemap.h], , [AC_MSG_ERROR(--enable-dmfilemapd requires fiemap.h)])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Build notifydbus
|
||||
AC_MSG_CHECKING(whether to build notifydbus)
|
||||
@ -1855,6 +1870,10 @@ if test "$UDEV_SYNC" = yes; then
|
||||
AC_CHECK_HEADERS(sys/ipc.h sys/sem.h,,hard_bailout)
|
||||
fi
|
||||
|
||||
if test "$DMFILEMAPD" = yes; then
|
||||
AC_CHECK_HEADERS([sys/inotify.h],,hard_bailout)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
AC_PATH_TOOL(MODPROBE_CMD, modprobe)
|
||||
|
||||
@ -1994,6 +2013,7 @@ AC_SUBST(BUILD_LVMPOLLD)
|
||||
AC_SUBST(BUILD_LVMLOCKD)
|
||||
AC_SUBST(BUILD_LOCKDSANLOCK)
|
||||
AC_SUBST(BUILD_LOCKDDLM)
|
||||
AC_SUBST(BUILD_DMFILEMAPD)
|
||||
AC_SUBST(BUILD_NOTIFYDBUS)
|
||||
AC_SUBST(CACHE)
|
||||
AC_SUBST(CFLAGS)
|
||||
@ -2043,6 +2063,7 @@ AC_SUBST(DLM_LIBS)
|
||||
AC_SUBST(DL_LIBS)
|
||||
AC_SUBST(DMEVENTD)
|
||||
AC_SUBST(DMEVENTD_PATH)
|
||||
AC_SUBST(DMFILEMAPD)
|
||||
AC_SUBST(DM_LIB_PATCHLEVEL)
|
||||
AC_SUBST(ELDFLAGS)
|
||||
AC_SUBST(FSADM)
|
||||
@ -2158,6 +2179,7 @@ daemons/dmeventd/plugins/raid/Makefile
|
||||
daemons/dmeventd/plugins/mirror/Makefile
|
||||
daemons/dmeventd/plugins/snapshot/Makefile
|
||||
daemons/dmeventd/plugins/thin/Makefile
|
||||
daemons/dmfilemapd/Makefile
|
||||
daemons/lvmdbusd/Makefile
|
||||
daemons/lvmdbusd/path.py
|
||||
daemons/lvmetad/Makefile
|
||||
|
@ -48,8 +48,12 @@ ifeq ("@BUILD_LVMDBUSD@", "yes")
|
||||
SUBDIRS += lvmdbusd
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_DMFILEMAPD@", "yes")
|
||||
SUBDIRS += dmfilemapd
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd
|
||||
SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd dmfilemapd
|
||||
endif
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
@ -111,6 +111,9 @@ static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconv
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dmeventd_lvm2_run_with_lock(cmd_lvscan))
|
||||
log_warn("WARNING: Re-scan of mirrored device %s failed.", device);
|
||||
|
||||
log_info("Repair of mirrored device %s finished successfully.", device);
|
||||
|
||||
return 1;
|
||||
@ -188,7 +191,7 @@ int register_device(const char *device,
|
||||
goto_bad;
|
||||
|
||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
|
||||
"lvconvert --repair --use-policies", device))
|
||||
"lvconvert --config global{use_lvmetad = 0}' --repair --use-policies", device))
|
||||
goto_bad;
|
||||
|
||||
*user = state;
|
||||
|
1
daemons/dmfilemapd/.gitignore
vendored
Normal file
1
daemons/dmfilemapd/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dmfilemapd
|
68
daemons/dmfilemapd/Makefile.in
Normal file
68
daemons/dmfilemapd/Makefile.in
Normal file
@ -0,0 +1,68 @@
|
||||
#
|
||||
# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the device-mapper userspace tools.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU Lesser General Public License v.2.1.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SOURCES = dmfilemapd.c
|
||||
|
||||
TARGETS = dmfilemapd
|
||||
|
||||
.PHONY: install_dmfilemapd install_dmfilemapd_static
|
||||
|
||||
INSTALL_DMFILEMAPD_TARGETS = install_dmfilemapd_dynamic
|
||||
|
||||
CLEAN_TARGETS = dmfilemapd.static
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
CFLOW_TARGET = dmfilemapd
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
all: device-mapper
|
||||
device-mapper: $(TARGETS)
|
||||
|
||||
LIBS += -ldevmapper
|
||||
|
||||
CFLAGS_dmfilemapd.o += $(EXTRA_EXEC_CFLAGS)
|
||||
|
||||
dmfilemapd: $(LIB_SHARED) dmfilemapd.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -L. -o $@ dmfilemapd.o \
|
||||
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
dmfilemapd.static: $(LIB_STATIC) dmfilemapd.o $(interfacebuilddir)/libdevmapper.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
|
||||
dmfilemapd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
|
||||
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
-include $(top_builddir)/libdm/libdevmapper.cflow
|
||||
-include $(top_builddir)/lib/liblvm-internal.cflow
|
||||
-include $(top_builddir)/lib/liblvm2cmd.cflow
|
||||
-include $(top_builddir)/daemons/dmfilemapd/$(LIB_NAME).cflow
|
||||
endif
|
||||
|
||||
install_dmfilemapd_dynamic: dmfilemapd
|
||||
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
||||
install_dmfilemapd_static: dmfilemapd.static
|
||||
$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
|
||||
|
||||
install_dmfilemapd: $(INSTALL_DMEVENTD_TARGETS)
|
||||
|
||||
install: install_dmfilemapd
|
||||
|
||||
install_device-mapper: install_dmfilemapd
|
||||
|
802
daemons/dmfilemapd/dmfilemapd.c
Normal file
802
daemons/dmfilemapd/dmfilemapd.c
Normal file
@ -0,0 +1,802 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* It includes tree drawing code based on pstree: http://psmisc.sourceforge.net/
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "tool.h"
|
||||
|
||||
#include "dm-logging.h"
|
||||
|
||||
#include "defaults.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef __linux__
|
||||
# include "kdev_t.h"
|
||||
#else
|
||||
# define MAJOR(x) major((x))
|
||||
# define MINOR(x) minor((x))
|
||||
# define MKDEV(x,y) makedev((x),(y))
|
||||
#endif
|
||||
|
||||
/* limit to two updates/sec */
|
||||
#define FILEMAPD_WAIT_USECS 500000
|
||||
|
||||
/* how long to wait for unlinked files */
|
||||
#define FILEMAPD_NOFILE_WAIT_USECS 100000
|
||||
#define FILEMAPD_NOFILE_WAIT_TRIES 10
|
||||
|
||||
struct filemap_monitor {
|
||||
dm_filemapd_mode_t mode;
|
||||
const char *program_id;
|
||||
uint64_t group_id;
|
||||
char *path;
|
||||
int fd;
|
||||
|
||||
int inotify_fd;
|
||||
int inotify_watch_fd;
|
||||
|
||||
/* monitoring heuristics */
|
||||
int64_t blocks; /* allocated blocks, from stat.st_blocks */
|
||||
int64_t nr_regions;
|
||||
int deleted;
|
||||
};
|
||||
|
||||
static int _foreground;
|
||||
static int _verbose;
|
||||
|
||||
const char *const _usage = "dmfilemapd <fd> <group_id> <abs_path> <mode> "
|
||||
"[<foreground>[<log_level>]]";
|
||||
|
||||
/*
|
||||
* Daemon logging. By default, all messages are thrown away: messages
|
||||
* are only written to the terminal if the daemon is run in the foreground.
|
||||
*/
|
||||
__attribute__((format(printf, 5, 0)))
|
||||
static void _dmfilemapd_log_line(int level,
|
||||
const char *file __attribute__((unused)),
|
||||
int line __attribute__((unused)),
|
||||
int dm_errno_or_class,
|
||||
const char *f, va_list ap)
|
||||
{
|
||||
static int _abort_on_internal_errors = -1;
|
||||
FILE *out = log_stderr(level) ? stderr : stdout;
|
||||
|
||||
level = log_level(level);
|
||||
|
||||
if (level <= _LOG_WARN || _verbose) {
|
||||
if (level < _LOG_WARN)
|
||||
out = stderr;
|
||||
vfprintf(out, f, ap);
|
||||
fputc('\n', out);
|
||||
}
|
||||
|
||||
if (_abort_on_internal_errors < 0)
|
||||
/* Set when env DM_ABORT_ON_INTERNAL_ERRORS is not "0" */
|
||||
_abort_on_internal_errors =
|
||||
strcmp(getenv("DM_ABORT_ON_INTERNAL_ERRORS") ? : "0", "0");
|
||||
|
||||
if (_abort_on_internal_errors &&
|
||||
!strncmp(f, INTERNAL_ERROR, sizeof(INTERNAL_ERROR) - 1))
|
||||
abort();
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 5, 6)))
|
||||
static void _dmfilemapd_log_with_errno(int level,
|
||||
const char *file, int line,
|
||||
int dm_errno_or_class,
|
||||
const char *f, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, f);
|
||||
_dmfilemapd_log_line(level, file, line, dm_errno_or_class, f, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only used for reporting errors before daemonise().
|
||||
*/
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
static void _early_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputc('\n', stderr);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void _setup_logging(void)
|
||||
{
|
||||
dm_log_init_verbose(_verbose - 1);
|
||||
dm_log_with_errno_init(_dmfilemapd_log_with_errno);
|
||||
}
|
||||
|
||||
#define PROC_FD_DELETED_STR "(deleted)"
|
||||
/*
|
||||
* Scan the /proc/<pid>/fd directory for pid and check for an fd
|
||||
* symlink whose contents match path.
|
||||
*/
|
||||
static int _is_open_in_pid(pid_t pid, const char *path)
|
||||
{
|
||||
char deleted_path[PATH_MAX + sizeof(PROC_FD_DELETED_STR)];
|
||||
struct dirent *pid_dp = NULL;
|
||||
char path_buf[PATH_MAX];
|
||||
char link_buf[PATH_MAX];
|
||||
DIR *pid_d = NULL;
|
||||
ssize_t len;
|
||||
|
||||
if (pid == getpid())
|
||||
return 0;
|
||||
|
||||
if (dm_snprintf(path_buf, sizeof(path_buf),
|
||||
DEFAULT_PROC_DIR "%d/fd", pid) < 0) {
|
||||
log_error("Could not format pid path.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test for the kernel 'file (deleted)' form when scanning.
|
||||
*/
|
||||
if (dm_snprintf(deleted_path, sizeof(deleted_path), "%s %s",
|
||||
path, PROC_FD_DELETED_STR) < 0) {
|
||||
log_error("Could not format check path.");
|
||||
}
|
||||
|
||||
pid_d = opendir(path_buf);
|
||||
if (!pid_d) {
|
||||
log_error("Could not open proc path: %s.", path_buf);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
while ((pid_dp = readdir(pid_d)) != NULL) {
|
||||
if (pid_dp->d_name[0] == '.')
|
||||
continue;
|
||||
if ((len = readlinkat(dirfd(pid_d), pid_dp->d_name, link_buf,
|
||||
sizeof(link_buf))) < 0) {
|
||||
log_error("readlink failed for " DEFAULT_PROC_DIR
|
||||
"/%d/fd/.", pid);
|
||||
goto bad;
|
||||
}
|
||||
link_buf[len] = '\0';
|
||||
if (!strcmp(deleted_path, link_buf)) {
|
||||
closedir(pid_d);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bad:
|
||||
closedir(pid_d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to determine whether a file is open by any process by
|
||||
* scanning symbolic links in /proc/<pid>/fd.
|
||||
*
|
||||
* This is a heuristic since it cannot guarantee to detect brief
|
||||
* access in all cases: a process that opens and then closes the
|
||||
* file rapidly may never be seen by the scan.
|
||||
*
|
||||
* The method will also give false-positives if a process exists
|
||||
* that has a deleted file open that had the same path, but a
|
||||
* different inode number, to the file being monitored.
|
||||
*
|
||||
* For this reason the daemon only uses _is_open() for unlinked
|
||||
* files when the mode is DM_FILEMAPD_FOLLOW_INODE, since these
|
||||
* files can no longer be newly opened by processes.
|
||||
*
|
||||
* In this situation !is_open(path) provides an indication that
|
||||
* the daemon should shut down: the file has been unlinked from
|
||||
* the file system and we appear to hold the final reference.
|
||||
*/
|
||||
static int _is_open(const char *path)
|
||||
{
|
||||
struct dirent *proc_dp = NULL;
|
||||
DIR *proc_d = NULL;
|
||||
pid_t pid;
|
||||
|
||||
proc_d = opendir(DEFAULT_PROC_DIR);
|
||||
if (!proc_d)
|
||||
return 0;
|
||||
while ((proc_dp = readdir(proc_d)) != NULL) {
|
||||
if (!isdigit(proc_dp->d_name[0]))
|
||||
continue;
|
||||
pid = strtol(proc_dp->d_name, NULL, 10);
|
||||
if (!pid)
|
||||
continue;
|
||||
if (_is_open_in_pid(pid, path)) {
|
||||
closedir(proc_d);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
closedir(proc_d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _filemap_monitor_wait(uint64_t usecs)
|
||||
{
|
||||
if (_verbose) {
|
||||
if (usecs == FILEMAPD_WAIT_USECS)
|
||||
log_very_verbose("Waiting for check interval");
|
||||
if (usecs == FILEMAPD_NOFILE_WAIT_USECS)
|
||||
log_very_verbose("Waiting for unlinked path");
|
||||
}
|
||||
usleep((useconds_t) usecs);
|
||||
}
|
||||
|
||||
static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
|
||||
{
|
||||
char *endptr;
|
||||
|
||||
/* we don't care what is in argv[0]. */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc < 5) {
|
||||
_early_log("Wrong number of arguments.");
|
||||
_early_log("usage: %s", _usage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(fm, 0, sizeof(*fm));
|
||||
|
||||
/*
|
||||
* We don't know the true nr_regions at daemon start time,
|
||||
* and it is not worth a dm_stats_list()/group walk to count:
|
||||
* we can assume that there is at least one region or the
|
||||
* daemon would not have been started.
|
||||
*
|
||||
* A correct value will be obtained following the first update
|
||||
* of the group's regions.
|
||||
*/
|
||||
fm->nr_regions = 1;
|
||||
|
||||
/* parse <fd> */
|
||||
fm->fd = strtol(argv[0], &endptr, 10);
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse file descriptor: %s", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
/* parse <group_id> */
|
||||
fm->group_id = strtoull(argv[0], &endptr, 10);
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse group identifier: %s", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
/* parse <path> */
|
||||
if (!argv[0] || !strlen(argv[0])) {
|
||||
_early_log("Path argument is required.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argv[0] != '/') {
|
||||
_early_log("Path argument must specify an absolute path.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fm->path = dm_strdup(argv[0]);
|
||||
if (!fm->path) {
|
||||
_early_log("Could not allocate memory for path argument.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
/* parse <mode> */
|
||||
if (!argv[0] || !strlen(argv[0])) {
|
||||
_early_log("Mode argument is required.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fm->mode = dm_filemapd_mode_from_string(argv[0]);
|
||||
if (fm->mode == DM_FILEMAPD_FOLLOW_NONE)
|
||||
return 0;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
/* parse [<foreground>[<verbose>]] */
|
||||
if (argc) {
|
||||
_foreground = strtol(argv[0], &endptr, 10);
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse debug argument: %s.",
|
||||
argv[0]);
|
||||
return 0;
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
if (argc) {
|
||||
_verbose = strtol(argv[0], &endptr, 10);
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse verbose "
|
||||
"argument: %s", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
if (_verbose < 0 || _verbose > 3) {
|
||||
_early_log("Verbose argument out of range: %d.",
|
||||
_verbose);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _filemap_fd_check_changed(struct filemap_monitor *fm)
|
||||
{
|
||||
int64_t blocks, old_blocks;
|
||||
struct stat buf;
|
||||
|
||||
if (fm->fd < 0) {
|
||||
log_error("Filemap fd is not open.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstat(fm->fd, &buf)) {
|
||||
log_error("Failed to fstat filemap file descriptor.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
blocks = buf.st_blocks;
|
||||
|
||||
/* first check? */
|
||||
if (fm->blocks < 0)
|
||||
old_blocks = buf.st_blocks;
|
||||
else
|
||||
old_blocks = fm->blocks;
|
||||
|
||||
fm->blocks = blocks;
|
||||
|
||||
return (fm->blocks != old_blocks);
|
||||
}
|
||||
|
||||
static void _filemap_monitor_close_fd(struct filemap_monitor *fm)
|
||||
{
|
||||
if (close(fm->fd))
|
||||
log_error("Error closing file descriptor.");
|
||||
fm->fd = -1;
|
||||
}
|
||||
|
||||
static void _filemap_monitor_end_notify(struct filemap_monitor *fm)
|
||||
{
|
||||
inotify_rm_watch(fm->inotify_fd, fm->inotify_watch_fd);
|
||||
}
|
||||
|
||||
static int _filemap_monitor_set_notify(struct filemap_monitor *fm)
|
||||
{
|
||||
int inotify_fd, watch_fd;
|
||||
|
||||
/*
|
||||
* Set IN_NONBLOCK since we do not want to block in event read()
|
||||
* calls. Do not set IN_CLOEXEC as dmfilemapd is single-threaded
|
||||
* and does not fork or exec.
|
||||
*/
|
||||
if ((inotify_fd = inotify_init1(IN_NONBLOCK)) < 0) {
|
||||
_early_log("Failed to initialise inotify.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((watch_fd = inotify_add_watch(inotify_fd, fm->path,
|
||||
IN_MODIFY | IN_DELETE_SELF)) < 0) {
|
||||
_early_log("Failed to add inotify watch.");
|
||||
return 0;
|
||||
}
|
||||
fm->inotify_fd = inotify_fd;
|
||||
fm->inotify_watch_fd = watch_fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _filemap_monitor_reopen_fd(struct filemap_monitor *fm)
|
||||
{
|
||||
int tries = FILEMAPD_NOFILE_WAIT_TRIES;
|
||||
|
||||
/*
|
||||
* In DM_FILEMAPD_FOLLOW_PATH mode, inotify watches must be
|
||||
* re-established whenever the file at the watched path is
|
||||
* changed.
|
||||
*
|
||||
* FIXME: stat file and skip if inode is unchanged.
|
||||
*/
|
||||
if (fm->fd > 0)
|
||||
log_error("Filemap file descriptor already open.");
|
||||
|
||||
while ((fm->fd < 0) && --tries)
|
||||
if (((fm->fd = open(fm->path, O_RDONLY)) < 0) && tries)
|
||||
_filemap_monitor_wait(FILEMAPD_NOFILE_WAIT_USECS);
|
||||
|
||||
if (!tries && (fm->fd < 0)) {
|
||||
log_error("Could not re-open file descriptor.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _filemap_monitor_set_notify(fm);
|
||||
}
|
||||
|
||||
static int _filemap_monitor_get_events(struct filemap_monitor *fm)
|
||||
{
|
||||
/* alignment as per man(7) inotify */
|
||||
char buf[sizeof(struct inotify_event) + NAME_MAX + 1]
|
||||
__attribute__ ((aligned(__alignof__(struct inotify_event))));
|
||||
|
||||
struct inotify_event *event;
|
||||
int check = 0;
|
||||
ssize_t len;
|
||||
char *ptr;
|
||||
|
||||
/*
|
||||
* Close the file descriptor for the file being monitored here
|
||||
* when mode=path: this will allow the inode to be de-allocated,
|
||||
* and an IN_DELETE_SELF event generated in the case that the
|
||||
* daemon is holding the last open reference to the file.
|
||||
*/
|
||||
if (fm->mode == DM_FILEMAPD_FOLLOW_PATH) {
|
||||
_filemap_monitor_end_notify(fm);
|
||||
_filemap_monitor_close_fd(fm);
|
||||
}
|
||||
|
||||
len = read(fm->inotify_fd, (void *) &buf, sizeof(buf));
|
||||
|
||||
/* no events to read? */
|
||||
if (len < 0 && (errno == EAGAIN))
|
||||
goto out;
|
||||
|
||||
/* interrupted by signal? */
|
||||
if (len < 0 && (errno == EINTR))
|
||||
goto out;
|
||||
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
if (!len)
|
||||
goto out;
|
||||
|
||||
for (ptr = buf; ptr < buf + len; ptr += sizeof(*event) + event->len) {
|
||||
event = (struct inotify_event *) ptr;
|
||||
if (event->mask & IN_DELETE_SELF)
|
||||
fm->deleted = 1;
|
||||
if (event->mask & IN_MODIFY)
|
||||
check = 1;
|
||||
/*
|
||||
* Event IN_IGNORED is generated when a file has been deleted
|
||||
* and IN_DELETE_SELF generated, and indicates that the file
|
||||
* watch has been automatically removed.
|
||||
*
|
||||
* This can only happen for the DM_FILEMAPD_FOLLOW_PATH mode,
|
||||
* since inotify IN_DELETE events are generated at the time
|
||||
* the inode is destroyed: DM_FILEMAPD_FOLLOW_INODE will hold
|
||||
* the file descriptor open, meaning that the event will not
|
||||
* be generated until after the daemon closes the file.
|
||||
*
|
||||
* The event is ignored here since inotify monitoring will
|
||||
* be reestablished (or the daemon will terminate) following
|
||||
* deletion of a DM_FILEMAPD_FOLLOW_PATH monitored file.
|
||||
*/
|
||||
if (event->mask & IN_IGNORED)
|
||||
log_very_verbose("Inotify watch removed: IN_IGNORED "
|
||||
"in event->mask");
|
||||
}
|
||||
|
||||
out:
|
||||
/*
|
||||
* Re-open file descriptor if required and log disposition.
|
||||
*/
|
||||
if (fm->mode == DM_FILEMAPD_FOLLOW_PATH)
|
||||
if (!_filemap_monitor_reopen_fd(fm))
|
||||
return -1;
|
||||
|
||||
log_very_verbose("exiting _filemap_monitor_get_events() with "
|
||||
"deleted=%d, check=%d", fm->deleted, check);
|
||||
return check;
|
||||
}
|
||||
|
||||
static void _filemap_monitor_destroy(struct filemap_monitor *fm)
|
||||
{
|
||||
if (fm->fd > 0) {
|
||||
_filemap_monitor_end_notify(fm);
|
||||
_filemap_monitor_close_fd(fm);
|
||||
}
|
||||
dm_free((void *) fm->program_id);
|
||||
}
|
||||
|
||||
static int _filemap_monitor_check_same_file(int fd1, int fd2)
|
||||
{
|
||||
struct stat buf1, buf2;
|
||||
|
||||
if ((fd1 < 0) || (fd2 < 0))
|
||||
return 0;
|
||||
|
||||
if (fstat(fd1, &buf1)) {
|
||||
log_error("Failed to fstat file descriptor %d", fd1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstat(fd2, &buf2)) {
|
||||
log_error("Failed to fstat file descriptor %d", fd2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino));
|
||||
}
|
||||
|
||||
static int _filemap_monitor_check_file_unlinked(struct filemap_monitor *fm)
|
||||
{
|
||||
char path_buf[PATH_MAX];
|
||||
char link_buf[PATH_MAX];
|
||||
int same, fd, len;
|
||||
|
||||
fm->deleted = 0;
|
||||
|
||||
if ((fd = open(fm->path, O_RDONLY)) < 0)
|
||||
goto check_unlinked;
|
||||
|
||||
if ((same = _filemap_monitor_check_same_file(fm->fd, fd)) < 0)
|
||||
return 0;
|
||||
|
||||
if (close(fd))
|
||||
log_error("Error closing fd %d", fd);
|
||||
|
||||
if (same)
|
||||
return 1;
|
||||
|
||||
check_unlinked:
|
||||
/*
|
||||
* The file has been unlinked from its original location: test
|
||||
* whether it is still reachable in the filesystem, or if it is
|
||||
* unlinked and anonymous.
|
||||
*/
|
||||
if (dm_snprintf(path_buf, sizeof(path_buf), DEFAULT_PROC_DIR
|
||||
"/%d/fd/%d", getpid(), fm->fd) < 0) {
|
||||
log_error("Could not format pid path.");
|
||||
return 0;
|
||||
}
|
||||
if ((len = readlink(path_buf, link_buf, sizeof(link_buf))) < 0) {
|
||||
log_error("readlink failed for " DEFAULT_PROC_DIR "/%d/fd/%d.",
|
||||
getpid(), fm->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to re-open the file, from the path now reported in /proc/pid/fd.
|
||||
*/
|
||||
if ((fd = open(link_buf, O_RDONLY)) < 0)
|
||||
fm->deleted = 1;
|
||||
|
||||
if ((same = _filemap_monitor_check_same_file(fm->fd, fd)) < 0)
|
||||
return 0;
|
||||
|
||||
if ((fd > 0) && close(fd))
|
||||
log_error("Error closing fd %d", fd);
|
||||
|
||||
/* Should not happen with normal /proc. */
|
||||
if ((fd > 0) && !same) {
|
||||
log_error("File descriptor mismatch: %d and %s (read from %s) "
|
||||
"are not the same file!", fm->fd, link_buf, path_buf);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _daemonise(struct filemap_monitor *fm)
|
||||
{
|
||||
pid_t pid = 0, sid;
|
||||
int fd;
|
||||
|
||||
if (!(sid = setsid())) {
|
||||
_early_log("setsid failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
_early_log("Failed to fork daemon process.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
if (_verbose)
|
||||
_early_log("Started dmfilemapd with pid=%d", pid);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (chdir("/")) {
|
||||
_early_log("Failed to change directory.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_verbose) {
|
||||
if (close(STDIN_FILENO))
|
||||
_early_log("Error closing stdin");
|
||||
if (close(STDOUT_FILENO))
|
||||
_early_log("Error closing stdout");
|
||||
if (close(STDERR_FILENO))
|
||||
_early_log("Error closing stderr");
|
||||
if ((open("/dev/null", O_RDONLY) < 0) ||
|
||||
(open("/dev/null", O_WRONLY) < 0) ||
|
||||
(open("/dev/null", O_WRONLY) < 0)) {
|
||||
_early_log("Error opening stdio streams.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (fd = sysconf(_SC_OPEN_MAX) - 1; fd > STDERR_FILENO; fd--) {
|
||||
if (fd == fm->fd)
|
||||
continue;
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _update_regions(struct dm_stats *dms, struct filemap_monitor *fm)
|
||||
{
|
||||
uint64_t *regions = NULL, *region, nr_regions = 0;
|
||||
|
||||
regions = dm_stats_update_regions_from_fd(dms, fm->fd, fm->group_id);
|
||||
if (!regions) {
|
||||
log_error("Failed to update filemap regions for group_id="
|
||||
FMTu64 ".", fm->group_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (region = regions; *region != DM_STATS_REGIONS_ALL; region++)
|
||||
nr_regions++;
|
||||
|
||||
if (regions[0] != fm->group_id) {
|
||||
log_warn("group_id changed from " FMTu64 " to " FMTu64,
|
||||
fm->group_id, regions[0]);
|
||||
fm->group_id = regions[0];
|
||||
}
|
||||
|
||||
fm->nr_regions = nr_regions;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _dmfilemapd(struct filemap_monitor *fm)
|
||||
{
|
||||
int running = 1, check = 0, open = 0;
|
||||
const char *program_id;
|
||||
struct dm_stats *dms;
|
||||
|
||||
/*
|
||||
* The correct program_id is retrieved from the group leader
|
||||
* following the call to dm_stats_list().
|
||||
*/
|
||||
dms = dm_stats_create(NULL);
|
||||
|
||||
if (!dm_stats_bind_from_fd(dms, fm->fd)) {
|
||||
log_error("Could not bind dm_stats handle to file descriptor "
|
||||
"%d", fm->fd);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!_filemap_monitor_set_notify(fm))
|
||||
goto bad;
|
||||
|
||||
if (!dm_stats_list(dms, DM_STATS_ALL_PROGRAMS)) {
|
||||
log_error("Failed to list stats handle.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the program_id for new regions (created by calls to
|
||||
* dm_stats_update_regions_from_fd()) from the value used by
|
||||
* the group leader.
|
||||
*/
|
||||
program_id = dm_stats_get_region_program_id(dms, fm->group_id);
|
||||
if (program_id)
|
||||
fm->program_id = dm_strdup(program_id);
|
||||
else
|
||||
fm->program_id = NULL;
|
||||
dm_stats_set_program_id(dms, 1, program_id);
|
||||
|
||||
do {
|
||||
if (!dm_stats_group_present(dms, fm->group_id)) {
|
||||
log_info("Filemap group removed: exiting.");
|
||||
running = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((check = _filemap_monitor_get_events(fm)) < 0)
|
||||
goto bad;
|
||||
|
||||
if (!check)
|
||||
goto wait;
|
||||
|
||||
if ((check = _filemap_fd_check_changed(fm)) < 0)
|
||||
goto bad;
|
||||
|
||||
if (!check)
|
||||
goto wait;
|
||||
|
||||
if (!_update_regions(dms, fm))
|
||||
goto bad;
|
||||
|
||||
wait:
|
||||
_filemap_monitor_wait(FILEMAPD_WAIT_USECS);
|
||||
|
||||
running = !!fm->nr_regions;
|
||||
|
||||
/* mode=inode termination condions */
|
||||
if (fm->mode == DM_FILEMAPD_FOLLOW_INODE) {
|
||||
if (!_filemap_monitor_check_file_unlinked(fm))
|
||||
goto bad;
|
||||
if (fm->deleted && !(open = _is_open(fm->path))) {
|
||||
log_info("File unlinked and closed: exiting.");
|
||||
running = 0;
|
||||
} else if (fm->deleted && open)
|
||||
log_verbose("File unlinked and open: "
|
||||
"continuing.");
|
||||
}
|
||||
|
||||
if (!dm_stats_list(dms, NULL)) {
|
||||
log_error("Failed to list stats handle.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
} while (running);
|
||||
|
||||
_filemap_monitor_destroy(fm);
|
||||
dm_stats_destroy(dms);
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
_filemap_monitor_destroy(fm);
|
||||
dm_stats_destroy(dms);
|
||||
log_error("Exiting");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char * _mode_names[] = {
|
||||
"inode",
|
||||
"path"
|
||||
};
|
||||
|
||||
/*
|
||||
* dmfilemapd <fd> <group_id> <path> <mode> [<foreground>[<log_level>]]
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct filemap_monitor fm;
|
||||
|
||||
if (!_parse_args(argc, argv, &fm))
|
||||
return 1;
|
||||
|
||||
_setup_logging();
|
||||
|
||||
log_info("Starting dmfilemapd with fd=%d, group_id=" FMTu64 " "
|
||||
"mode=%s, path=%s", fm.fd, fm.group_id,
|
||||
_mode_names[fm.mode], fm.path);
|
||||
|
||||
if (!_foreground && !_daemonise(&fm))
|
||||
return 1;
|
||||
|
||||
return _dmfilemapd(&fm);
|
||||
}
|
@ -38,7 +38,7 @@ class AutomatedProperties(dbus.service.Object):
|
||||
props = {}
|
||||
|
||||
for i in self.interface():
|
||||
props[i] = self.GetAll(i)
|
||||
props[i] = AutomatedProperties._get_all_prop(self, i)
|
||||
|
||||
return self._ap_o_path, props
|
||||
|
||||
@ -65,32 +65,53 @@ class AutomatedProperties(dbus.service.Object):
|
||||
|
||||
return self._ap_interface
|
||||
|
||||
# Properties
|
||||
# noinspection PyUnusedLocal
|
||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
||||
in_signature='ss', out_signature='v')
|
||||
def Get(self, interface_name, property_name):
|
||||
value = getattr(self, property_name)
|
||||
@staticmethod
|
||||
def _get_prop(obj, interface_name, property_name):
|
||||
value = getattr(obj, property_name)
|
||||
# Note: If we get an exception in this handler we won't know about it,
|
||||
# only the side effect of no returned value!
|
||||
log_debug('Get (%s), type (%s), value(%s)' %
|
||||
(property_name, str(type(value)), str(value)))
|
||||
return value
|
||||
|
||||
# Properties
|
||||
# noinspection PyUnusedLocal
|
||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
||||
in_signature='s', out_signature='a{sv}')
|
||||
def GetAll(self, interface_name):
|
||||
if interface_name in self.interface(True):
|
||||
in_signature='ss', out_signature='v',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
def Get(self, interface_name, property_name, cb, cbe):
|
||||
# Note: If we get an exception in this handler we won't know about it,
|
||||
# only the side effect of no returned value!
|
||||
r = cfg.create_request_entry(
|
||||
-1, AutomatedProperties._get_prop,
|
||||
(self, interface_name, property_name),
|
||||
cb, cbe, False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _get_all_prop(obj, interface_name):
|
||||
if interface_name in obj.interface(True):
|
||||
# Using introspection, lets build this dynamically
|
||||
properties = get_properties(self)
|
||||
properties = get_properties(obj)
|
||||
if interface_name in properties:
|
||||
return properties[interface_name][1]
|
||||
return {}
|
||||
raise dbus.exceptions.DBusException(
|
||||
self._ap_interface,
|
||||
obj._ap_interface,
|
||||
'The object %s does not implement the %s interface'
|
||||
% (self.__class__, interface_name))
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
||||
in_signature='s', out_signature='a{sv}',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
def GetAll(self, interface_name, cb, cbe):
|
||||
r = cfg.create_request_entry(
|
||||
-1, AutomatedProperties._get_all_prop,
|
||||
(self, interface_name),
|
||||
cb, cbe, False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
||||
in_signature='ssv')
|
||||
def Set(self, interface_name, property_name, new_value):
|
||||
|
@ -84,3 +84,6 @@ db = None
|
||||
|
||||
# lvm flight recorder
|
||||
blackbox = None
|
||||
|
||||
# RequestEntry ctor
|
||||
create_request_entry = None
|
||||
|
@ -16,7 +16,7 @@ import traceback
|
||||
import os
|
||||
|
||||
from lvmdbusd import cfg
|
||||
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error
|
||||
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify
|
||||
from lvmdbusd.lvm_shell_proxy import LVMShellProxy
|
||||
|
||||
try:
|
||||
@ -93,6 +93,7 @@ def call_lvm(command, debug=False):
|
||||
# Prepend the full lvm executable so that we can run different versions
|
||||
# in different locations on the same box
|
||||
command.insert(0, cfg.LVM_CMD)
|
||||
command = add_no_notify(command)
|
||||
|
||||
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
|
||||
env=os.environ)
|
||||
|
@ -29,7 +29,7 @@ except ImportError:
|
||||
|
||||
|
||||
from lvmdbusd.cfg import LVM_CMD
|
||||
from lvmdbusd.utils import log_debug, log_error
|
||||
from lvmdbusd.utils import log_debug, log_error, add_no_notify
|
||||
|
||||
SHELL_PROMPT = "lvm> "
|
||||
|
||||
@ -206,6 +206,8 @@ class LVMShellProxy(object):
|
||||
self.lvm_shell.returncode,
|
||||
"Underlying lvm shell process is not present!")
|
||||
|
||||
argv = add_no_notify(argv)
|
||||
|
||||
# create the command string
|
||||
cmd = " ".join(_quote_arg(arg) for arg in argv)
|
||||
cmd += "\n"
|
||||
|
@ -30,6 +30,7 @@ import argparse
|
||||
import os
|
||||
import sys
|
||||
from .cmdhandler import LvmFlightRecorder
|
||||
from .request import RequestEntry
|
||||
|
||||
|
||||
class Lvm(objectmanager.ObjectManager):
|
||||
@ -97,6 +98,7 @@ def main():
|
||||
os.environ["LC_ALL"] = "C"
|
||||
|
||||
cfg.args = parser.parse_args()
|
||||
cfg.create_request_entry = RequestEntry
|
||||
|
||||
# We create a flight recorder in cmdhandler too, but we replace it here
|
||||
# as the user may be specifying a different size. The default one in
|
||||
@ -144,7 +146,6 @@ def main():
|
||||
thread_list.append(updater.thread)
|
||||
|
||||
cfg.load = updater.load
|
||||
cfg.event = updater.event
|
||||
|
||||
cfg.loop = GLib.MainLoop()
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from utils import log_debug
|
||||
from .automatedproperties import AutomatedProperties
|
||||
|
||||
from . import utils
|
||||
@ -132,11 +132,28 @@ class Manager(AutomatedProperties):
|
||||
r = RequestEntry(-1, Manager._refresh, (), cb, cbe, False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=MANAGER_INTERFACE)
|
||||
def FlightRecorderDump(self):
|
||||
"""
|
||||
Dump the flight recorder to syslog
|
||||
"""
|
||||
cfg.blackbox.dump()
|
||||
|
||||
@staticmethod
|
||||
def _lookup_by_lvm_id(key):
|
||||
p = cfg.om.get_object_path_by_uuid_lvm_id(key, key)
|
||||
if not p:
|
||||
p = '/'
|
||||
log_debug('LookUpByLvmId: key = %s, result = %s' % (key, p))
|
||||
return p
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=MANAGER_INTERFACE,
|
||||
in_signature='s',
|
||||
out_signature='o')
|
||||
def LookUpByLvmId(self, key):
|
||||
out_signature='o',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
def LookUpByLvmId(self, key, cb, cbe):
|
||||
"""
|
||||
Given a lvm id in one of the forms:
|
||||
|
||||
@ -150,10 +167,8 @@ class Manager(AutomatedProperties):
|
||||
:param key: The lookup value
|
||||
:return: Return the object path. If object not found you will get '/'
|
||||
"""
|
||||
p = cfg.om.get_object_path_by_uuid_lvm_id(key, key)
|
||||
if p:
|
||||
return p
|
||||
return '/'
|
||||
r = RequestEntry(-1, Manager._lookup_by_lvm_id, (key,), cb, cbe, False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
@staticmethod
|
||||
def _use_lvm_shell(yes_no):
|
||||
@ -169,16 +184,22 @@ class Manager(AutomatedProperties):
|
||||
:param yes_no:
|
||||
:param cb: dbus python call back parameter, not client visible
|
||||
:param cbe: dbus python error call back parameter, not client visible
|
||||
:return: Nothing
|
||||
:return: Boolean
|
||||
"""
|
||||
r = RequestEntry(-1, Manager._use_lvm_shell, (yes_no,), cb, cbe, False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
@staticmethod
|
||||
def _external_event(command):
|
||||
utils.log_debug("Processing _external_event= %s" % command,
|
||||
'bg_black', 'fg_orange')
|
||||
cfg.load()
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=MANAGER_INTERFACE,
|
||||
in_signature='s', out_signature='i')
|
||||
def ExternalEvent(self, command):
|
||||
|
||||
utils.log_debug("ExternalEvent %s" % command)
|
||||
# If a user didn't explicitly specify udev, we will turn it off now.
|
||||
if not cfg.args.use_udev:
|
||||
if udevwatch.remove():
|
||||
@ -186,8 +207,10 @@ class Manager(AutomatedProperties):
|
||||
"udev monitoring")
|
||||
# We are dependent on external events now to stay current!
|
||||
cfg.ee = True
|
||||
utils.log_debug("ExternalEvent %s" % command)
|
||||
cfg.event()
|
||||
|
||||
r = RequestEntry(
|
||||
-1, Manager._external_event, (command,), None, None, False)
|
||||
cfg.worker_q.put(r)
|
||||
return dbus.Int32(0)
|
||||
|
||||
@staticmethod
|
||||
|
@ -32,14 +32,12 @@ class ObjectManager(AutomatedProperties):
|
||||
self._id_to_object_path = {}
|
||||
self.rlock = threading.RLock()
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface="org.freedesktop.DBus.ObjectManager",
|
||||
out_signature='a{oa{sa{sv}}}')
|
||||
def GetManagedObjects(self):
|
||||
with self.rlock:
|
||||
@staticmethod
|
||||
def _get_managed_objects(obj):
|
||||
with obj.rlock:
|
||||
rc = {}
|
||||
try:
|
||||
for k, v in list(self._objects.items()):
|
||||
for k, v in list(obj._objects.items()):
|
||||
path, props = v[0].emit_data()
|
||||
rc[path] = props
|
||||
except Exception:
|
||||
@ -47,6 +45,14 @@ class ObjectManager(AutomatedProperties):
|
||||
sys.exit(1)
|
||||
return rc
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface="org.freedesktop.DBus.ObjectManager",
|
||||
out_signature='a{oa{sa{sv}}}', async_callbacks=('cb', 'cbe'))
|
||||
def GetManagedObjects(self, cb, cbe):
|
||||
r = cfg.create_request_entry(-1, ObjectManager._get_managed_objects,
|
||||
(self, ), cb, cbe, False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
def locked(self):
|
||||
"""
|
||||
If some external code need to run across a number of different
|
||||
|
@ -10,11 +10,18 @@
|
||||
import pyudev
|
||||
import threading
|
||||
from . import cfg
|
||||
from .request import RequestEntry
|
||||
from . import utils
|
||||
|
||||
observer = None
|
||||
observer_lock = threading.RLock()
|
||||
|
||||
|
||||
def _udev_event():
|
||||
utils.log_debug("Processing udev event")
|
||||
cfg.load()
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
def filter_event(action, device):
|
||||
# Filter for events of interest and add a request object to be processed
|
||||
@ -37,7 +44,10 @@ def filter_event(action, device):
|
||||
refresh = True
|
||||
|
||||
if refresh:
|
||||
cfg.event()
|
||||
# Place this on the queue so any other operations will sequence behind it
|
||||
r = RequestEntry(
|
||||
-1, _udev_event, (), None, None, False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
|
||||
def add():
|
||||
|
@ -499,6 +499,30 @@ def validate_tag(interface, tag):
|
||||
% (tag, _ALLOWABLE_TAG_CH))
|
||||
|
||||
|
||||
def add_no_notify(cmdline):
|
||||
"""
|
||||
Given a command line to execute we will see if `--config` is present, if it
|
||||
is we will add the global/notify_dbus=0 to it, otherwise we will append it
|
||||
to the end of the list.
|
||||
:param: cmdline: The command line to inspect
|
||||
:type: cmdline: list
|
||||
:return: cmdline with notify_dbus config option present
|
||||
:rtype: list
|
||||
"""
|
||||
|
||||
if 'help' in cmdline:
|
||||
return cmdline
|
||||
|
||||
if '--config' in cmdline:
|
||||
for i, arg in enumerate(cmdline):
|
||||
if arg == '--config':
|
||||
cmdline[i] += "global/notify_dbus=0"
|
||||
break
|
||||
else:
|
||||
cmdline.extend(['--config', 'global/notify_dbus=0'])
|
||||
return cmdline
|
||||
|
||||
|
||||
# The methods below which start with mt_* are used to execute the desired code
|
||||
# on the the main thread of execution to alleviate any issues the dbus-python
|
||||
# library with regards to multi-threaded access. Essentially, we are trying to
|
||||
|
@ -127,6 +127,9 @@
|
||||
/* Path to dmeventd pidfile. */
|
||||
#undef DMEVENTD_PIDFILE
|
||||
|
||||
/* Define to 1 to enable the device-mapper filemap daemon. */
|
||||
#undef DMFILEMAPD
|
||||
|
||||
/* Define to enable compat protocol */
|
||||
#undef DM_COMPAT
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -272,10 +272,18 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
|
||||
{
|
||||
return 0;
|
||||
@ -984,6 +992,30 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
|
||||
return lv_mirror_percent(lv->vg->cmd, lv, 0, percent, NULL);
|
||||
}
|
||||
|
||||
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
struct dm_status_raid *status;
|
||||
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking raid data offset and dev sectors for LV %s/%s",
|
||||
lv->vg->name, lv->name);
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_raid_status(dm, lv, &status)))
|
||||
stack;
|
||||
|
||||
*data_offset = status->data_offset;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
||||
{
|
||||
int r;
|
||||
@ -1013,6 +1045,32 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
struct dm_status_raid *status;
|
||||
|
||||
*dev_cnt = 0;
|
||||
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking raid device count for LV %s/%s",
|
||||
lv->vg->name, lv->name);
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!dev_manager_raid_status(dm, lv, &status)) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
}
|
||||
*dev_cnt = status->dev_count;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
|
@ -168,6 +168,8 @@ int lv_snapshot_percent(const struct logical_volume *lv, dm_percent_t *percent);
|
||||
int lv_mirror_percent(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
int wait, dm_percent_t *percent, uint32_t *event_nr);
|
||||
int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent);
|
||||
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt);
|
||||
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset);
|
||||
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
|
||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
|
||||
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -214,6 +214,14 @@ typedef enum {
|
||||
STATUS, /* DM_DEVICE_STATUS ioctl */
|
||||
} info_type_t;
|
||||
|
||||
/* Return length of segment depending on type and reshape_len */
|
||||
static uint32_t _seg_len(const struct lv_segment *seg)
|
||||
{
|
||||
uint32_t reshape_len = seg_is_raid(seg) ? ((seg->area_count - seg->segtype->parity_devs) * seg->reshape_len) : 0;
|
||||
|
||||
return seg->len - reshape_len;
|
||||
}
|
||||
|
||||
static int _info_run(const char *dlid, struct dm_info *dminfo,
|
||||
uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status,
|
||||
@ -250,7 +258,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
|
||||
if (seg_status && dminfo->exists) {
|
||||
start = length = seg_status->seg->lv->vg->extent_size;
|
||||
start *= seg_status->seg->le;
|
||||
length *= seg_status->seg->len;
|
||||
length *= _seg_len(seg_status->seg);
|
||||
|
||||
do {
|
||||
target = dm_get_next_target(dmt, target, &target_start,
|
||||
@ -1308,14 +1316,13 @@ int dev_manager_raid_message(struct dev_manager *dm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* These are the supported RAID messages for dm-raid v1.5.0 */
|
||||
/* These are the supported RAID messages for dm-raid v1.9.0 */
|
||||
if (strcmp(msg, "idle") &&
|
||||
strcmp(msg, "frozen") &&
|
||||
strcmp(msg, "resync") &&
|
||||
strcmp(msg, "recover") &&
|
||||
strcmp(msg, "check") &&
|
||||
strcmp(msg, "repair") &&
|
||||
strcmp(msg, "reshape")) {
|
||||
strcmp(msg, "repair")) {
|
||||
log_error(INTERNAL_ERROR "Unknown RAID message: %s.", msg);
|
||||
return 0;
|
||||
}
|
||||
@ -2214,7 +2221,7 @@ static char *_add_error_or_zero_device(struct dev_manager *dm, struct dm_tree *d
|
||||
struct lv_segment *seg_i;
|
||||
struct dm_info info;
|
||||
int segno = -1, i = 0;
|
||||
uint64_t size = (uint64_t) seg->len * seg->lv->vg->extent_size;
|
||||
uint64_t size = (uint64_t) _seg_len(seg) * seg->lv->vg->extent_size;
|
||||
|
||||
dm_list_iterate_items(seg_i, &seg->lv->segments) {
|
||||
if (seg == seg_i) {
|
||||
@ -2500,7 +2507,7 @@ static int _add_target_to_dtree(struct dev_manager *dm,
|
||||
return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
|
||||
&dm->target_state, seg,
|
||||
laopts, dnode,
|
||||
extent_size * seg->len,
|
||||
extent_size * _seg_len(seg),
|
||||
&dm->pvmove_mirror_count);
|
||||
}
|
||||
|
||||
@ -2693,7 +2700,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
/* Replace target and all its used devs with error mapping */
|
||||
log_debug_activation("Using error for pending delete %s.",
|
||||
display_lvname(seg->lv));
|
||||
if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * seg->len))
|
||||
if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * _seg_len(seg)))
|
||||
return_0;
|
||||
} else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
|
||||
return_0;
|
||||
@ -3165,7 +3172,6 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
log_error(INTERNAL_ERROR "_tree_action: Action %u not supported.", action);
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
|
2
lib/cache/lvmetad.c
vendored
2
lib/cache/lvmetad.c
vendored
@ -1304,7 +1304,7 @@ int lvmetad_vg_remove_pending(struct volume_group *vg)
|
||||
reply = _lvmetad_send(vg->cmd, "set_vg_info",
|
||||
"name = %s", vg->name,
|
||||
"uuid = %s", uuid,
|
||||
"version = %d", 0,
|
||||
"version = %"PRId64, (int64_t)0,
|
||||
NULL);
|
||||
|
||||
if (!_lvmetad_handle_reply(reply, "set_vg_info", vg->name, NULL)) {
|
||||
|
@ -36,6 +36,31 @@ static unsigned _feature_mask;
|
||||
log_error(t " segment %s of logical volume %s.", ## p, \
|
||||
dm_config_parent_name(sn), seg->lv->name), 0;
|
||||
|
||||
static int _cache_out_line(const char *line, void *_f)
|
||||
{
|
||||
log_print(" Setting\t\t%s", line);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _cache_display(const struct lv_segment *seg)
|
||||
{
|
||||
const struct dm_config_node *n;
|
||||
const struct lv_segment *pool_seg =
|
||||
seg_is_cache_pool(seg) ? seg : first_seg(seg->pool_lv);
|
||||
|
||||
log_print(" Chunk size\t\t%s",
|
||||
display_size(seg->lv->vg->cmd, pool_seg->chunk_size));
|
||||
log_print(" Metadata format\t%u", pool_seg->cache_metadata_format);
|
||||
log_print(" Mode\t\t%s", get_cache_mode_name(pool_seg));
|
||||
log_print(" Policy\t\t%s", pool_seg->policy_name);
|
||||
|
||||
if ((n = pool_seg->policy_settings->child))
|
||||
dm_config_write_node(n, _cache_out_line, NULL);
|
||||
|
||||
log_print(" ");
|
||||
}
|
||||
|
||||
/*
|
||||
* When older metadata are loaded without newer settings,
|
||||
* set then to default settings (the one that could have been
|
||||
@ -52,7 +77,13 @@ static void _fix_missing_defaults(struct lv_segment *cpool_seg)
|
||||
cpool_seg->policy_name);
|
||||
}
|
||||
|
||||
if (cpool_seg->cache_mode == CACHE_MODE_UNDEFINED) {
|
||||
if (cpool_seg->cache_metadata_format == CACHE_METADATA_FORMAT_UNSELECTED) {
|
||||
cpool_seg->cache_metadata_format = CACHE_METADATA_FORMAT_1;
|
||||
log_verbose("Cache pool %s uses implicit metadata format %u.",
|
||||
display_lvname(cpool_seg->lv), cpool_seg->cache_metadata_format);
|
||||
}
|
||||
|
||||
if (cpool_seg->cache_mode == CACHE_MODE_UNSELECTED) {
|
||||
cpool_seg->cache_mode = CACHE_MODE_WHEN_MISSING;
|
||||
log_verbose("Cache pool %s is missing cache mode, using %s.",
|
||||
display_lvname(cpool_seg->lv),
|
||||
@ -107,6 +138,16 @@ static int _cache_pool_text_import(struct lv_segment *seg,
|
||||
return SEG_LOG_ERROR("Failed to duplicate policy in");
|
||||
}
|
||||
|
||||
if (dm_config_has_node(sn, "metadata_format")) {
|
||||
if (!dm_config_get_uint32(sn, "metadata_format", &seg->cache_metadata_format) ||
|
||||
((seg->cache_metadata_format != CACHE_METADATA_FORMAT_1) &&
|
||||
(seg->cache_metadata_format != CACHE_METADATA_FORMAT_2)))
|
||||
return SEG_LOG_ERROR("Unknown cache metadata format %u number in",
|
||||
seg->cache_metadata_format);
|
||||
if (seg->cache_metadata_format == CACHE_METADATA_FORMAT_2)
|
||||
seg->lv->status |= LV_METADATA_FORMAT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in policy args:
|
||||
* policy_settings {
|
||||
@ -164,12 +205,31 @@ static int _cache_pool_text_export(const struct lv_segment *seg,
|
||||
outf(f, "metadata = \"%s\"", seg->metadata_lv->name);
|
||||
outf(f, "chunk_size = %" PRIu32, seg->chunk_size);
|
||||
|
||||
switch (seg->cache_metadata_format) {
|
||||
case CACHE_METADATA_FORMAT_UNSELECTED:
|
||||
/* Unselected format is not printed */
|
||||
break;
|
||||
case CACHE_METADATA_FORMAT_1:
|
||||
/* If format 1 was already specified with cache pool, store it,
|
||||
* otherwise format gets stored when LV is cached.
|
||||
* NB: format 1 could be lost anytime, it's a default format.
|
||||
* Older lvm2 tool can easily drop it.
|
||||
*/
|
||||
case CACHE_METADATA_FORMAT_2: /* more in future ? */
|
||||
outf(f, "metadata_format = " FMTu32, seg->cache_metadata_format);
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "LV %s is using unknown cache metadada format %u.",
|
||||
display_lvname(seg->lv), seg->cache_metadata_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache pool used by a cache LV holds data. Not ideal,
|
||||
* but not worth to break backward compatibility, by shifting
|
||||
* content to cache segment
|
||||
*/
|
||||
if (seg->cache_mode != CACHE_MODE_UNDEFINED) {
|
||||
if (seg->cache_mode != CACHE_MODE_UNSELECTED) {
|
||||
if (!(cache_mode = get_cache_mode_name(seg)))
|
||||
return_0;
|
||||
outf(f, "cache_mode = \"%s\"", cache_mode);
|
||||
@ -213,6 +273,7 @@ static int _target_present(struct cmd_context *cmd,
|
||||
const char *aliasing;
|
||||
} _features[] = {
|
||||
/* Assumption: cache >=1.9 always aliases MQ policy */
|
||||
{ 1, 10, CACHE_FEATURE_METADATA2, 0, "metadata2" },
|
||||
{ 1, 9, CACHE_FEATURE_POLICY_SMQ, CACHE_FEATURE_POLICY_MQ, "policy_smq", "cache-smq",
|
||||
" and aliases cache-mq" },
|
||||
{ 1, 8, CACHE_FEATURE_POLICY_SMQ, 0, "policy_smq", "cache-smq" },
|
||||
@ -250,6 +311,16 @@ static int _target_present(struct cmd_context *cmd,
|
||||
for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) {
|
||||
if (_attrs & _features[i].cache_feature)
|
||||
continue; /* already present */
|
||||
|
||||
if (!_features[i].module[0]) {
|
||||
if ((maj > _features[i].maj) ||
|
||||
(maj == _features[i].maj && min >= _features[i].min)) {
|
||||
log_debug_activation("Cache supports %s.",
|
||||
_features[i].feature);
|
||||
_attrs |= _features[i].cache_feature;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (((maj > _features[i].maj) ||
|
||||
(maj == _features[i].maj && min >= _features[i].min)) &&
|
||||
module_present(cmd, _features[i].module)) {
|
||||
@ -310,6 +381,7 @@ static int _modules_needed(struct dm_pool *mem,
|
||||
#endif /* DEVMAPPER_SUPPORT */
|
||||
|
||||
static struct segtype_handler _cache_pool_ops = {
|
||||
.display = _cache_display,
|
||||
.text_import = _cache_pool_text_import,
|
||||
.text_import_area_count = _cache_pool_text_import_area_count,
|
||||
.text_export = _cache_pool_text_export,
|
||||
@ -399,6 +471,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
|
||||
struct lv_segment *cache_pool_seg;
|
||||
char *metadata_uuid, *data_uuid, *origin_uuid;
|
||||
uint64_t feature_flags = 0;
|
||||
unsigned attr;
|
||||
|
||||
if (!seg->pool_lv || !seg_is_cache(seg)) {
|
||||
log_error(INTERNAL_ERROR "Passed segment is not cache.");
|
||||
@ -426,6 +499,26 @@ static int _cache_add_target_line(struct dev_manager *dm,
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cache_pool_seg->cache_metadata_format) {
|
||||
case CACHE_METADATA_FORMAT_1: break;
|
||||
case CACHE_METADATA_FORMAT_2:
|
||||
if (!_target_present(cmd, NULL, &attr))
|
||||
return_0;
|
||||
|
||||
if (!(attr & CACHE_FEATURE_METADATA2)) {
|
||||
log_error("LV %s has metadata format %u unsuported by kernel.",
|
||||
display_lvname(seg->lv), cache_pool_seg->cache_metadata_format);
|
||||
return 0;
|
||||
}
|
||||
feature_flags |= DM_CACHE_FEATURE_METADATA2;
|
||||
log_debug_activation("Using metadata2 format for %s.", display_lvname(seg->lv));
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "LV %s has unknown metadata format %u.",
|
||||
display_lvname(seg->lv), cache_pool_seg->cache_metadata_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL)))
|
||||
return_0;
|
||||
|
||||
@ -452,6 +545,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
|
||||
#endif /* DEVMAPPER_SUPPORT */
|
||||
|
||||
static struct segtype_handler _cache_ops = {
|
||||
.display = _cache_display,
|
||||
.text_import = _cache_text_import,
|
||||
.text_import_area_count = _cache_text_import_area_count,
|
||||
.text_export = _cache_text_export,
|
||||
|
@ -2442,21 +2442,13 @@ const char *get_default_activation_mirror_image_fault_policy_CFG(struct cmd_cont
|
||||
|
||||
int get_default_allocation_thin_pool_chunk_size_CFG(struct cmd_context *cmd, struct profile *profile)
|
||||
{
|
||||
const char *str;
|
||||
uint32_t chunk_size;
|
||||
int chunk_size_calc_method;
|
||||
|
||||
if (!(str = find_config_tree_str(cmd, allocation_thin_pool_chunk_size_policy_CFG, profile))) {
|
||||
log_error(INTERNAL_ERROR "Cannot find configuration.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcasecmp(str, "generic"))
|
||||
if (!get_default_allocation_thin_pool_chunk_size(cmd, profile, &chunk_size,
|
||||
&chunk_size_calc_method)) {
|
||||
stack; /* Ignore this error, never happens... */
|
||||
chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2;
|
||||
else if (!strcasecmp(str, "performance"))
|
||||
chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE * 2;
|
||||
else {
|
||||
log_error("Thin pool chunk size calculation policy \"%s\" is unrecognised.", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) chunk_size;
|
||||
|
@ -473,14 +473,23 @@ cfg(allocation_raid_stripe_all_devices_CFG, "raid_stripe_all_devices", allocatio
|
||||
"when the command does not specify the number of stripes to use.\n"
|
||||
"This was the default behaviour until release 2.02.162.\n")
|
||||
|
||||
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
|
||||
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
|
||||
"Cache pool metadata and data will always use different PVs.\n")
|
||||
|
||||
cfg(allocation_cache_pool_cachemode_CFG, "cache_pool_cachemode", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 113), NULL, vsn(2, 2, 128),
|
||||
cfg(allocation_cache_pool_cachemode_CFG, "cache_pool_cachemode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 113), NULL, vsn(2, 2, 128),
|
||||
"This has been replaced by the allocation/cache_mode setting.\n",
|
||||
"Cache mode.\n")
|
||||
|
||||
cfg(allocation_cache_mode_CFG, "cache_mode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 128), NULL, 0, NULL,
|
||||
cfg(allocation_cache_metadata_format_CFG, "cache_metadata_format", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_CACHE_METADATA_FORMAT, vsn(2, 2, 169), NULL, 0, NULL,
|
||||
"Sets default metadata format for new cache.\n"
|
||||
"#\n"
|
||||
"Accepted values:\n"
|
||||
" 0 Automatically detected best available format\n"
|
||||
" 1 Original format\n"
|
||||
" 2 Improved 2nd. generation format\n"
|
||||
"#\n")
|
||||
|
||||
cfg(allocation_cache_mode_CFG, "cache_mode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 128), NULL, 0, NULL,
|
||||
"The default cache mode used for new cache.\n"
|
||||
"#\n"
|
||||
"Accepted values:\n"
|
||||
@ -492,20 +501,20 @@ cfg(allocation_cache_mode_CFG, "cache_mode", allocation_CFG_SECTION, CFG_PROFILA
|
||||
"#\n"
|
||||
"This setting replaces allocation/cache_pool_cachemode.\n")
|
||||
|
||||
cfg(allocation_cache_policy_CFG, "cache_policy", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, 0, vsn(2, 2, 128), NULL, 0, NULL,
|
||||
cfg(allocation_cache_policy_CFG, "cache_policy", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, 0, vsn(2, 2, 128), NULL, 0, NULL,
|
||||
"The default cache policy used for new cache volume.\n"
|
||||
"Since kernel 4.2 the default policy is smq (Stochastic multique),\n"
|
||||
"Since kernel 4.2 the default policy is smq (Stochastic multiqueue),\n"
|
||||
"otherwise the older mq (Multiqueue) policy is selected.\n")
|
||||
|
||||
cfg_section(allocation_cache_settings_CFG_SECTION, "cache_settings", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, vsn(2, 2, 128), 0, NULL,
|
||||
cfg_section(allocation_cache_settings_CFG_SECTION, "cache_settings", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, vsn(2, 2, 128), 0, NULL,
|
||||
"Settings for the cache policy.\n"
|
||||
"See documentation for individual cache policies for more info.\n")
|
||||
|
||||
cfg_section(policy_settings_CFG_SUBSECTION, "policy_settings", allocation_cache_settings_CFG_SECTION, CFG_NAME_VARIABLE | CFG_SECTION_NO_CHECK | CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, vsn(2, 2, 128), 0, NULL,
|
||||
cfg_section(policy_settings_CFG_SUBSECTION, "policy_settings", allocation_cache_settings_CFG_SECTION, CFG_NAME_VARIABLE | CFG_SECTION_NO_CHECK | CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, vsn(2, 2, 128), 0, NULL,
|
||||
"Replace this subsection name with a policy name.\n"
|
||||
"Multiple subsections for different policies can be created.\n")
|
||||
|
||||
cfg_runtime(allocation_cache_pool_chunk_size_CFG, "cache_pool_chunk_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(2, 2, 106), 0, NULL,
|
||||
cfg_runtime(allocation_cache_pool_chunk_size_CFG, "cache_pool_chunk_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(2, 2, 106), 0, NULL,
|
||||
"The minimal chunk size in KiB for cache pool volumes.\n"
|
||||
"Using a chunk_size that is too large can result in wasteful use of\n"
|
||||
"the cache, where small reads and writes can cause large sections of\n"
|
||||
@ -516,7 +525,7 @@ cfg_runtime(allocation_cache_pool_chunk_size_CFG, "cache_pool_chunk_size", alloc
|
||||
"on the smaller end of the spectrum. Supported values range from\n"
|
||||
"32KiB to 1GiB in multiples of 32.\n")
|
||||
|
||||
cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, 0, vsn(2, 2, 165), NULL, 0, NULL,
|
||||
cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, 0, vsn(2, 2, 165), NULL, 0, NULL,
|
||||
"The maximum number of chunks in a cache pool.\n"
|
||||
"For cache target v1.9 the recommended maximumm is 1000000 chunks.\n"
|
||||
"Using cache pool with more chunks may degrade cache performance.\n")
|
||||
@ -992,7 +1001,7 @@ cfg_array(global_thin_disabled_features_CFG, "thin_disabled_features", global_CF
|
||||
cfg_array(global_cache_disabled_features_CFG, "cache_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 128), NULL, 0, NULL,
|
||||
"Features to not use in the cache driver.\n"
|
||||
"This can be helpful for testing, or to avoid using a feature that is\n"
|
||||
"causing problems. Features include: policy_mq, policy_smq.\n"
|
||||
"causing problems. Features include: policy_mq, policy_smq, metadata2.\n"
|
||||
"#\n"
|
||||
"Example\n"
|
||||
"cache_disabled_features = [ \"policy_smq\" ]\n"
|
||||
|
@ -71,7 +71,7 @@
|
||||
* FIXME: Increase these to 64 and further to the MD maximum
|
||||
* once the SubLVs split and name shift got enhanced
|
||||
*/
|
||||
#define DEFAULT_RAID1_MAX_IMAGES 10
|
||||
#define DEFAULT_RAID1_MAX_IMAGES 64
|
||||
#define DEFAULT_RAID_MAX_IMAGES 64
|
||||
#define DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES 0 /* Don't stripe across all devices if not -i/--stripes given */
|
||||
|
||||
@ -132,6 +132,7 @@
|
||||
#define DEFAULT_CACHE_POOL_MIN_METADATA_SIZE 2048 /* KB */
|
||||
#define DEFAULT_CACHE_POOL_MAX_METADATA_SIZE (16 * 1024 * 1024) /* KB */
|
||||
#define DEFAULT_CACHE_POLICY "mq"
|
||||
#define DEFAULT_CACHE_METADATA_FORMAT CACHE_METADATA_FORMAT_UNSELECTED /* Autodetect */
|
||||
#define DEFAULT_CACHE_MODE "writethrough"
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
@ -386,6 +386,7 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
dm_percent_t thin_data_percent, thin_metadata_percent;
|
||||
int thin_active = 0;
|
||||
dm_percent_t thin_percent;
|
||||
struct lv_status_cache *cache_status = NULL;
|
||||
|
||||
if (lv_is_historical(lv))
|
||||
return _lvdisplay_historical_full(cmd, lv);
|
||||
@ -491,6 +492,19 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
seg = first_seg(lv);
|
||||
log_print("LV Pool metadata %s", seg->metadata_lv->name);
|
||||
log_print("LV Pool data %s", seg_lv(seg, 0)->name);
|
||||
} else if (lv_is_cache_origin(lv)) {
|
||||
log_print("LV origin of Cache LV %s",
|
||||
get_only_segment_using_this_lv(lv)->lv->name);
|
||||
} else if (lv_is_cache(lv)) {
|
||||
seg = first_seg(lv);
|
||||
if (inkernel && !lv_cache_status(lv, &cache_status))
|
||||
return_0;
|
||||
log_print("LV Cache pool name %s", seg->pool_lv->name);
|
||||
log_print("LV Cache origin name %s", seg_lv(seg, 0)->name);
|
||||
} else if (lv_is_cache_pool(lv)) {
|
||||
seg = first_seg(lv);
|
||||
log_print("LV Pool metadata %s", seg->metadata_lv->name);
|
||||
log_print("LV Pool data %s", seg_lv(seg, 0)->name);
|
||||
}
|
||||
|
||||
if (inkernel && info.suspended)
|
||||
@ -510,6 +524,27 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
display_size(cmd,
|
||||
snap_seg ? snap_seg->origin->size : lv->size));
|
||||
|
||||
if (cache_status) {
|
||||
log_print("Cache used blocks %.2f%%",
|
||||
dm_percent_to_float(cache_status->data_usage));
|
||||
log_print("Cache metadata blocks %.2f%%",
|
||||
dm_percent_to_float(cache_status->metadata_usage));
|
||||
log_print("Cache dirty blocks %.2f%%",
|
||||
dm_percent_to_float(cache_status->dirty_usage));
|
||||
log_print("Cache read hits/misses " FMTu64 " / " FMTu64,
|
||||
cache_status->cache->read_hits,
|
||||
cache_status->cache->read_misses);
|
||||
log_print("Cache wrt hits/misses " FMTu64 " / " FMTu64,
|
||||
cache_status->cache->write_hits,
|
||||
cache_status->cache->write_misses);
|
||||
log_print("Cache demotions " FMTu64,
|
||||
cache_status->cache->demotions);
|
||||
log_print("Cache promotions " FMTu64,
|
||||
cache_status->cache->promotions);
|
||||
|
||||
dm_pool_destroy(cache_status->mem);
|
||||
}
|
||||
|
||||
if (thin_data_active)
|
||||
log_print("Allocated pool data %.2f%%",
|
||||
dm_percent_to_float(thin_data_percent));
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -225,8 +225,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
while (le < lvm->lv->le_count) {
|
||||
len = _area_length(lvm, le);
|
||||
|
||||
if (!(seg = alloc_lv_segment(segtype, lvm->lv, le, len, 0, 0,
|
||||
NULL, 1, len, 0, 0, 0, NULL))) {
|
||||
if (!(seg = alloc_lv_segment(segtype, lvm->lv, le, len, 0, 0, 0,
|
||||
NULL, 1, len, 0, 0, 0, 0, NULL))) {
|
||||
log_error("Failed to allocate linear segment.");
|
||||
return 0;
|
||||
}
|
||||
@ -297,10 +297,10 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
|
||||
if (!(seg = alloc_lv_segment(segtype, lvm->lv,
|
||||
lvm->stripes * first_area_le,
|
||||
lvm->stripes * area_len,
|
||||
lvm->stripes * area_len, 0,
|
||||
0, lvm->stripe_size, NULL,
|
||||
lvm->stripes,
|
||||
area_len, 0, 0, 0, NULL))) {
|
||||
area_len, 0, 0, 0, 0, NULL))) {
|
||||
log_error("Failed to allocate striped segment.");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -192,9 +192,9 @@ static int _add_stripe_seg(struct dm_pool *mem,
|
||||
return_0;
|
||||
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
|
||||
area_len * usp->num_devs, 0,
|
||||
area_len * usp->num_devs, 0, 0,
|
||||
usp->striping, NULL, usp->num_devs,
|
||||
area_len, 0, 0, 0, NULL))) {
|
||||
area_len, 0, 0, 0, 0, NULL))) {
|
||||
log_error("Unable to allocate striped lv_segment structure");
|
||||
return 0;
|
||||
}
|
||||
@ -232,8 +232,8 @@ static int _add_linear_seg(struct dm_pool *mem,
|
||||
area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
||||
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
|
||||
area_len, 0, usp->striping,
|
||||
NULL, 1, area_len,
|
||||
area_len, 0, 0, usp->striping,
|
||||
NULL, 1, area_len, 0,
|
||||
POOL_PE_SIZE, 0, 0, NULL))) {
|
||||
log_error("Unable to allocate linear lv_segment "
|
||||
"structure");
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -583,8 +583,10 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
|
||||
outf(f, "start_extent = %u", seg->le);
|
||||
outsize(f, (uint64_t) seg->len * vg->extent_size,
|
||||
"extent_count = %u", seg->len);
|
||||
|
||||
outnl(f);
|
||||
if (seg->reshape_len)
|
||||
outsize(f, (uint64_t) seg->reshape_len * vg->extent_size,
|
||||
"reshape_count = %u", seg->reshape_len);
|
||||
outf(f, "type = \"%s\"", seg->segtype->name);
|
||||
|
||||
if (!_out_list(f, &seg->tags, "tags"))
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -61,9 +61,13 @@ static const struct flag _lv_flags[] = {
|
||||
{LOCKED, "LOCKED", STATUS_FLAG},
|
||||
{LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
|
||||
{LV_REBUILD, "REBUILD", STATUS_FLAG},
|
||||
{LV_RESHAPE_DELTA_DISKS_PLUS, "RESHAPE_DELTA_DISKS_PLUS", STATUS_FLAG},
|
||||
{LV_RESHAPE_DELTA_DISKS_MINUS, "RESHAPE_DELTA_DISKS_MINUS", STATUS_FLAG},
|
||||
{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", STATUS_FLAG},
|
||||
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
|
||||
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
|
||||
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
|
||||
{LV_METADATA_FORMAT, "METADATA_FORMAT", STATUS_FLAG},
|
||||
{LV_NOSCAN, NULL, 0},
|
||||
{LV_TEMPORARY, NULL, 0},
|
||||
{POOL_METADATA_SPARE, NULL, 0},
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -354,7 +354,7 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
||||
struct lv_segment *seg;
|
||||
const struct dm_config_node *sn_child = sn->child;
|
||||
const struct dm_config_value *cv;
|
||||
uint32_t start_extent, extent_count;
|
||||
uint32_t area_extents, start_extent, extent_count, reshape_count, data_copies;
|
||||
struct segment_type *segtype;
|
||||
const char *segtype_str;
|
||||
|
||||
@ -375,6 +375,12 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_read_int32(sn_child, "reshape_count", &reshape_count))
|
||||
reshape_count = 0;
|
||||
|
||||
if (!_read_int32(sn_child, "data_copies", &data_copies))
|
||||
data_copies = 1;
|
||||
|
||||
segtype_str = SEG_TYPE_NAME_STRIPED;
|
||||
|
||||
if (!dm_config_get_str(sn_child, "type", &segtype_str)) {
|
||||
@ -389,9 +395,11 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
||||
!segtype->ops->text_import_area_count(sn_child, &area_count))
|
||||
return_0;
|
||||
|
||||
area_extents = segtype->parity_devs ?
|
||||
raid_rimage_extents(segtype, extent_count, area_count - segtype->parity_devs, data_copies) : extent_count;
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, start_extent,
|
||||
extent_count, 0, 0, NULL, area_count,
|
||||
extent_count, 0, 0, 0, NULL))) {
|
||||
extent_count, reshape_count, 0, 0, NULL, area_count,
|
||||
area_extents, data_copies, 0, 0, 0, NULL))) {
|
||||
log_error("Segment allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ const char *display_cache_mode(const struct lv_segment *seg)
|
||||
seg = first_seg(seg->pool_lv);
|
||||
|
||||
if (!seg_is_cache_pool(seg) ||
|
||||
(seg->cache_mode == CACHE_MODE_UNDEFINED))
|
||||
(seg->cache_mode == CACHE_MODE_UNSELECTED))
|
||||
return "";
|
||||
|
||||
return get_cache_mode_name(seg);
|
||||
@ -77,13 +77,14 @@ int set_cache_mode(cache_mode_t *mode, const char *cache_mode)
|
||||
int cache_set_cache_mode(struct lv_segment *seg, cache_mode_t mode)
|
||||
{
|
||||
struct cmd_context *cmd = seg->lv->vg->cmd;
|
||||
struct profile *profile = seg->lv->profile;
|
||||
const char *str;
|
||||
int id;
|
||||
|
||||
if (seg_is_cache(seg))
|
||||
seg = first_seg(seg->pool_lv);
|
||||
else if (seg_is_cache_pool(seg)) {
|
||||
if (mode == CACHE_MODE_UNDEFINED)
|
||||
if (mode == CACHE_MODE_UNSELECTED)
|
||||
return 1; /* Defaults only for cache */
|
||||
} else {
|
||||
log_error(INTERNAL_ERROR "Cannot set cache mode for non cache volume %s.",
|
||||
@ -91,12 +92,12 @@ int cache_set_cache_mode(struct lv_segment *seg, cache_mode_t mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode != CACHE_MODE_UNDEFINED) {
|
||||
if (mode != CACHE_MODE_UNSELECTED) {
|
||||
seg->cache_mode = mode;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (seg->cache_mode != CACHE_MODE_UNDEFINED)
|
||||
if (seg->cache_mode != CACHE_MODE_UNSELECTED)
|
||||
return 1; /* Default already set in cache pool */
|
||||
|
||||
/* Figure default settings from config/profiles */
|
||||
@ -107,7 +108,7 @@ int cache_set_cache_mode(struct lv_segment *seg, cache_mode_t mode)
|
||||
find_config_node(cmd, cmd->cft, allocation_cache_pool_cachemode_CFG))
|
||||
id = allocation_cache_pool_cachemode_CFG;
|
||||
|
||||
if (!(str = find_config_tree_str(cmd, id, NULL))) {
|
||||
if (!(str = find_config_tree_str(cmd, id, profile))) {
|
||||
log_error(INTERNAL_ERROR "Cache mode is not determined.");
|
||||
return 0;
|
||||
}
|
||||
@ -152,25 +153,30 @@ static uint64_t _cache_min_metadata_size(uint64_t data_size, uint32_t chunk_size
|
||||
return min_meta_size;
|
||||
}
|
||||
|
||||
int update_cache_pool_params(const struct segment_type *segtype,
|
||||
struct volume_group *vg, unsigned attr,
|
||||
int passed_args, uint32_t pool_data_extents,
|
||||
int update_cache_pool_params(struct cmd_context *cmd,
|
||||
struct profile *profile,
|
||||
uint32_t extent_size,
|
||||
const struct segment_type *segtype,
|
||||
unsigned attr,
|
||||
uint32_t pool_data_extents,
|
||||
uint32_t *pool_metadata_extents,
|
||||
int *chunk_size_calc_method, uint32_t *chunk_size)
|
||||
{
|
||||
uint64_t min_meta_size;
|
||||
uint32_t extent_size = vg->extent_size;
|
||||
uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
|
||||
uint64_t pool_data_size = (uint64_t) pool_data_extents * extent_size;
|
||||
uint64_t max_chunks =
|
||||
get_default_allocation_cache_pool_max_chunks_CFG(vg->cmd, vg->profile);
|
||||
const uint64_t max_chunks =
|
||||
get_default_allocation_cache_pool_max_chunks_CFG(cmd, profile);
|
||||
/* min chunk size in a multiple of DM_CACHE_MIN_DATA_BLOCK_SIZE */
|
||||
uint64_t min_chunk_size = (((pool_data_size + max_chunks - 1) / max_chunks +
|
||||
DM_CACHE_MIN_DATA_BLOCK_SIZE - 1) /
|
||||
DM_CACHE_MIN_DATA_BLOCK_SIZE) * DM_CACHE_MIN_DATA_BLOCK_SIZE;
|
||||
|
||||
if (!(passed_args & PASS_ARG_CHUNK_SIZE)) {
|
||||
*chunk_size = DEFAULT_CACHE_POOL_CHUNK_SIZE * 2;
|
||||
if (!*chunk_size) {
|
||||
if (!(*chunk_size = find_config_tree_int(cmd, allocation_cache_pool_chunk_size_CFG,
|
||||
profile) * 2))
|
||||
*chunk_size = get_default_allocation_cache_pool_chunk_size_CFG(cmd,
|
||||
profile);
|
||||
if (*chunk_size < min_chunk_size) {
|
||||
/*
|
||||
* When using more then 'standard' default,
|
||||
@ -178,25 +184,25 @@ int update_cache_pool_params(const struct segment_type *segtype,
|
||||
*/
|
||||
log_print_unless_silent("Using %s chunk size instead of default %s, "
|
||||
"so cache pool has less then " FMTu64 " chunks.",
|
||||
display_size(vg->cmd, min_chunk_size),
|
||||
display_size(vg->cmd, *chunk_size),
|
||||
display_size(cmd, min_chunk_size),
|
||||
display_size(cmd, *chunk_size),
|
||||
max_chunks);
|
||||
*chunk_size = min_chunk_size;
|
||||
} else
|
||||
log_verbose("Setting chunk size to %s.",
|
||||
display_size(vg->cmd, *chunk_size));
|
||||
display_size(cmd, *chunk_size));
|
||||
} else if (*chunk_size < min_chunk_size) {
|
||||
log_error("Chunk size %s is less then required minimal chunk size %s "
|
||||
"for a cache pool of %s size and limit " FMTu64 " chunks.",
|
||||
display_size(vg->cmd, *chunk_size),
|
||||
display_size(vg->cmd, min_chunk_size),
|
||||
display_size(vg->cmd, pool_data_size),
|
||||
display_size(cmd, *chunk_size),
|
||||
display_size(cmd, min_chunk_size),
|
||||
display_size(cmd, pool_data_size),
|
||||
max_chunks);
|
||||
log_error("To allow use of more chunks, see setting allocation/cache_pool_max_chunks.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!validate_pool_chunk_size(vg->cmd, segtype, *chunk_size))
|
||||
if (!validate_cache_chunk_size(cmd, *chunk_size))
|
||||
return_0;
|
||||
|
||||
min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
|
||||
@ -210,22 +216,31 @@ int update_cache_pool_params(const struct segment_type *segtype,
|
||||
|
||||
if (pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
|
||||
pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
|
||||
if (passed_args & PASS_ARG_POOL_METADATA_SIZE)
|
||||
if (*pool_metadata_extents)
|
||||
log_warn("WARNING: Maximum supported pool metadata size is %s.",
|
||||
display_size(vg->cmd, pool_metadata_size));
|
||||
display_size(cmd, pool_metadata_size));
|
||||
} else if (pool_metadata_size < min_meta_size) {
|
||||
if (passed_args & PASS_ARG_POOL_METADATA_SIZE)
|
||||
if (*pool_metadata_extents)
|
||||
log_warn("WARNING: Minimum required pool metadata size is %s "
|
||||
"(needs extra %s).",
|
||||
display_size(vg->cmd, min_meta_size),
|
||||
display_size(vg->cmd, min_meta_size - pool_metadata_size));
|
||||
display_size(cmd, min_meta_size),
|
||||
display_size(cmd, min_meta_size - pool_metadata_size));
|
||||
pool_metadata_size = min_meta_size;
|
||||
}
|
||||
|
||||
if (!(*pool_metadata_extents =
|
||||
extents_from_size(vg->cmd, pool_metadata_size, extent_size)))
|
||||
extents_from_size(cmd, pool_metadata_size, extent_size)))
|
||||
return_0;
|
||||
|
||||
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
|
||||
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
|
||||
segtype->name, display_size(cmd, *chunk_size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Preferred pool metadata size %s.",
|
||||
display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -236,7 +251,7 @@ int update_cache_pool_params(const struct segment_type *segtype,
|
||||
int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size)
|
||||
{
|
||||
struct volume_group *vg = pool_lv->vg;
|
||||
uint64_t max_chunks = get_default_allocation_cache_pool_max_chunks_CFG(vg->cmd, vg->profile);
|
||||
const uint64_t max_chunks = get_default_allocation_cache_pool_max_chunks_CFG(vg->cmd, pool_lv->profile);
|
||||
uint64_t min_size = _cache_min_metadata_size(pool_lv->size, chunk_size);
|
||||
uint64_t chunks = pool_lv->size / chunk_size;
|
||||
int r = 1;
|
||||
@ -292,7 +307,7 @@ int validate_lv_cache_create_pool(const struct logical_volume *pool_lv)
|
||||
|
||||
if (!dm_list_empty(&pool_lv->segs_using_this_lv)) {
|
||||
seg = get_only_segment_using_this_lv(pool_lv);
|
||||
log_error("Logical volume %s is already in use by %s",
|
||||
log_error("Logical volume %s is already in use by %s.",
|
||||
display_lvname(pool_lv),
|
||||
seg ? display_lvname(seg->lv) : "another LV");
|
||||
return 0;
|
||||
@ -333,6 +348,30 @@ int validate_lv_cache_create_origin(const struct logical_volume *origin_lv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int validate_cache_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
|
||||
{
|
||||
const uint32_t min_size = DM_CACHE_MIN_DATA_BLOCK_SIZE;
|
||||
const uint32_t max_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
|
||||
int r = 1;
|
||||
|
||||
if ((chunk_size < min_size) || (chunk_size > max_size)) {
|
||||
log_error("Cache chunk size %s is not in the range %s to %s.",
|
||||
display_size(cmd, chunk_size),
|
||||
display_size(cmd, min_size),
|
||||
display_size(cmd, max_size));
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (chunk_size & (min_size - 1)) {
|
||||
log_error("Cache chunk size %s must be a multiple of %s.",
|
||||
display_size(cmd, chunk_size),
|
||||
display_size(cmd, min_size));
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* lv_cache_create
|
||||
* @pool
|
||||
@ -370,6 +409,9 @@ struct logical_volume *lv_cache_create(struct logical_volume *pool_lv,
|
||||
if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
|
||||
return_NULL;
|
||||
|
||||
if (!seg->lv->profile) /* Inherit profile from cache-pool */
|
||||
seg->lv->profile = seg->pool_lv->profile;
|
||||
|
||||
return cache_lv;
|
||||
}
|
||||
|
||||
@ -633,6 +675,26 @@ static const char *_get_default_cache_policy(struct cmd_context *cmd)
|
||||
return def;
|
||||
}
|
||||
|
||||
/* Autodetect best available cache metadata format for a user */
|
||||
static cache_metadata_format_t _get_default_cache_metadata_format(struct cmd_context *cmd)
|
||||
{
|
||||
const struct segment_type *segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_CACHE);
|
||||
unsigned attr;
|
||||
cache_metadata_format_t f;
|
||||
|
||||
if (!segtype ||
|
||||
!segtype->ops->target_present ||
|
||||
!segtype->ops->target_present(cmd, NULL, &attr)) {
|
||||
f = CACHE_METADATA_FORMAT_1;
|
||||
log_warn("WARNING: Cannot detect default cache metadata format, using format: %u.", f);
|
||||
} else {
|
||||
f = (attr & CACHE_FEATURE_METADATA2) ? CACHE_METADATA_FORMAT_2 : CACHE_METADATA_FORMAT_1;
|
||||
log_debug_metadata("Detected default cache metadata format: %u.", f);
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
int cache_set_policy(struct lv_segment *seg, const char *name,
|
||||
const struct dm_config_tree *settings)
|
||||
{
|
||||
@ -640,28 +702,36 @@ int cache_set_policy(struct lv_segment *seg, const char *name,
|
||||
const struct dm_config_node *cns;
|
||||
struct dm_config_tree *old = NULL, *new = NULL, *tmp = NULL;
|
||||
int r = 0;
|
||||
const int passed_seg_is_cache = seg_is_cache(seg);
|
||||
struct profile *profile = seg->lv->profile;
|
||||
|
||||
if (passed_seg_is_cache)
|
||||
if (seg_is_cache(seg))
|
||||
seg = first_seg(seg->pool_lv);
|
||||
else if (seg_is_cache_pool(seg)) {
|
||||
if (!name && !settings)
|
||||
return 1; /* Policy and settings can be selected later when caching LV */
|
||||
} else {
|
||||
log_error(INTERNAL_ERROR "Cannot set cache metadata format for non cache volume %s.",
|
||||
display_lvname(seg->lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (name) {
|
||||
if (!(seg->policy_name = dm_pool_strdup(seg->lv->vg->vgmem, name))) {
|
||||
log_error("Failed to duplicate policy name.");
|
||||
return 0;
|
||||
}
|
||||
} 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)) &&
|
||||
} else if (!seg->policy_name) {
|
||||
if (!(seg->policy_name = find_config_tree_str(seg->lv->vg->cmd, allocation_cache_policy_CFG,
|
||||
profile)) &&
|
||||
!(seg->policy_name = _get_default_cache_policy(seg->lv->vg->cmd)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (settings) {
|
||||
if (!seg->policy_name) {
|
||||
log_error(INTERNAL_ERROR "Can't set policy settings without policy name.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings) {
|
||||
if (seg->policy_settings) {
|
||||
if (!(old = dm_config_create()))
|
||||
goto_out;
|
||||
@ -677,30 +747,26 @@ int cache_set_policy(struct lv_segment *seg, const char *name,
|
||||
if ((cn = dm_config_find_node((tmp) ? tmp->root : settings->root, "policy_settings")) &&
|
||||
!(seg->policy_settings = dm_config_clone_node_with_mem(seg->lv->vg->vgmem, cn, 0)))
|
||||
goto_out;
|
||||
} else if (passed_seg_is_cache && /* Look for command's profile cache_policies */
|
||||
(cns = find_config_tree_node(seg->lv->vg->cmd, allocation_cache_settings_CFG_SECTION, NULL))) {
|
||||
/* Try to find our section for given policy */
|
||||
for (cn = cns->child; cn; cn = cn->sib) {
|
||||
/* Only matching section names */
|
||||
if (cn->v || strcmp(cn->key, seg->policy_name) != 0)
|
||||
continue;
|
||||
} else if (!seg->policy_settings) {
|
||||
if ((cns = find_config_tree_node(seg->lv->vg->cmd, allocation_cache_settings_CFG_SECTION,
|
||||
profile))) {
|
||||
/* Try to find our section for given policy */
|
||||
for (cn = cns->child; cn; cn = cn->sib) {
|
||||
if (!cn->child)
|
||||
continue; /* Ignore section without settings */
|
||||
|
||||
if (!cn->child)
|
||||
break;
|
||||
if (cn->v || strcmp(cn->key, seg->policy_name) != 0)
|
||||
continue; /* Ignore mismatching sections */
|
||||
|
||||
if (!(new = dm_config_create()))
|
||||
goto_out;
|
||||
/* Clone nodes with policy name */
|
||||
if (!(seg->policy_settings = dm_config_clone_node_with_mem(seg->lv->vg->vgmem,
|
||||
cn, 0)))
|
||||
return_0;
|
||||
|
||||
if (!(new->root = dm_config_clone_node_with_mem(new->mem,
|
||||
cn->child, 1)))
|
||||
goto_out;
|
||||
|
||||
if (!(seg->policy_settings = dm_config_create_node(new, "policy_settings")))
|
||||
goto_out;
|
||||
|
||||
seg->policy_settings->child = new->root;
|
||||
|
||||
break; /* Only first match counts */
|
||||
/* Replace policy name key with 'policy_settings' */
|
||||
seg->policy_settings->key = "policy_settings";
|
||||
break; /* Only first match counts */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -727,17 +793,94 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets metadata format on cache pool segment with these rules:
|
||||
* 1. When 'cache-pool' segment is passed, sets only for selected formats (1 or 2).
|
||||
* 2. For 'cache' segment passed in we know cache pool segment.
|
||||
* When passed format is 0 (UNSELECTED) with 'cache' segment - it's the moment
|
||||
* lvm2 has to figure out 'default' metadata format (1 or 2) from
|
||||
* configuration or profiles.
|
||||
* 3. If still unselected or selected format is != 1, figure the best supported format
|
||||
* and either use it or validate users settings is possible.
|
||||
*
|
||||
* Reasoning: A user may create cache-pool and may or may not specify CMFormat.
|
||||
* If the CMFormat has been selected (1 or 2) store this in metadata, otherwise
|
||||
* for an unused cache-pool UNSELECTED CMFormat is used. When caching LV, CMFormat
|
||||
* must be decided and from this moment it's always stored. To support backward
|
||||
* compatibility 'CMFormat 1' is used when it is NOT specified for a cached LV in
|
||||
* lvm2 metadata (no metadata_format=#F element in cache-pool segment).
|
||||
*/
|
||||
int cache_set_metadata_format(struct lv_segment *seg, cache_metadata_format_t format)
|
||||
{
|
||||
cache_metadata_format_t best;
|
||||
struct profile *profile = seg->lv->profile;
|
||||
|
||||
if (seg_is_cache(seg))
|
||||
seg = first_seg(seg->pool_lv);
|
||||
else if (seg_is_cache_pool(seg)) {
|
||||
if (format == CACHE_METADATA_FORMAT_UNSELECTED)
|
||||
return 1; /* Format can be selected later when caching LV */
|
||||
} else {
|
||||
log_error(INTERNAL_ERROR "Cannot set cache metadata format for non cache volume %s.",
|
||||
display_lvname(seg->lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if we need to search for configured cache metadata format */
|
||||
if (format == CACHE_METADATA_FORMAT_UNSELECTED) {
|
||||
if (seg->cache_metadata_format != CACHE_METADATA_FORMAT_UNSELECTED)
|
||||
return 1; /* Format already selected in cache pool */
|
||||
|
||||
/* Check configurations and profiles */
|
||||
format = find_config_tree_int(seg->lv->vg->cmd, allocation_cache_metadata_format_CFG,
|
||||
profile);
|
||||
}
|
||||
|
||||
/* See what is a 'best' available cache metadata format
|
||||
* when the specifed format is other then always existing CMFormat 1 */
|
||||
if (format != CACHE_METADATA_FORMAT_1) {
|
||||
best = _get_default_cache_metadata_format(seg->lv->vg->cmd);
|
||||
|
||||
/* Format was not selected, so use best present on a system */
|
||||
if (format == CACHE_METADATA_FORMAT_UNSELECTED)
|
||||
format = best;
|
||||
else if (format != best) {
|
||||
/* Format is not valid (Only Format 1 or 2 is supported ATM) */
|
||||
log_error("Cache metadata format %u is not supported by kernel target.", format);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case CACHE_METADATA_FORMAT_2: seg->lv->status |= LV_METADATA_FORMAT; break;
|
||||
case CACHE_METADATA_FORMAT_1: seg->lv->status &= ~LV_METADATA_FORMAT; break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "Invalid cache metadata format %u for cache volume %s.",
|
||||
format, display_lvname(seg->lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->cache_metadata_format = format;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Universal 'wrapper' function do-it-all
|
||||
* to update all commonly specified cache parameters
|
||||
*/
|
||||
int cache_set_params(struct lv_segment *seg,
|
||||
uint32_t chunk_size,
|
||||
cache_metadata_format_t format,
|
||||
cache_mode_t mode,
|
||||
const char *policy_name,
|
||||
const struct dm_config_tree *policy_settings,
|
||||
uint32_t chunk_size)
|
||||
const struct dm_config_tree *policy_settings)
|
||||
{
|
||||
struct lv_segment *pool_seg;
|
||||
struct cmd_context *cmd = seg->lv->vg->cmd;
|
||||
|
||||
if (!cache_set_metadata_format(seg, format))
|
||||
return_0;
|
||||
|
||||
if (!cache_set_cache_mode(seg, mode))
|
||||
return_0;
|
||||
@ -748,16 +891,35 @@ int cache_set_params(struct lv_segment *seg,
|
||||
pool_seg = seg_is_cache(seg) ? first_seg(seg->pool_lv) : seg;
|
||||
|
||||
if (chunk_size) {
|
||||
if (!validate_lv_cache_chunk_size(pool_seg->lv, chunk_size))
|
||||
if (seg_is_cache(seg) &&
|
||||
!validate_lv_cache_chunk_size(pool_seg->lv, chunk_size))
|
||||
return_0;
|
||||
pool_seg->chunk_size = chunk_size;
|
||||
} else {
|
||||
/* TODO: some calc_policy solution for cache ? */
|
||||
if (!recalculate_pool_chunk_size_with_dev_hints(pool_seg->lv, 0,
|
||||
} else if (seg_is_cache(seg)) {
|
||||
/* Chunk size in profile has priority over cache-pool chunk size */
|
||||
if ((chunk_size = find_config_tree_int(cmd, allocation_cache_pool_chunk_size_CFG,
|
||||
seg->lv->profile) * 2)) {
|
||||
if (!validate_lv_cache_chunk_size(pool_seg->lv, chunk_size))
|
||||
return_0;
|
||||
if (pool_seg->chunk_size != chunk_size)
|
||||
log_verbose("Replacing chunk size %s in cache pool %s with "
|
||||
"chunk size %s from profile.",
|
||||
display_size(cmd, pool_seg->chunk_size),
|
||||
display_lvname(seg->lv),
|
||||
display_size(cmd, chunk_size));
|
||||
pool_seg->chunk_size = chunk_size;
|
||||
}
|
||||
} else if (seg_is_cache_pool(seg)) {
|
||||
if (!pool_seg->chunk_size &&
|
||||
/* TODO: some calc_policy solution for cache ? */
|
||||
!recalculate_pool_chunk_size_with_dev_hints(pool_seg->lv,
|
||||
THIN_CHUNK_SIZE_CALC_METHOD_GENERIC))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (seg_is_cache(seg))
|
||||
cache_check_for_warns(seg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -227,12 +227,23 @@ char *lvseg_kernel_discards_dup_with_info_and_seg_status(struct dm_pool *mem, co
|
||||
{
|
||||
const char *s = "";
|
||||
char *ret;
|
||||
thin_discards_t d;
|
||||
|
||||
if (lvdm->seg_status.type == SEG_STATUS_THIN_POOL)
|
||||
s = get_pool_discards_name(lvdm->seg_status.thin_pool->discards);
|
||||
if (lvdm->seg_status.type == SEG_STATUS_THIN_POOL) {
|
||||
switch (lvdm->seg_status.thin_pool->discards) {
|
||||
case DM_THIN_DISCARDS_IGNORE: d = THIN_DISCARDS_IGNORE; break;
|
||||
case DM_THIN_DISCARDS_NO_PASSDOWN: d = THIN_DISCARDS_NO_PASSDOWN; break;
|
||||
case DM_THIN_DISCARDS_PASSDOWN: d = THIN_DISCARDS_PASSDOWN; break;
|
||||
default:
|
||||
log_error("Kernel reports unknown discards status %u.",
|
||||
lvdm->seg_status.thin_pool->discards);
|
||||
return 0;
|
||||
}
|
||||
s = get_pool_discards_name(d);
|
||||
}
|
||||
|
||||
if (!(ret = dm_pool_strdup(mem, s))) {
|
||||
log_error("lvseg_kernel_discards_dup_with_info_and_seg_status: dm_pool_strdup failed");
|
||||
log_error("lvseg_kernel_discards_dup_with_info_and_seg_status: dm_pool_strdup failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1104,6 +1115,19 @@ int lv_raid_healthy(const struct logical_volume *lv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Helper: check for any sub LVs after a disk removing reshape */
|
||||
static int _sublvs_remove_after_reshape(const struct logical_volume *lv)
|
||||
{
|
||||
uint32_t s;
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
|
||||
for (s = seg->area_count -1; s; s--)
|
||||
if (seg_lv(seg, s)->status & LV_REMOVE_AFTER_RESHAPE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm)
|
||||
{
|
||||
const struct logical_volume *lv = lvdm->lv;
|
||||
@ -1255,7 +1279,7 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
|
||||
|
||||
if (((lv_is_thin_volume(lv) && (seg = first_seg(lv)) && seg->pool_lv && (seg = first_seg(seg->pool_lv))) ||
|
||||
(lv_is_thin_pool(lv) && (seg = first_seg(lv)))) &&
|
||||
seg->zero_new_blocks)
|
||||
(seg->zero_new_blocks == THIN_ZERO_YES))
|
||||
repstr[7] = 'z';
|
||||
else
|
||||
repstr[7] = '-';
|
||||
@ -1269,6 +1293,8 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
|
||||
repstr[8] = 'p';
|
||||
else if (lv_is_raid_type(lv)) {
|
||||
uint64_t n;
|
||||
char *sync_action;
|
||||
|
||||
if (!activation())
|
||||
repstr[8] = 'X'; /* Unknown */
|
||||
else if (!lv_raid_healthy(lv))
|
||||
@ -1276,8 +1302,17 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
|
||||
else if (lv_is_raid(lv)) {
|
||||
if (lv_raid_mismatch_count(lv, &n) && n)
|
||||
repstr[8] = 'm'; /* RAID has 'm'ismatches */
|
||||
else if (lv_raid_sync_action(lv, &sync_action) &&
|
||||
!strcmp(sync_action, "reshape"))
|
||||
repstr[8] = 's'; /* LV is re(s)haping */
|
||||
else if (_sublvs_remove_after_reshape(lv))
|
||||
repstr[8] = 'R'; /* sub-LV got freed from raid set by reshaping
|
||||
and has to be 'R'emoved */
|
||||
} else if (lv->status & LV_WRITEMOSTLY)
|
||||
repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */
|
||||
else if (lv->status & LV_REMOVE_AFTER_RESHAPE)
|
||||
repstr[8] = 'R'; /* sub-LV got freed from raid set by reshaping
|
||||
and has to be 'R'emoved */
|
||||
} else if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
|
||||
if (lvdm->seg_status.cache->fail)
|
||||
repstr[8] = 'F';
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -21,11 +21,13 @@
|
||||
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
|
||||
struct logical_volume *lv,
|
||||
uint32_t le, uint32_t len,
|
||||
uint32_t reshape_len,
|
||||
uint64_t status,
|
||||
uint32_t stripe_size,
|
||||
struct logical_volume *log_lv,
|
||||
uint32_t area_count,
|
||||
uint32_t area_len,
|
||||
uint32_t data_copies,
|
||||
uint32_t chunk_size,
|
||||
uint32_t region_size,
|
||||
uint32_t extents_copied,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -912,11 +912,13 @@ static uint32_t _round_to_stripe_boundary(struct volume_group *vg, uint32_t exte
|
||||
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
|
||||
struct logical_volume *lv,
|
||||
uint32_t le, uint32_t len,
|
||||
uint32_t reshape_len,
|
||||
uint64_t status,
|
||||
uint32_t stripe_size,
|
||||
struct logical_volume *log_lv,
|
||||
uint32_t area_count,
|
||||
uint32_t area_len,
|
||||
uint32_t data_copies,
|
||||
uint32_t chunk_size,
|
||||
uint32_t region_size,
|
||||
uint32_t extents_copied,
|
||||
@ -950,10 +952,12 @@ struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
|
||||
seg->lv = lv;
|
||||
seg->le = le;
|
||||
seg->len = len;
|
||||
seg->reshape_len = reshape_len;
|
||||
seg->status = status;
|
||||
seg->stripe_size = stripe_size;
|
||||
seg->area_count = area_count;
|
||||
seg->area_len = area_len;
|
||||
seg->data_copies = data_copies ? : lv_raid_data_copies(segtype, area_count);
|
||||
seg->chunk_size = chunk_size;
|
||||
seg->region_size = region_size;
|
||||
seg->extents_copied = extents_copied;
|
||||
@ -1047,11 +1051,10 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
|
||||
if (lv_is_raid_image(lv)) {
|
||||
/* Calculate the amount of extents to reduce per rmate/rimage LV */
|
||||
uint32_t rimage_extents;
|
||||
struct lv_segment *seg1 = first_seg(lv);
|
||||
|
||||
/* FIXME: avoid extra seg_is_*() conditonals */
|
||||
area_reduction =_round_to_stripe_boundary(lv->vg, area_reduction,
|
||||
(seg_is_raid1(seg) || seg_is_any_raid0(seg)) ? 0 : _raid_stripes_count(seg), 0);
|
||||
rimage_extents = raid_rimage_extents(seg->segtype, area_reduction, seg_is_any_raid0(seg) ? 0 : _raid_stripes_count(seg),
|
||||
/* FIXME: avoid extra seg_is_*() conditionals here */
|
||||
rimage_extents = raid_rimage_extents(seg1->segtype, area_reduction, seg_is_any_raid0(seg) ? 0 : _raid_stripes_count(seg),
|
||||
seg_is_raid10(seg) ? 1 :_raid_data_copies(seg));
|
||||
if (!rimage_extents)
|
||||
return 0;
|
||||
@ -1258,7 +1261,7 @@ static uint32_t _calc_area_multiple(const struct segment_type *segtype,
|
||||
* the 'stripes' argument will always need to
|
||||
* be given.
|
||||
*/
|
||||
if (!strcmp(segtype->name, _lv_type_names[LV_TYPE_RAID10])) {
|
||||
if (segtype_is_raid10(segtype)) {
|
||||
if (!stripes)
|
||||
return area_count / 2;
|
||||
return stripes;
|
||||
@ -1278,16 +1281,17 @@ static uint32_t _calc_area_multiple(const struct segment_type *segtype,
|
||||
static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
|
||||
{
|
||||
uint32_t area_reduction, s;
|
||||
uint32_t areas = (seg->area_count / (seg_is_raid10(seg) ? seg->data_copies : 1)) - seg->segtype->parity_devs;
|
||||
|
||||
/* Caller must ensure exact divisibility */
|
||||
if (seg_is_striped(seg)) {
|
||||
if (reduction % seg->area_count) {
|
||||
if (seg_is_striped(seg) || seg_is_striped_raid(seg)) {
|
||||
if (reduction % areas) {
|
||||
log_error("Segment extent reduction %" PRIu32
|
||||
" not divisible by #stripes %" PRIu32,
|
||||
reduction, seg->area_count);
|
||||
return 0;
|
||||
}
|
||||
area_reduction = (reduction / seg->area_count);
|
||||
area_reduction = reduction / areas;
|
||||
} else
|
||||
area_reduction = reduction;
|
||||
|
||||
@ -1296,7 +1300,11 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
|
||||
return_0;
|
||||
|
||||
seg->len -= reduction;
|
||||
seg->area_len -= area_reduction;
|
||||
|
||||
if (seg_is_raid(seg))
|
||||
seg->area_len = seg->len;
|
||||
else
|
||||
seg->area_len -= area_reduction;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1306,11 +1314,13 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
|
||||
*/
|
||||
static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
struct lv_segment *seg = first_seg(lv);;
|
||||
uint32_t count = extents;
|
||||
uint32_t reduction;
|
||||
struct logical_volume *pool_lv;
|
||||
struct logical_volume *external_lv = NULL;
|
||||
int is_raid10 = seg_is_any_raid10(seg) && seg->reshape_len;
|
||||
uint32_t data_copies = seg->data_copies;
|
||||
|
||||
if (lv_is_merging_origin(lv)) {
|
||||
log_debug_metadata("Dropping snapshot merge of %s to removed origin %s.",
|
||||
@ -1373,8 +1383,18 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
||||
count -= reduction;
|
||||
}
|
||||
|
||||
lv->le_count -= extents;
|
||||
seg = first_seg(lv);
|
||||
|
||||
if (is_raid10) {
|
||||
lv->le_count -= extents * data_copies;
|
||||
if (seg)
|
||||
seg->len = seg->area_len = lv->le_count;
|
||||
} else
|
||||
lv->le_count -= extents;
|
||||
|
||||
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
|
||||
if (seg)
|
||||
seg->extents_copied = seg->len;
|
||||
|
||||
if (!delete)
|
||||
return 1;
|
||||
@ -1487,11 +1507,10 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
|
||||
{
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
|
||||
/* Ensure stipe boundary extents on RAID LVs */
|
||||
/* Ensure stripe boundary extents on RAID LVs */
|
||||
if (lv_is_raid(lv) && extents != lv->le_count)
|
||||
extents =_round_to_stripe_boundary(lv->vg, extents,
|
||||
seg_is_raid1(seg) ? 0 : _raid_stripes_count(seg), 0);
|
||||
|
||||
return _lv_reduce(lv, extents, 1);
|
||||
}
|
||||
|
||||
@ -1793,10 +1812,10 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
|
||||
area_multiple = _calc_area_multiple(segtype, area_count, 0);
|
||||
extents = aa[0].len * area_multiple;
|
||||
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents,
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents, 0,
|
||||
status, stripe_size, NULL,
|
||||
area_count,
|
||||
aa[0].len, 0u, region_size, 0u, NULL))) {
|
||||
aa[0].len, 0, 0u, region_size, 0u, NULL))) {
|
||||
log_error("Couldn't allocate new LV segment.");
|
||||
return 0;
|
||||
}
|
||||
@ -3234,9 +3253,9 @@ int lv_add_virtual_segment(struct logical_volume *lv, uint64_t status,
|
||||
seg->area_len += extents;
|
||||
seg->len += extents;
|
||||
} else {
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents,
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents, 0,
|
||||
status, 0, NULL, 0,
|
||||
extents, 0, 0, 0, NULL))) {
|
||||
extents, 0, 0, 0, 0, NULL))) {
|
||||
log_error("Couldn't allocate new %s segment.", segtype->name);
|
||||
return 0;
|
||||
}
|
||||
@ -3562,10 +3581,10 @@ static struct lv_segment *_convert_seg_to_mirror(struct lv_segment *seg,
|
||||
}
|
||||
|
||||
if (!(newseg = alloc_lv_segment(get_segtype_from_string(seg->lv->vg->cmd, SEG_TYPE_NAME_MIRROR),
|
||||
seg->lv, seg->le, seg->len,
|
||||
seg->lv, seg->le, seg->len, 0,
|
||||
seg->status, seg->stripe_size,
|
||||
log_lv,
|
||||
seg->area_count, seg->area_len,
|
||||
seg->area_count, seg->area_len, 0,
|
||||
seg->chunk_size, region_size,
|
||||
seg->extents_copied, NULL))) {
|
||||
log_error("Couldn't allocate converted LV segment.");
|
||||
@ -3667,8 +3686,8 @@ int lv_add_segmented_mirror_image(struct alloc_handle *ah,
|
||||
}
|
||||
|
||||
if (!(new_seg = alloc_lv_segment(segtype, copy_lv,
|
||||
seg->le, seg->len, PVMOVE, 0,
|
||||
NULL, 1, seg->len,
|
||||
seg->le, seg->len, 0, PVMOVE, 0,
|
||||
NULL, 1, seg->len, 0,
|
||||
0, 0, 0, NULL)))
|
||||
return_0;
|
||||
|
||||
@ -3863,9 +3882,9 @@ static int _lv_insert_empty_sublvs(struct logical_volume *lv,
|
||||
/*
|
||||
* First, create our top-level segment for our top-level LV
|
||||
*/
|
||||
if (!(mapseg = alloc_lv_segment(segtype, lv, 0, 0, lv->status,
|
||||
if (!(mapseg = alloc_lv_segment(segtype, lv, 0, 0, 0, lv->status,
|
||||
stripe_size, NULL,
|
||||
devices, 0, 0, region_size, 0, NULL))) {
|
||||
devices, 0, 0, 0, region_size, 0, NULL))) {
|
||||
log_error("Failed to create mapping segment for %s.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
@ -3925,7 +3944,7 @@ bad:
|
||||
static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
||||
struct logical_volume *lv,
|
||||
uint32_t extents, uint32_t first_area,
|
||||
uint32_t stripes, uint32_t stripe_size)
|
||||
uint32_t mirrors, uint32_t stripes, uint32_t stripe_size)
|
||||
{
|
||||
const struct segment_type *segtype;
|
||||
struct logical_volume *sub_lv, *meta_lv;
|
||||
@ -3953,7 +3972,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
||||
for (fa = first_area, s = 0; s < seg->area_count; s++) {
|
||||
if (is_temporary_mirror_layer(seg_lv(seg, s))) {
|
||||
if (!_lv_extend_layered_lv(ah, seg_lv(seg, s), extents / area_multiple,
|
||||
fa, stripes, stripe_size))
|
||||
fa, mirrors, stripes, stripe_size))
|
||||
return_0;
|
||||
fa += lv_mirror_count(seg_lv(seg, s));
|
||||
continue;
|
||||
@ -3967,6 +3986,8 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
||||
return 0;
|
||||
}
|
||||
|
||||
last_seg(lv)->data_copies = mirrors;
|
||||
|
||||
/* Extend metadata LVs only on initial creation */
|
||||
if (seg_is_raid_with_meta(seg) && !lv->le_count) {
|
||||
if (!seg->meta_areas) {
|
||||
@ -4063,8 +4084,11 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
||||
lv_set_hidden(seg_metalv(seg, s));
|
||||
}
|
||||
|
||||
seg->area_len += extents / area_multiple;
|
||||
seg->len += extents;
|
||||
if (seg_is_raid(seg))
|
||||
seg->area_len = seg->len;
|
||||
else
|
||||
seg->area_len += extents / area_multiple;
|
||||
|
||||
if (!_setup_lv_size(lv, lv->le_count + extents))
|
||||
return_0;
|
||||
@ -4171,7 +4195,7 @@ int lv_extend(struct logical_volume *lv,
|
||||
}
|
||||
|
||||
if (!(r = _lv_extend_layered_lv(ah, lv, new_extents - lv->le_count, 0,
|
||||
stripes, stripe_size)))
|
||||
mirrors, stripes, stripe_size)))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
@ -5391,6 +5415,17 @@ int lv_resize(struct logical_volume *lv,
|
||||
if (!_lvresize_check(lv, lp))
|
||||
return_0;
|
||||
|
||||
if (seg->reshape_len) {
|
||||
/* Prevent resizing on out-of-sync reshapable raid */
|
||||
if (!lv_raid_in_sync(lv)) {
|
||||
log_error("Can't resize reshaping LV %s.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
/* Remove any striped raid reshape space for LV resizing */
|
||||
if (!lv_raid_free_reshape_space(lv))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (lp->use_policies) {
|
||||
lp->extents = 0;
|
||||
lp->sign = SIGN_PLUS;
|
||||
@ -5902,6 +5937,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int ask_discard;
|
||||
struct lv_list *lvl;
|
||||
struct seg_list *sl;
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
int is_last_pool = lv_is_pool(lv);
|
||||
|
||||
vg = lv->vg;
|
||||
@ -6008,6 +6044,13 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
is_last_pool = 1;
|
||||
}
|
||||
|
||||
/* Special case removing a striped raid LV with allocated reshape space */
|
||||
if (seg && seg->reshape_len) {
|
||||
if (!(seg->segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED)))
|
||||
return_0;
|
||||
lv->le_count = seg->len = seg->area_len = seg_lv(seg, 0)->le_count * seg->area_count;
|
||||
}
|
||||
|
||||
/* Used cache pool, COW or historical LV cannot be activated */
|
||||
if ((!lv_is_cache_pool(lv) || dm_list_empty(&lv->segs_using_this_lv)) &&
|
||||
!lv_is_cow(lv) && !lv_is_historical(lv) &&
|
||||
@ -6309,7 +6352,6 @@ static int _lv_update_and_reload(struct logical_volume *lv, int origin_only)
|
||||
|
||||
log_very_verbose("Updating logical volume %s on disk(s)%s.",
|
||||
display_lvname(lock_lv), origin_only ? " (origin only)": "");
|
||||
|
||||
if (!vg_write(vg))
|
||||
return_0;
|
||||
|
||||
@ -6776,8 +6818,8 @@ struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
|
||||
return_NULL;
|
||||
|
||||
/* allocate a new linear segment */
|
||||
if (!(mapseg = alloc_lv_segment(segtype, lv_where, 0, layer_lv->le_count,
|
||||
status, 0, NULL, 1, layer_lv->le_count,
|
||||
if (!(mapseg = alloc_lv_segment(segtype, lv_where, 0, layer_lv->le_count, 0,
|
||||
status, 0, NULL, 1, layer_lv->le_count, 0,
|
||||
0, 0, 0, NULL)))
|
||||
return_NULL;
|
||||
|
||||
@ -6833,8 +6875,8 @@ static int _extend_layer_lv_for_segment(struct logical_volume *layer_lv,
|
||||
|
||||
/* allocate a new segment */
|
||||
if (!(mapseg = alloc_lv_segment(segtype, layer_lv, layer_lv->le_count,
|
||||
seg->area_len, status, 0,
|
||||
NULL, 1, seg->area_len, 0, 0, 0, seg)))
|
||||
seg->area_len, 0, status, 0,
|
||||
NULL, 1, seg->area_len, 0, 0, 0, 0, seg)))
|
||||
return_0;
|
||||
|
||||
/* map the new segment to the original underlying are */
|
||||
@ -7360,29 +7402,20 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (seg_is_cache(lp)) {
|
||||
/* validate metadata size */
|
||||
if (!validate_lv_cache_chunk_size(pool_lv, lp->chunk_size))
|
||||
return_0;
|
||||
|
||||
first_seg(pool_lv)->chunk_size = lp->chunk_size;
|
||||
}
|
||||
|
||||
/* Validate volume size to to aling on chunk for small extents */
|
||||
/* Cache chunk size is always set */
|
||||
size = first_seg(pool_lv)->chunk_size;
|
||||
if (size > vg->extent_size) {
|
||||
/* Align extents on chunk boundary size */
|
||||
size = ((uint64_t)vg->extent_size * lp->extents + size - 1) /
|
||||
size * size / vg->extent_size;
|
||||
if (size != lp->extents) {
|
||||
log_print_unless_silent("Rounding size (%d extents) up to chunk boundary "
|
||||
"size (%d extents).", lp->extents, size);
|
||||
lp->extents = size;
|
||||
}
|
||||
}
|
||||
|
||||
if (seg_is_thin_volume(lp)) {
|
||||
/* Validate volume size to to aling on chunk for small extents */
|
||||
size = first_seg(pool_lv)->chunk_size;
|
||||
if (size > vg->extent_size) {
|
||||
/* Align extents on chunk boundary size */
|
||||
size = ((uint64_t)vg->extent_size * lp->extents + size - 1) /
|
||||
size * size / vg->extent_size;
|
||||
if (size != lp->extents) {
|
||||
log_print_unless_silent("Rounding size (%d extents) up to chunk boundary "
|
||||
"size (%d extents).", lp->extents, size);
|
||||
lp->extents = size;
|
||||
}
|
||||
}
|
||||
|
||||
thin_pool_was_active = lv_is_active(pool_lv);
|
||||
if (lv_is_new_thin_pool(pool_lv)) {
|
||||
if (!check_new_thin_pool(pool_lv))
|
||||
@ -7392,7 +7425,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
if (!activate_lv_excl_local(cmd, pool_lv)) {
|
||||
log_error("Aborting. Failed to locally activate thin pool %s.",
|
||||
display_lvname(pool_lv));
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (!pool_below_threshold(first_seg(pool_lv))) {
|
||||
log_error("Cannot create new thin volume, free space in "
|
||||
@ -7630,10 +7663,11 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
|
||||
if (lv_is_cache_pool(lv)) {
|
||||
if (!cache_set_params(first_seg(lv),
|
||||
lp->chunk_size,
|
||||
lp->cache_metadata_format,
|
||||
lp->cache_mode,
|
||||
lp->policy_name,
|
||||
lp->policy_settings,
|
||||
lp->chunk_size)) {
|
||||
lp->policy_settings)) {
|
||||
stack;
|
||||
goto revert_new_lv;
|
||||
}
|
||||
@ -7642,10 +7676,9 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
first_seg(lv)->max_recovery_rate = lp->max_recovery_rate;
|
||||
} else if (lv_is_thin_pool(lv)) {
|
||||
first_seg(lv)->chunk_size = lp->chunk_size;
|
||||
first_seg(lv)->zero_new_blocks = lp->zero ? 1 : 0;
|
||||
first_seg(lv)->zero_new_blocks = lp->zero_new_blocks;
|
||||
first_seg(lv)->discards = lp->discards;
|
||||
if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->passed_args,
|
||||
lp->thin_chunk_size_calc_policy)) {
|
||||
if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->thin_chunk_size_calc_policy)) {
|
||||
stack;
|
||||
goto revert_new_lv;
|
||||
}
|
||||
@ -7839,14 +7872,13 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
lv = tmp_lv;
|
||||
|
||||
if (!cache_set_params(first_seg(lv),
|
||||
lp->chunk_size,
|
||||
lp->cache_metadata_format,
|
||||
lp->cache_mode,
|
||||
lp->policy_name,
|
||||
lp->policy_settings,
|
||||
(lp->passed_args & PASS_ARG_CHUNK_SIZE) ? lp->chunk_size : 0))
|
||||
lp->policy_settings))
|
||||
return_NULL; /* revert? */
|
||||
|
||||
cache_check_for_warns(first_seg(lv));
|
||||
|
||||
if (!lv_update_and_reload(lv)) {
|
||||
/* FIXME Do a better revert */
|
||||
log_error("Aborting. Manual intervention required.");
|
||||
|
@ -236,7 +236,7 @@ static void _check_raid_seg(struct lv_segment *seg, int *error_count)
|
||||
if (!seg->areas)
|
||||
raid_seg_error("zero areas");
|
||||
|
||||
if (seg->extents_copied > seg->area_len)
|
||||
if (seg->extents_copied > seg->len)
|
||||
raid_seg_error_val("extents_copied too large", seg->extents_copied);
|
||||
|
||||
/* Default < 10, change once raid1 split shift and rename SubLVs works! */
|
||||
@ -328,6 +328,13 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
|
||||
if (seg_is_cache_pool(seg)) {
|
||||
if (!dm_list_empty(&seg->lv->segs_using_this_lv)) {
|
||||
switch (seg->cache_metadata_format) {
|
||||
case CACHE_METADATA_FORMAT_2:
|
||||
case CACHE_METADATA_FORMAT_1:
|
||||
break;
|
||||
default:
|
||||
seg_error("has invalid cache metadata format");
|
||||
}
|
||||
switch (seg->cache_mode) {
|
||||
case CACHE_MODE_WRITETHROUGH:
|
||||
case CACHE_MODE_WRITEBACK:
|
||||
@ -339,13 +346,24 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
if (!seg->policy_name)
|
||||
seg_error("is missing cache policy name");
|
||||
}
|
||||
if (!validate_cache_chunk_size(lv->vg->cmd, seg->chunk_size))
|
||||
seg_error("has invalid chunk size.");
|
||||
if (seg->lv->status & LV_METADATA_FORMAT) {
|
||||
if (seg->cache_metadata_format != CACHE_METADATA_FORMAT_2)
|
||||
seg_error("sets METADATA_FORMAT flag");
|
||||
} else if (seg->cache_metadata_format == CACHE_METADATA_FORMAT_2)
|
||||
seg_error("is missing METADATA_FORMAT flag");
|
||||
} else { /* !cache_pool */
|
||||
if (seg->cache_metadata_format)
|
||||
seg_error("sets cache metadata format");
|
||||
if (seg->cache_mode)
|
||||
seg_error("sets cache mode");
|
||||
if (seg->policy_name)
|
||||
seg_error("sets policy name");
|
||||
if (seg->policy_settings)
|
||||
seg_error("sets policy settings");
|
||||
if (seg->lv->status & LV_METADATA_FORMAT)
|
||||
seg_error("sets METADATA_FORMAT flag");
|
||||
}
|
||||
|
||||
if (!seg_can_error_when_full(seg) && lv_is_error_when_full(lv))
|
||||
@ -380,9 +398,6 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
seg_error("is missing a pool metadata LV");
|
||||
} else if (!(seg2 = first_seg(seg->metadata_lv)) || (find_pool_seg(seg2) != seg))
|
||||
seg_error("metadata LV does not refer back to pool LV");
|
||||
|
||||
if (!validate_pool_chunk_size(lv->vg->cmd, seg->segtype, seg->chunk_size))
|
||||
seg_error("has invalid chunk size.");
|
||||
} else { /* !thin_pool && !cache_pool */
|
||||
if (seg->metadata_lv)
|
||||
seg_error("must not have pool metadata LV set");
|
||||
@ -394,10 +409,17 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
|
||||
if (lv_is_thin_volume(lv))
|
||||
seg_error("is a thin volume that must not contain thin pool segment");
|
||||
|
||||
if (!validate_thin_pool_chunk_size(lv->vg->cmd, seg->chunk_size))
|
||||
seg_error("has invalid chunk size.");
|
||||
|
||||
if (seg->zero_new_blocks != THIN_ZERO_YES &&
|
||||
seg->zero_new_blocks != THIN_ZERO_NO)
|
||||
seg_error("zero_new_blocks is invalid");
|
||||
} else { /* !thin_pool */
|
||||
if (seg->zero_new_blocks)
|
||||
if (seg->zero_new_blocks != THIN_ZERO_UNSELECTED)
|
||||
seg_error("sets zero_new_blocks");
|
||||
if (seg->discards)
|
||||
if (seg->discards != THIN_DISCARDS_UNSELECTED)
|
||||
seg_error("sets discards");
|
||||
if (!dm_list_empty(&seg->thin_messages))
|
||||
seg_error("sets thin_messages list");
|
||||
@ -475,7 +497,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
|
||||
struct lv_segment *seg, *seg2;
|
||||
uint32_t le = 0;
|
||||
unsigned seg_count = 0, seg_found, external_lv_found = 0;
|
||||
uint32_t area_multiplier, s;
|
||||
uint32_t data_rimage_count, s;
|
||||
struct seg_list *sl;
|
||||
struct glv_list *glvl;
|
||||
int error_count = 0;
|
||||
@ -498,13 +520,13 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
|
||||
inc_error_count;
|
||||
}
|
||||
|
||||
area_multiplier = segtype_is_striped(seg->segtype) ?
|
||||
seg->area_count : 1;
|
||||
|
||||
if (seg->area_len * area_multiplier != seg->len) {
|
||||
log_error("LV %s: segment %u has inconsistent "
|
||||
"area_len %u",
|
||||
lv->name, seg_count, seg->area_len);
|
||||
data_rimage_count = seg->area_count - seg->segtype->parity_devs;
|
||||
/* FIXME: raid varies seg->area_len? */
|
||||
if (seg->len != seg->area_len &&
|
||||
seg->len != seg->area_len * data_rimage_count) {
|
||||
log_error("LV %s: segment %u with len=%u "
|
||||
" has inconsistent area_len %u",
|
||||
lv->name, seg_count, seg->len, seg->area_len);
|
||||
inc_error_count;
|
||||
}
|
||||
|
||||
@ -766,10 +788,10 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
|
||||
/* Clone the existing segment */
|
||||
if (!(split_seg = alloc_lv_segment(seg->segtype,
|
||||
seg->lv, seg->le, seg->len,
|
||||
seg->lv, seg->le, seg->len, seg->reshape_len,
|
||||
seg->status, seg->stripe_size,
|
||||
seg->log_lv,
|
||||
seg->area_count, seg->area_len,
|
||||
seg->area_count, seg->area_len, seg->data_copies,
|
||||
seg->chunk_size, seg->region_size,
|
||||
seg->extents_copied, seg->pvmove_source_seg))) {
|
||||
log_error("Couldn't allocate cloned LV segment.");
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -137,7 +137,12 @@
|
||||
e.g. to prohibit allocation of a RAID image
|
||||
on a PV already holing an image of the RAID set */
|
||||
#define LOCKD_SANLOCK_LV UINT64_C(0x0080000000000000) /* LV - Internal use only */
|
||||
/* Next unused flag: UINT64_C(0x0100000000000000) */
|
||||
#define LV_RESHAPE_DELTA_DISKS_PLUS UINT64_C(0x0100000000000000) /* LV reshape flag delta disks plus image(s) */
|
||||
#define LV_RESHAPE_DELTA_DISKS_MINUS UINT64_C(0x0200000000000000) /* LV reshape flag delta disks minus image(s) */
|
||||
|
||||
#define LV_REMOVE_AFTER_RESHAPE UINT64_C(0x0400000000000000) /* LV needs to be removed after a shrinking reshape */
|
||||
#define LV_METADATA_FORMAT UINT64_C(0x0800000000000000) /* LV has segments with metadata format */
|
||||
/* Next unused flag: UINT64_C(0x1000000000000000) */
|
||||
|
||||
/* Format features flags */
|
||||
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
|
||||
@ -271,18 +276,32 @@ enum {
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
THIN_ZERO_UNSELECTED = 0,
|
||||
THIN_ZERO_NO,
|
||||
THIN_ZERO_YES,
|
||||
} thin_zero_t;
|
||||
|
||||
typedef enum {
|
||||
THIN_DISCARDS_UNSELECTED = 0,
|
||||
THIN_DISCARDS_IGNORE,
|
||||
THIN_DISCARDS_NO_PASSDOWN,
|
||||
THIN_DISCARDS_PASSDOWN,
|
||||
} thin_discards_t;
|
||||
|
||||
typedef enum {
|
||||
CACHE_MODE_UNDEFINED = 0,
|
||||
CACHE_MODE_UNSELECTED = 0,
|
||||
CACHE_MODE_WRITETHROUGH,
|
||||
CACHE_MODE_WRITEBACK,
|
||||
CACHE_MODE_PASSTHROUGH,
|
||||
} cache_mode_t;
|
||||
|
||||
/* ATM used for cache only */
|
||||
typedef enum {
|
||||
CACHE_METADATA_FORMAT_UNSELECTED = 0, /* On input means 'auto' */
|
||||
CACHE_METADATA_FORMAT_1,
|
||||
CACHE_METADATA_FORMAT_2,
|
||||
} cache_metadata_format_t;
|
||||
|
||||
typedef enum {
|
||||
LOCK_TYPE_INVALID = -1,
|
||||
LOCK_TYPE_NONE = 0,
|
||||
@ -446,6 +465,7 @@ struct lv_segment {
|
||||
const struct segment_type *segtype;
|
||||
uint32_t le;
|
||||
uint32_t len;
|
||||
uint32_t reshape_len; /* For RAID: user hidden additional out of place reshaping length off area_len and len */
|
||||
|
||||
uint64_t status;
|
||||
|
||||
@ -454,6 +474,7 @@ struct lv_segment {
|
||||
uint32_t writebehind; /* For RAID (RAID1 only) */
|
||||
uint32_t min_recovery_rate; /* For RAID */
|
||||
uint32_t max_recovery_rate; /* For RAID */
|
||||
uint32_t data_offset; /* For RAID: data offset in sectors on each data component image */
|
||||
uint32_t area_count;
|
||||
uint32_t area_len;
|
||||
uint32_t chunk_size; /* For snapshots/thin_pool. In sectors. */
|
||||
@ -464,6 +485,7 @@ struct lv_segment {
|
||||
struct logical_volume *cow;
|
||||
struct dm_list origin_list;
|
||||
uint32_t region_size; /* For mirrors, replicators - in sectors */
|
||||
uint32_t data_copies; /* For RAID: number of data copies (e.g. 3 for RAID 6 */
|
||||
uint32_t extents_copied;/* Number of extents synced for raids/mirrors */
|
||||
struct logical_volume *log_lv;
|
||||
struct lv_segment *pvmove_source_seg;
|
||||
@ -475,13 +497,14 @@ struct lv_segment {
|
||||
struct lv_segment_area *meta_areas; /* For RAID */
|
||||
struct logical_volume *metadata_lv; /* For thin_pool */
|
||||
uint64_t transaction_id; /* For thin_pool, thin */
|
||||
unsigned zero_new_blocks; /* For thin_pool */
|
||||
thin_zero_t zero_new_blocks; /* For thin_pool */
|
||||
thin_discards_t discards; /* For thin_pool */
|
||||
struct dm_list thin_messages; /* For thin_pool */
|
||||
struct logical_volume *external_lv; /* For thin */
|
||||
struct logical_volume *pool_lv; /* For thin, cache */
|
||||
uint32_t device_id; /* For thin, 24bit */
|
||||
|
||||
cache_metadata_format_t cache_metadata_format;/* For cache_pool */
|
||||
cache_mode_t cache_mode; /* For cache_pool */
|
||||
const char *policy_name; /* For cache_pool */
|
||||
struct dm_config_node *policy_settings; /* For cache_pool */
|
||||
@ -838,26 +861,22 @@ int pool_is_active(const struct logical_volume *pool_lv);
|
||||
int pool_supports_external_origin(const struct lv_segment *pool_seg, const struct logical_volume *external_lv);
|
||||
int thin_pool_feature_supported(const struct logical_volume *pool_lv, int feature);
|
||||
int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
|
||||
int passed_args,
|
||||
int chunk_size_calc_policy);
|
||||
int validate_cache_chunk_size(struct cmd_context *cmd, uint32_t chunk_size);
|
||||
int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size);
|
||||
int validate_pool_chunk_size(struct cmd_context *cmd, const struct segment_type *segtype, uint32_t chunk_size);
|
||||
int update_pool_lv(struct logical_volume *lv, int activate);
|
||||
int update_pool_params(const struct segment_type *segtype,
|
||||
struct volume_group *vg, unsigned target_attr,
|
||||
int passed_args, uint32_t pool_data_extents,
|
||||
uint32_t *pool_metadata_extents,
|
||||
int *chunk_size_calc_policy, uint32_t *chunk_size,
|
||||
thin_discards_t *discards, int *zero);
|
||||
int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profile,
|
||||
int passed_args, int *chunk_size_calc_method,
|
||||
uint32_t *chunk_size, thin_discards_t *discards,
|
||||
int *zero);
|
||||
int update_thin_pool_params(const struct segment_type *segtype,
|
||||
struct volume_group *vg, unsigned attr,
|
||||
int passed_args, uint32_t pool_data_extents,
|
||||
int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct profile *profile,
|
||||
uint32_t *chunk_size, int *chunk_size_calc_method);
|
||||
int update_thin_pool_params(struct cmd_context *cmd,
|
||||
struct profile *profile,
|
||||
uint32_t extent_size,
|
||||
const struct segment_type *segtype,
|
||||
unsigned attr,
|
||||
uint32_t pool_data_extents,
|
||||
uint32_t *pool_metadata_extents,
|
||||
int *chunk_size_calc_method, uint32_t *chunk_size,
|
||||
thin_discards_t *discards, int *zero);
|
||||
thin_discards_t *discards, thin_zero_t *zero_new_blocks);
|
||||
const char *get_pool_discards_name(thin_discards_t discards);
|
||||
int set_pool_discards(thin_discards_t *discards, const char *str);
|
||||
struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
|
||||
@ -909,8 +928,8 @@ struct lvcreate_params {
|
||||
int wipe_signatures; /* all */
|
||||
int32_t major; /* all */
|
||||
int32_t minor; /* all */
|
||||
int log_count; /* mirror */
|
||||
int nosync; /* mirror */
|
||||
int log_count; /* mirror/RAID */
|
||||
int nosync; /* mirror/RAID */
|
||||
int pool_metadata_spare; /* pools */
|
||||
int type; /* type arg is given */
|
||||
int temporary; /* temporary LV */
|
||||
@ -920,6 +939,7 @@ struct lvcreate_params {
|
||||
int activation_skip; /* activation skip flags */
|
||||
activation_change_t activate; /* non-snapshot, non-mirror */
|
||||
thin_discards_t discards; /* thin */
|
||||
thin_zero_t zero_new_blocks;
|
||||
#define THIN_CHUNK_SIZE_CALC_METHOD_GENERIC 0x01
|
||||
#define THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE 0x02
|
||||
int thin_chunk_size_calc_policy;
|
||||
@ -933,27 +953,20 @@ struct lvcreate_params {
|
||||
|
||||
const char *lock_args;
|
||||
|
||||
/* Keep args given by the user on command line */
|
||||
/* FIXME: create some more universal solution here */
|
||||
#define PASS_ARG_CHUNK_SIZE 0x01
|
||||
#define PASS_ARG_DISCARDS 0x02
|
||||
#define PASS_ARG_POOL_METADATA_SIZE 0x04
|
||||
#define PASS_ARG_ZERO 0x08
|
||||
int passed_args;
|
||||
|
||||
uint32_t stripes; /* striped */
|
||||
uint32_t stripe_size; /* striped */
|
||||
uint32_t stripes; /* striped/RAID */
|
||||
uint32_t stripe_size; /* striped/RAID */
|
||||
uint32_t chunk_size; /* snapshot */
|
||||
uint32_t region_size; /* mirror */
|
||||
uint32_t region_size; /* mirror/RAID */
|
||||
|
||||
unsigned stripes_supplied; /* striped */
|
||||
unsigned stripe_size_supplied; /* striped */
|
||||
unsigned stripes_supplied; /* striped/RAID */
|
||||
unsigned stripe_size_supplied; /* striped/RAID */
|
||||
|
||||
uint32_t mirrors; /* mirror */
|
||||
uint32_t mirrors; /* mirror/RAID */
|
||||
|
||||
uint32_t min_recovery_rate; /* RAID */
|
||||
uint32_t max_recovery_rate; /* RAID */
|
||||
|
||||
cache_metadata_format_t cache_metadata_format; /* cache */
|
||||
cache_mode_t cache_mode; /* cache */
|
||||
const char *policy_name; /* cache */
|
||||
struct dm_config_tree *policy_settings; /* cache */
|
||||
@ -1205,10 +1218,14 @@ struct logical_volume *first_replicator_dev(const struct logical_volume *lv);
|
||||
int lv_is_raid_with_tracking(const struct logical_volume *lv);
|
||||
uint32_t lv_raid_image_count(const struct logical_volume *lv);
|
||||
int lv_raid_change_image_count(struct logical_volume *lv,
|
||||
uint32_t new_count, struct dm_list *allocate_pvs);
|
||||
int lv_raid_split(struct logical_volume *lv, const char *split_name,
|
||||
int yes,
|
||||
uint32_t new_count,
|
||||
uint32_t new_region_size,
|
||||
struct dm_list *allocate_pvs);
|
||||
int lv_raid_split(struct logical_volume *lv, int yes, const char *split_name,
|
||||
uint32_t new_count, struct dm_list *splittable_pvs);
|
||||
int lv_raid_split_and_track(struct logical_volume *lv,
|
||||
int yes,
|
||||
struct dm_list *splittable_pvs);
|
||||
int lv_raid_merge(struct logical_volume *lv);
|
||||
int lv_raid_convert(struct logical_volume *lv,
|
||||
@ -1233,6 +1250,8 @@ uint32_t raid_ensure_min_region_size(const struct logical_volume *lv, uint64_t r
|
||||
int lv_raid_change_region_size(struct logical_volume *lv,
|
||||
int yes, int force, uint32_t new_region_size);
|
||||
int lv_raid_in_sync(const struct logical_volume *lv);
|
||||
uint32_t lv_raid_data_copies(const struct segment_type *segtype, uint32_t area_count);
|
||||
int lv_raid_free_reshape_space(const struct logical_volume *lv);
|
||||
/* -- metadata/raid_manip.c */
|
||||
|
||||
/* ++ metadata/cache_manip.c */
|
||||
@ -1248,17 +1267,22 @@ const char *display_cache_mode(const struct lv_segment *seg);
|
||||
const char *get_cache_mode_name(const struct lv_segment *cache_seg);
|
||||
int set_cache_mode(cache_mode_t *mode, const char *cache_mode);
|
||||
int cache_set_cache_mode(struct lv_segment *cache_seg, cache_mode_t mode);
|
||||
int cache_set_metadata_format(struct lv_segment *cache_seg, cache_metadata_format_t format);
|
||||
int cache_set_policy(struct lv_segment *cache_seg, const char *name,
|
||||
const struct dm_config_tree *settings);
|
||||
int cache_set_params(struct lv_segment *seg,
|
||||
uint32_t chunk_size,
|
||||
cache_metadata_format_t format,
|
||||
cache_mode_t mode,
|
||||
const char *policy_name,
|
||||
const struct dm_config_tree *policy_settings,
|
||||
uint32_t chunk_size);
|
||||
const struct dm_config_tree *policy_settings);
|
||||
void cache_check_for_warns(const struct lv_segment *seg);
|
||||
int update_cache_pool_params(const struct segment_type *segtype,
|
||||
struct volume_group *vg, unsigned attr,
|
||||
int passed_args, uint32_t pool_data_extents,
|
||||
int update_cache_pool_params(struct cmd_context *cmd,
|
||||
struct profile *profile,
|
||||
uint32_t extent_size,
|
||||
const struct segment_type *segtype,
|
||||
unsigned attr,
|
||||
uint32_t pool_data_extents,
|
||||
uint32_t *pool_metadata_extents,
|
||||
int *chunk_size_calc_method, uint32_t *chunk_size);
|
||||
int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size);
|
||||
|
@ -394,44 +394,13 @@ int validate_pool_chunk_size(struct cmd_context *cmd,
|
||||
const struct segment_type *segtype,
|
||||
uint32_t chunk_size)
|
||||
{
|
||||
uint32_t min_size, max_size;
|
||||
const char *name;
|
||||
int r = 1;
|
||||
if (segtype_is_cache(segtype) || segtype_is_cache_pool(segtype))
|
||||
return validate_cache_chunk_size(cmd, chunk_size);
|
||||
|
||||
if (segtype_is_cache(segtype) || segtype_is_cache_pool(segtype)) {
|
||||
min_size = DM_CACHE_MIN_DATA_BLOCK_SIZE;
|
||||
max_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
|
||||
name = "Cache";
|
||||
} else if (segtype_is_thin(segtype)) {
|
||||
min_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
|
||||
max_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
|
||||
name = "Thin";
|
||||
} else {
|
||||
log_error(INTERNAL_ERROR "Cannot validate chunk size of "
|
||||
"%s segtype.", segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((chunk_size < min_size) || (chunk_size > max_size)) {
|
||||
log_error("%s pool chunk size %s is not in the range %s to %s.",
|
||||
name, display_size(cmd, chunk_size),
|
||||
display_size(cmd, min_size),
|
||||
display_size(cmd, max_size));
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (chunk_size & (min_size - 1)) {
|
||||
log_error("%s pool chunk size %s must be a multiple of %s.",
|
||||
name, display_size(cmd, chunk_size),
|
||||
display_size(cmd, min_size));
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
return validate_thin_pool_chunk_size(cmd, chunk_size);
|
||||
}
|
||||
|
||||
int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
|
||||
int passed_args,
|
||||
int chunk_size_calc_policy)
|
||||
{
|
||||
struct logical_volume *pool_data_lv;
|
||||
@ -439,24 +408,17 @@ int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
|
||||
struct physical_volume *pv;
|
||||
struct cmd_context *cmd = pool_lv->vg->cmd;
|
||||
unsigned long previous_hint = 0, hint = 0;
|
||||
uint32_t default_chunk_size;
|
||||
uint32_t min_chunk_size, max_chunk_size;
|
||||
|
||||
if (passed_args & PASS_ARG_CHUNK_SIZE)
|
||||
return 1;
|
||||
if (!chunk_size_calc_policy)
|
||||
return 1; /* Chunk size was specified by user */
|
||||
|
||||
if (lv_is_thin_pool(pool_lv)) {
|
||||
if (find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, NULL))
|
||||
return 1;
|
||||
min_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
|
||||
max_chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
|
||||
default_chunk_size = get_default_allocation_thin_pool_chunk_size_CFG(cmd, NULL);
|
||||
} else if (lv_is_cache_pool(pool_lv)) {
|
||||
if (find_config_tree_int(cmd, allocation_cache_pool_chunk_size_CFG, NULL))
|
||||
return 1;
|
||||
min_chunk_size = DM_CACHE_MIN_DATA_BLOCK_SIZE;
|
||||
max_chunk_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
|
||||
default_chunk_size = get_default_allocation_cache_pool_chunk_size_CFG(cmd, NULL);
|
||||
} else {
|
||||
log_error(INTERNAL_ERROR "%s is not a pool logical volume.", display_lvname(pool_lv));
|
||||
return 0;
|
||||
@ -494,40 +456,14 @@ int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
|
||||
display_size(cmd, hint), display_lvname(pool_lv),
|
||||
display_size(cmd, min_chunk_size),
|
||||
display_size(cmd, max_chunk_size));
|
||||
else
|
||||
first_seg(pool_lv)->chunk_size =
|
||||
(hint >= default_chunk_size) ? hint : default_chunk_size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int update_pool_params(const struct segment_type *segtype,
|
||||
struct volume_group *vg, unsigned target_attr,
|
||||
int passed_args, uint32_t pool_data_extents,
|
||||
uint32_t *pool_metadata_extents,
|
||||
int *chunk_size_calc_policy, uint32_t *chunk_size,
|
||||
thin_discards_t *discards, int *zero)
|
||||
{
|
||||
if (segtype_is_cache_pool(segtype) || segtype_is_cache(segtype)) {
|
||||
if (!update_cache_pool_params(segtype, vg, target_attr, passed_args,
|
||||
pool_data_extents, pool_metadata_extents,
|
||||
chunk_size_calc_policy, chunk_size))
|
||||
return_0;
|
||||
} else if (!update_thin_pool_params(segtype, vg, target_attr, passed_args,
|
||||
pool_data_extents, pool_metadata_extents,
|
||||
chunk_size_calc_policy, chunk_size,
|
||||
discards, zero)) /* thin-pool */
|
||||
return_0;
|
||||
|
||||
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * vg->extent_size) {
|
||||
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
|
||||
segtype->name, display_size(vg->cmd, *chunk_size));
|
||||
return 0;
|
||||
else if (hint > first_seg(pool_lv)->chunk_size) {
|
||||
log_debug_alloc("Updating chunk size %s for pool %s to %s.",
|
||||
display_size(cmd, first_seg(pool_lv)->chunk_size),
|
||||
display_lvname(pool_lv),
|
||||
display_size(cmd, hint));
|
||||
first_seg(pool_lv)->chunk_size = hint;
|
||||
}
|
||||
|
||||
log_verbose("Preferred pool metadata size %s.",
|
||||
display_size(vg->cmd, (uint64_t)*pool_metadata_extents * vg->extent_size));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,8 @@ struct segment_type *get_segtype_from_flag(struct cmd_context *cmd, uint64_t fla
|
||||
{
|
||||
struct segment_type *segtype;
|
||||
|
||||
dm_list_iterate_items(segtype, &cmd->segtypes)
|
||||
/* Iterate backwards to provide aliases; e.g. raid5 instead of raid5_ls */
|
||||
dm_list_iterate_back_items(segtype, &cmd->segtypes)
|
||||
if (flag & segtype->flags)
|
||||
return segtype;
|
||||
|
||||
|
@ -140,7 +140,11 @@ struct dev_manager;
|
||||
#define segtype_is_any_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
|
||||
#define segtype_is_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
|
||||
#define segtype_is_raid10_near(segtype) segtype_is_raid10(segtype)
|
||||
/* FIXME: once raid10_offset supported */
|
||||
#define segtype_is_raid10_offset(segtype) 0 // ((segtype)->flags & SEG_RAID10_OFFSET ? 1 : 0)
|
||||
#define segtype_is_raid_with_meta(segtype) (segtype_is_raid(segtype) && !segtype_is_raid0(segtype))
|
||||
#define segtype_is_striped_raid(segtype) (segtype_is_raid(segtype) && !segtype_is_raid1(segtype))
|
||||
#define segtype_is_reshapable_raid(segtype) ((segtype_is_striped_raid(segtype) && !segtype_is_any_raid0(segtype)) || segtype_is_raid10_near(segtype) || segtype_is_raid10_offset(segtype))
|
||||
#define segtype_is_snapshot(segtype) ((segtype)->flags & SEG_SNAPSHOT ? 1 : 0)
|
||||
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
|
||||
#define segtype_is_thin(segtype) ((segtype)->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0)
|
||||
@ -190,6 +194,8 @@ struct dev_manager;
|
||||
#define seg_is_raid10(seg) segtype_is_raid10((seg)->segtype)
|
||||
#define seg_is_raid10_near(seg) segtype_is_raid10_near((seg)->segtype)
|
||||
#define seg_is_raid_with_meta(seg) segtype_is_raid_with_meta((seg)->segtype)
|
||||
#define seg_is_striped_raid(seg) segtype_is_striped_raid((seg)->segtype)
|
||||
#define seg_is_reshapable_raid(seg) segtype_is_reshapable_raid((seg)->segtype)
|
||||
#define seg_is_replicator(seg) ((seg)->segtype->flags & SEG_REPLICATOR ? 1 : 0)
|
||||
#define seg_is_replicator_dev(seg) ((seg)->segtype->flags & SEG_REPLICATOR_DEV ? 1 : 0)
|
||||
#define seg_is_snapshot(seg) segtype_is_snapshot((seg)->segtype)
|
||||
@ -280,6 +286,7 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
|
||||
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */
|
||||
#define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */
|
||||
#define RAID_FEATURE_RAID4 (1U << 3) /* ! version 1.8 or 1.9.0 */
|
||||
#define RAID_FEATURE_RESHAPE (1U << 4) /* version 1.10.1 */
|
||||
|
||||
#ifdef RAID_INTERNAL
|
||||
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
|
||||
@ -308,6 +315,7 @@ int init_cache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
|
||||
|
||||
#define CACHE_FEATURE_POLICY_MQ (1U << 0)
|
||||
#define CACHE_FEATURE_POLICY_SMQ (1U << 1)
|
||||
#define CACHE_FEATURE_METADATA2 (1U << 2)
|
||||
|
||||
#define SNAPSHOT_FEATURE_FIXED_LEAK (1U << 0) /* version 1.12 */
|
||||
|
||||
|
@ -238,8 +238,8 @@ static struct lv_segment *_alloc_snapshot_seg(struct logical_volume *lv)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, 0, lv->le_count, 0, 0,
|
||||
NULL, 0, lv->le_count, 0, 0, 0, NULL))) {
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, 0, lv->le_count, 0, 0, 0,
|
||||
NULL, 0, lv->le_count, 0, 0, 0, 0, NULL))) {
|
||||
log_error("Couldn't allocate new snapshot segment.");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -58,13 +58,13 @@
|
||||
#define r1__r0m _takeover_from_raid1_to_raid0_meta
|
||||
#define r1__r1 _takeover_from_raid1_to_raid1
|
||||
#define r1__r10 _takeover_from_raid1_to_raid10
|
||||
#define r1__r45 _takeover_from_raid1_to_raid45
|
||||
#define r1__r5 _takeover_from_raid1_to_raid5
|
||||
#define r1__str _takeover_from_raid1_to_striped
|
||||
#define r45_lin _takeover_from_raid45_to_linear
|
||||
#define r45_mir _takeover_from_raid45_to_mirrored
|
||||
#define r45_r0 _takeover_from_raid45_to_raid0
|
||||
#define r45_r0m _takeover_from_raid45_to_raid0_meta
|
||||
#define r45_r1 _takeover_from_raid45_to_raid1
|
||||
#define r5_r1 _takeover_from_raid5_to_raid1
|
||||
#define r45_r54 _takeover_from_raid45_to_raid54
|
||||
#define r45_r6 _takeover_from_raid45_to_raid6
|
||||
#define r45_str _takeover_from_raid45_to_striped
|
||||
@ -109,8 +109,8 @@ static takeover_fn_t _takeover_fns[][11] = {
|
||||
/* mirror */ { X , X , N , mir_r0, mir_r0m, mir_r1, mir_r45, X , mir_r10, X , X },
|
||||
/* raid0 */ { r0__lin, r0__str, r0__mir, N , r0__r0m, r0__r1, r0__r45, r0__r6, r0__r10, X , X },
|
||||
/* raid0_meta */ { r0m_lin, r0m_str, r0m_mir, r0m_r0, N , r0m_r1, r0m_r45, r0m_r6, r0m_r10, X , X },
|
||||
/* raid1 */ { r1__lin, r1__str, r1__mir, r1__r0, r1__r0m, r1__r1, r1__r45, X , r1__r10, X , X },
|
||||
/* raid4/5 */ { r45_lin, r45_str, r45_mir, r45_r0, r45_r0m, r45_r1, r45_r54, r45_r6, X , X , X },
|
||||
/* raid1 */ { r1__lin, r1__str, r1__mir, r1__r0, r1__r0m, r1__r1, r1__r5, X , r1__r10, X , X },
|
||||
/* raid4/5 */ { r45_lin, r45_str, r45_mir, r45_r0, r45_r0m, r5_r1 , r45_r54, r45_r6, X , X , X },
|
||||
/* raid6 */ { X , r6__str, X , r6__r0, r6__r0m, X , r6__r45, X , X , X , X },
|
||||
/* raid10 */ { r10_lin, r10_str, r10_mir, r10_r0, r10_r0m, r10_r1, X , X , X , X , X },
|
||||
/* raid01 */ // { X , r01_str, X , X , X , X , X , X , r01_r10, r01_r01, X },
|
||||
|
@ -547,19 +547,31 @@ int update_pool_lv(struct logical_volume *lv, int activate)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Estimate thin pool chunk size from data and metadata size (in sector units) */
|
||||
static size_t _estimate_chunk_size(uint64_t data_size, uint64_t metadata_size, int attr)
|
||||
static uint64_t _estimate_size(uint32_t data_extents, uint32_t extent_size, uint64_t size)
|
||||
{
|
||||
/*
|
||||
* nr_pool_blocks = data_size / metadata_size
|
||||
* chunk_size = nr_pool_blocks * 64b / sector_size
|
||||
*/
|
||||
size_t chunk_size = data_size / (metadata_size * (SECTOR_SIZE / 64));
|
||||
return (uint64_t) data_extents * extent_size / (size * (SECTOR_SIZE / UINT64_C(64)));
|
||||
}
|
||||
|
||||
/* Estimate thin pool metadata size from data size and chunks size (in sector units) */
|
||||
static uint64_t _estimate_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size)
|
||||
{
|
||||
return _estimate_size(data_extents, extent_size, chunk_size);
|
||||
}
|
||||
|
||||
/* Estimate thin pool chunk size from data and metadata size (in sector units) */
|
||||
static uint32_t _estimate_chunk_size(uint32_t data_extents, uint32_t extent_size,
|
||||
uint64_t metadata_size, int attr)
|
||||
{
|
||||
uint32_t chunk_size = _estimate_size(data_extents, extent_size, metadata_size);
|
||||
|
||||
if (attr & THIN_FEATURE_BLOCK_SIZE) {
|
||||
/* Round up to 64KB */
|
||||
chunk_size += DM_THIN_MIN_DATA_BLOCK_SIZE - 1;
|
||||
chunk_size &= ~(size_t)(DM_THIN_MIN_DATA_BLOCK_SIZE - 1);
|
||||
chunk_size &= ~(uint32_t)(DM_THIN_MIN_DATA_BLOCK_SIZE - 1);
|
||||
} else {
|
||||
/* Round up to nearest power of 2 */
|
||||
chunk_size--;
|
||||
@ -571,47 +583,64 @@ static size_t _estimate_chunk_size(uint64_t data_size, uint64_t metadata_size, i
|
||||
chunk_size++;
|
||||
}
|
||||
|
||||
if (chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE)
|
||||
chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
|
||||
else if (chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE)
|
||||
chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
|
||||
|
||||
return chunk_size;
|
||||
}
|
||||
|
||||
int update_thin_pool_params(const struct segment_type *segtype,
|
||||
struct volume_group *vg,
|
||||
unsigned attr, int passed_args,
|
||||
int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct profile *profile,
|
||||
uint32_t *chunk_size, int *chunk_size_calc_method)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
if (!(str = find_config_tree_str(cmd, allocation_thin_pool_chunk_size_policy_CFG, profile))) {
|
||||
log_error(INTERNAL_ERROR "Cannot find configuration.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcasecmp(str, "generic")) {
|
||||
*chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2;
|
||||
*chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_GENERIC;
|
||||
} else if (!strcasecmp(str, "performance")) {
|
||||
*chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE * 2;
|
||||
*chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE;
|
||||
} else {
|
||||
log_error("Thin pool chunk size calculation policy \"%s\" is unrecognised.", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int update_thin_pool_params(struct cmd_context *cmd,
|
||||
struct profile *profile,
|
||||
uint32_t extent_size,
|
||||
const struct segment_type *segtype,
|
||||
unsigned attr,
|
||||
uint32_t pool_data_extents,
|
||||
uint32_t *pool_metadata_extents,
|
||||
int *chunk_size_calc_method, uint32_t *chunk_size,
|
||||
thin_discards_t *discards, int *zero)
|
||||
thin_discards_t *discards, thin_zero_t *zero_new_blocks)
|
||||
{
|
||||
struct cmd_context *cmd = vg->cmd;
|
||||
struct profile *profile = vg->profile;
|
||||
uint32_t extent_size = vg->extent_size;
|
||||
uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
|
||||
size_t estimate_chunk_size;
|
||||
uint32_t estimate_chunk_size;
|
||||
const char *str;
|
||||
|
||||
if (!(passed_args & PASS_ARG_CHUNK_SIZE)) {
|
||||
if (!(*chunk_size = find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, profile) * 2)) {
|
||||
if (!(str = find_config_tree_str(cmd, allocation_thin_pool_chunk_size_policy_CFG, profile))) {
|
||||
log_error(INTERNAL_ERROR "Could not find configuration.");
|
||||
return 0;
|
||||
}
|
||||
if (!strcasecmp(str, "generic"))
|
||||
*chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_GENERIC;
|
||||
else if (!strcasecmp(str, "performance"))
|
||||
*chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE;
|
||||
else {
|
||||
log_error("Thin pool chunk size calculation policy \"%s\" is unrecognised.", str);
|
||||
return 0;
|
||||
}
|
||||
if (!(*chunk_size = get_default_allocation_thin_pool_chunk_size_CFG(cmd, profile)))
|
||||
return_0;
|
||||
}
|
||||
if (!*chunk_size &&
|
||||
find_config_tree_node(cmd, allocation_thin_pool_chunk_size_CFG, profile))
|
||||
*chunk_size = find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, profile) * 2;
|
||||
|
||||
if (*chunk_size && !(attr & THIN_FEATURE_BLOCK_SIZE) &&
|
||||
!is_power_of_2(*chunk_size)) {
|
||||
log_error("Chunk size must be a power of 2 for this thin target version.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!validate_pool_chunk_size(cmd, segtype, *chunk_size))
|
||||
return_0;
|
||||
|
||||
if (!(passed_args & PASS_ARG_DISCARDS)) {
|
||||
if ((*discards == THIN_DISCARDS_UNSELECTED) &&
|
||||
find_config_tree_node(cmd, allocation_thin_pool_discards_CFG, profile)) {
|
||||
if (!(str = find_config_tree_str(cmd, allocation_thin_pool_discards_CFG, profile))) {
|
||||
log_error(INTERNAL_ERROR "Could not find configuration.");
|
||||
return 0;
|
||||
@ -620,21 +649,22 @@ int update_thin_pool_params(const struct segment_type *segtype,
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!(passed_args & PASS_ARG_ZERO))
|
||||
*zero = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile);
|
||||
|
||||
if (!(attr & THIN_FEATURE_BLOCK_SIZE) &&
|
||||
!is_power_of_2(*chunk_size)) {
|
||||
log_error("Chunk size must be a power of 2 for this thin target version.");
|
||||
return 0;
|
||||
}
|
||||
if (zero_new_blocks &&
|
||||
(*zero_new_blocks == THIN_ZERO_UNSELECTED) &&
|
||||
find_config_tree_node(cmd, allocation_thin_pool_zero_CFG, profile))
|
||||
*zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile)
|
||||
? THIN_ZERO_YES : THIN_ZERO_NO;
|
||||
|
||||
if (!pool_metadata_size) {
|
||||
/* Defaults to nr_pool_blocks * 64b converted to size in sectors */
|
||||
pool_metadata_size = (uint64_t) pool_data_extents * extent_size /
|
||||
(*chunk_size * (SECTOR_SIZE / UINT64_C(64)));
|
||||
/* Check if we could eventually use bigger chunk size */
|
||||
if (!(passed_args & PASS_ARG_CHUNK_SIZE)) {
|
||||
if (!*chunk_size) {
|
||||
if (!get_default_allocation_thin_pool_chunk_size(cmd, profile,
|
||||
chunk_size,
|
||||
chunk_size_calc_method))
|
||||
return_0;
|
||||
|
||||
pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size);
|
||||
|
||||
/* Check if we should eventually use bigger chunk size */
|
||||
while ((pool_metadata_size >
|
||||
(DEFAULT_THIN_POOL_OPTIMAL_SIZE / SECTOR_SIZE)) &&
|
||||
(*chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE)) {
|
||||
@ -643,29 +673,28 @@ int update_thin_pool_params(const struct segment_type *segtype,
|
||||
}
|
||||
log_verbose("Setting chunk size to %s.",
|
||||
display_size(cmd, *chunk_size));
|
||||
} else if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
|
||||
/* Suggest bigger chunk size */
|
||||
estimate_chunk_size =
|
||||
_estimate_chunk_size((uint64_t) pool_data_extents * extent_size,
|
||||
(DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
|
||||
log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
|
||||
display_size(cmd, estimate_chunk_size));
|
||||
} else {
|
||||
pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size);
|
||||
|
||||
if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
|
||||
/* Suggest bigger chunk size */
|
||||
estimate_chunk_size =
|
||||
_estimate_chunk_size(pool_data_extents, extent_size,
|
||||
(DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
|
||||
log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
|
||||
display_size(cmd, estimate_chunk_size));
|
||||
}
|
||||
}
|
||||
|
||||
/* Round up to extent size silently */
|
||||
if (pool_metadata_size % extent_size)
|
||||
pool_metadata_size += extent_size - pool_metadata_size % extent_size;
|
||||
} else {
|
||||
estimate_chunk_size =
|
||||
_estimate_chunk_size((uint64_t) pool_data_extents * extent_size,
|
||||
pool_metadata_size, attr);
|
||||
if (estimate_chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE)
|
||||
estimate_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
|
||||
else if (estimate_chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE)
|
||||
estimate_chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
|
||||
estimate_chunk_size = _estimate_chunk_size(pool_data_extents, extent_size,
|
||||
pool_metadata_size, attr);
|
||||
|
||||
/* Check to eventually use bigger chunk size */
|
||||
if (!(passed_args & PASS_ARG_CHUNK_SIZE)) {
|
||||
if (!*chunk_size) {
|
||||
*chunk_size = estimate_chunk_size;
|
||||
log_verbose("Setting chunk size %s.", display_size(cmd, *chunk_size));
|
||||
} else if (*chunk_size < estimate_chunk_size) {
|
||||
@ -675,22 +704,41 @@ int update_thin_pool_params(const struct segment_type *segtype,
|
||||
}
|
||||
}
|
||||
|
||||
if (!validate_thin_pool_chunk_size(cmd, *chunk_size))
|
||||
return_0;
|
||||
|
||||
if (pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
|
||||
pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
|
||||
if (passed_args & PASS_ARG_POOL_METADATA_SIZE)
|
||||
if (*pool_metadata_extents)
|
||||
log_warn("WARNING: Maximum supported pool metadata size is %s.",
|
||||
display_size(cmd, pool_metadata_size));
|
||||
} else if (pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
|
||||
pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
|
||||
if (passed_args & PASS_ARG_POOL_METADATA_SIZE)
|
||||
if (*pool_metadata_extents)
|
||||
log_warn("WARNING: Minimum supported pool metadata size is %s.",
|
||||
display_size(cmd, pool_metadata_size));
|
||||
}
|
||||
|
||||
if (!(*pool_metadata_extents =
|
||||
extents_from_size(vg->cmd, pool_metadata_size, extent_size)))
|
||||
extents_from_size(cmd, pool_metadata_size, extent_size)))
|
||||
return_0;
|
||||
|
||||
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
|
||||
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
|
||||
segtype->name, display_size(cmd, *chunk_size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((*discards == THIN_DISCARDS_UNSELECTED) &&
|
||||
!set_pool_discards(discards, DEFAULT_THIN_POOL_DISCARDS))
|
||||
return_0;
|
||||
|
||||
if (*zero_new_blocks == THIN_ZERO_UNSELECTED)
|
||||
*zero_new_blocks = (DEFAULT_THIN_POOL_ZERO) ? THIN_ZERO_YES : THIN_ZERO_NO;
|
||||
|
||||
log_verbose("Preferred pool metadata size %s.",
|
||||
display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -719,11 +767,10 @@ const char *get_pool_discards_name(thin_discards_t discards)
|
||||
return "nopassdown";
|
||||
case THIN_DISCARDS_IGNORE:
|
||||
return "ignore";
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "Unknown discards type encountered.");
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
log_error(INTERNAL_ERROR "Unknown discards type encountered.");
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snap_count)
|
||||
@ -734,20 +781,16 @@ int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snap_count)
|
||||
if (snap_count)
|
||||
*snap_count = 0;
|
||||
|
||||
if (!lv_is_thin_volume(lv) ||
|
||||
dm_list_empty(&lv->segs_using_this_lv))
|
||||
return 0;
|
||||
if (lv_is_thin_volume(lv))
|
||||
dm_list_iterate_items(segl, &lv->segs_using_this_lv)
|
||||
if (segl->seg->origin == lv) {
|
||||
r = 1;
|
||||
|
||||
if (!snap_count)
|
||||
break;/* not interested in number of snapshots */
|
||||
|
||||
dm_list_iterate_items(segl, &lv->segs_using_this_lv) {
|
||||
if (segl->seg->origin == lv) {
|
||||
r = 1;
|
||||
if (snap_count)
|
||||
(*snap_count)++;
|
||||
else
|
||||
/* not interested in number of snapshots */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -816,3 +859,27 @@ int check_new_thin_pool(const struct logical_volume *pool_lv)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
|
||||
{
|
||||
const uint32_t min_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
|
||||
const uint32_t max_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
|
||||
int r = 1;
|
||||
|
||||
if ((chunk_size < min_size) || (chunk_size > max_size)) {
|
||||
log_error("Thin pool chunk size %s is not in the range %s to %s.",
|
||||
display_size(cmd, chunk_size),
|
||||
display_size(cmd, min_size),
|
||||
display_size(cmd, max_size));
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (chunk_size & (min_size - 1)) {
|
||||
log_error("Thin pool chunk size %s must be a multiple of %s.",
|
||||
display_size(cmd, chunk_size),
|
||||
display_size(cmd, min_size));
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
165
lib/raid/raid.c
165
lib/raid/raid.c
@ -137,6 +137,7 @@ static int _raid_text_import(struct lv_segment *seg,
|
||||
} raid_attr_import[] = {
|
||||
{ "region_size", &seg->region_size },
|
||||
{ "stripe_size", &seg->stripe_size },
|
||||
{ "data_copies", &seg->data_copies },
|
||||
{ "writebehind", &seg->writebehind },
|
||||
{ "min_recovery_rate", &seg->min_recovery_rate },
|
||||
{ "max_recovery_rate", &seg->max_recovery_rate },
|
||||
@ -146,6 +147,10 @@ static int _raid_text_import(struct lv_segment *seg,
|
||||
for (i = 0; i < DM_ARRAY_SIZE(raid_attr_import); i++, aip++) {
|
||||
if (dm_config_has_node(sn, aip->name)) {
|
||||
if (!dm_config_get_uint32(sn, aip->name, aip->var)) {
|
||||
if (!strcmp(aip->name, "data_copies")) {
|
||||
*aip->var = 0;
|
||||
continue;
|
||||
}
|
||||
log_error("Couldn't read '%s' for segment %s of logical volume %s.",
|
||||
aip->name, dm_config_parent_name(sn), seg->lv->name);
|
||||
return 0;
|
||||
@ -165,6 +170,9 @@ static int _raid_text_import(struct lv_segment *seg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (seg->data_copies < 2)
|
||||
seg->data_copies = lv_raid_data_copies(seg->segtype, seg->area_count);
|
||||
|
||||
if (seg_is_any_raid0(seg))
|
||||
seg->area_len /= seg->area_count;
|
||||
|
||||
@ -183,18 +191,31 @@ static int _raid_text_export_raid0(const struct lv_segment *seg, struct formatte
|
||||
|
||||
static int _raid_text_export_raid(const struct lv_segment *seg, struct formatter *f)
|
||||
{
|
||||
outf(f, "device_count = %u", seg->area_count);
|
||||
int raid0 = seg_is_any_raid0(seg);
|
||||
|
||||
if (raid0)
|
||||
outfc(f, (seg->area_count == 1) ? "# linear" : NULL,
|
||||
"stripe_count = %u", seg->area_count);
|
||||
|
||||
else {
|
||||
outf(f, "device_count = %u", seg->area_count);
|
||||
if (seg_is_any_raid10(seg) && seg->data_copies > 0)
|
||||
outf(f, "data_copies = %" PRIu32, seg->data_copies);
|
||||
if (seg->region_size)
|
||||
outf(f, "region_size = %" PRIu32, seg->region_size);
|
||||
}
|
||||
|
||||
if (seg->stripe_size)
|
||||
outf(f, "stripe_size = %" PRIu32, seg->stripe_size);
|
||||
if (seg->region_size)
|
||||
outf(f, "region_size = %" PRIu32, seg->region_size);
|
||||
if (seg->writebehind)
|
||||
outf(f, "writebehind = %" PRIu32, seg->writebehind);
|
||||
if (seg->min_recovery_rate)
|
||||
outf(f, "min_recovery_rate = %" PRIu32, seg->min_recovery_rate);
|
||||
if (seg->max_recovery_rate)
|
||||
outf(f, "max_recovery_rate = %" PRIu32, seg->max_recovery_rate);
|
||||
|
||||
if (!raid0) {
|
||||
if (seg_is_raid1(seg) && seg->writebehind)
|
||||
outf(f, "writebehind = %" PRIu32, seg->writebehind);
|
||||
if (seg->min_recovery_rate)
|
||||
outf(f, "min_recovery_rate = %" PRIu32, seg->min_recovery_rate);
|
||||
if (seg->max_recovery_rate)
|
||||
outf(f, "max_recovery_rate = %" PRIu32, seg->max_recovery_rate);
|
||||
}
|
||||
|
||||
return out_areas(f, seg, "raid");
|
||||
}
|
||||
@ -216,14 +237,16 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
|
||||
struct dm_tree_node *node, uint64_t len,
|
||||
uint32_t *pvmove_mirror_count __attribute__((unused)))
|
||||
{
|
||||
int delta_disks = 0, delta_disks_minus = 0, delta_disks_plus = 0, data_offset = 0;
|
||||
uint32_t s;
|
||||
uint64_t flags = 0;
|
||||
uint64_t rebuilds = 0;
|
||||
uint64_t writemostly = 0;
|
||||
struct dm_tree_node_raid_params params;
|
||||
int raid0 = seg_is_any_raid0(seg);
|
||||
uint64_t rebuilds[RAID_BITMAP_SIZE];
|
||||
uint64_t writemostly[RAID_BITMAP_SIZE];
|
||||
struct dm_tree_node_raid_params_v2 params;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
memset(&rebuilds, 0, sizeof(rebuilds));
|
||||
memset(&writemostly, 0, sizeof(writemostly));
|
||||
|
||||
if (!seg->area_count) {
|
||||
log_error(INTERNAL_ERROR "_raid_add_target_line called "
|
||||
@ -232,64 +255,85 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
|
||||
}
|
||||
|
||||
/*
|
||||
* 64 device restriction imposed by kernel as well. It is
|
||||
* not strictly a userspace limitation.
|
||||
* 253 device restriction imposed by kernel due to MD and dm-raid bitfield limitation in superblock.
|
||||
* It is not strictly a userspace limitation.
|
||||
*/
|
||||
if (seg->area_count > 64) {
|
||||
log_error("Unable to handle more than 64 devices in a "
|
||||
"single RAID array");
|
||||
if (seg->area_count > DEFAULT_RAID_MAX_IMAGES) {
|
||||
log_error("Unable to handle more than %u devices in a "
|
||||
"single RAID array", DEFAULT_RAID_MAX_IMAGES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!raid0) {
|
||||
if (!seg_is_any_raid0(seg)) {
|
||||
if (!seg->region_size) {
|
||||
log_error("Missing region size for mirror segment.");
|
||||
log_error("Missing region size for raid segment in %s.",
|
||||
seg_lv(seg, 0)->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (s = 0; s < seg->area_count; s++)
|
||||
if (seg_lv(seg, s)->status & LV_REBUILD)
|
||||
rebuilds |= 1ULL << s;
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
uint64_t status = seg_lv(seg, s)->status;
|
||||
|
||||
for (s = 0; s < seg->area_count; s++)
|
||||
if (seg_lv(seg, s)->status & LV_WRITEMOSTLY)
|
||||
writemostly |= 1ULL << s;
|
||||
if (status & LV_REBUILD)
|
||||
rebuilds[s/64] |= 1ULL << (s%64);
|
||||
|
||||
if (status & LV_RESHAPE_DELTA_DISKS_PLUS) {
|
||||
delta_disks++;
|
||||
delta_disks_plus++;
|
||||
} else if (status & LV_RESHAPE_DELTA_DISKS_MINUS) {
|
||||
delta_disks--;
|
||||
delta_disks_minus++;
|
||||
}
|
||||
|
||||
if (delta_disks_plus && delta_disks_minus) {
|
||||
log_error(INTERNAL_ERROR "Invalid request for delta disks minus and delta disks plus!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (status & LV_WRITEMOSTLY)
|
||||
writemostly[s/64] |= 1ULL << (s%64);
|
||||
}
|
||||
|
||||
data_offset = seg->data_offset;
|
||||
|
||||
if (mirror_in_sync())
|
||||
flags = DM_NOSYNC;
|
||||
}
|
||||
|
||||
params.raid_type = lvseg_name(seg);
|
||||
params.stripe_size = seg->stripe_size;
|
||||
params.flags = flags;
|
||||
|
||||
if (raid0) {
|
||||
params.mirrors = 1;
|
||||
params.stripes = seg->area_count;
|
||||
} else if (seg->segtype->parity_devs) {
|
||||
if (seg->segtype->parity_devs) {
|
||||
/* RAID 4/5/6 */
|
||||
params.mirrors = 1;
|
||||
params.stripes = seg->area_count - seg->segtype->parity_devs;
|
||||
} else if (seg_is_raid10(seg)) {
|
||||
/* RAID 10 only supports 2 mirrors now */
|
||||
params.mirrors = 2;
|
||||
params.stripes = seg->area_count / 2;
|
||||
} else if (seg_is_any_raid0(seg)) {
|
||||
params.mirrors = 1;
|
||||
params.stripes = seg->area_count;
|
||||
} else if (seg_is_any_raid10(seg)) {
|
||||
params.data_copies = seg->data_copies;
|
||||
params.stripes = seg->area_count;
|
||||
} else {
|
||||
/* RAID 1 */
|
||||
params.mirrors = seg->area_count;
|
||||
params.mirrors = seg->data_copies;
|
||||
params.stripes = 1;
|
||||
params.writebehind = seg->writebehind;
|
||||
memcpy(params.writemostly, writemostly, sizeof(params.writemostly));
|
||||
}
|
||||
|
||||
if (!raid0) {
|
||||
/* RAID 0 doesn't have a bitmap, thus no region_size, rebuilds etc. */
|
||||
if (!seg_is_any_raid0(seg)) {
|
||||
params.region_size = seg->region_size;
|
||||
params.rebuilds = rebuilds;
|
||||
params.writemostly = writemostly;
|
||||
memcpy(params.rebuilds, rebuilds, sizeof(params.rebuilds));
|
||||
params.min_recovery_rate = seg->min_recovery_rate;
|
||||
params.max_recovery_rate = seg->max_recovery_rate;
|
||||
params.delta_disks = delta_disks;
|
||||
params.data_offset = data_offset;
|
||||
}
|
||||
|
||||
if (!dm_tree_node_add_raid_target_with_params(node, len, ¶ms))
|
||||
params.stripe_size = seg->stripe_size;
|
||||
params.flags = flags;
|
||||
|
||||
if (!dm_tree_node_add_raid_target_with_params_v2(node, len, ¶ms))
|
||||
return_0;
|
||||
|
||||
return add_areas_line(dm, seg, node, 0u, seg->area_count);
|
||||
@ -404,19 +448,32 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Define raid feature based on the tuple(major, minor, patchlevel) of raid target */
|
||||
struct raid_feature {
|
||||
uint32_t maj;
|
||||
uint32_t min;
|
||||
uint32_t patchlevel;
|
||||
unsigned raid_feature;
|
||||
const char *feature;
|
||||
};
|
||||
|
||||
/* Return true if tuple(@maj, @min, @patchlevel) is greater/equal to @*feature members */
|
||||
static int _check_feature(const struct raid_feature *feature, uint32_t maj, uint32_t min, uint32_t patchlevel)
|
||||
{
|
||||
return (maj > feature->maj) ||
|
||||
(maj == feature->maj && min >= feature->min) ||
|
||||
(maj == feature->maj && min == feature->min && patchlevel >= feature->patchlevel);
|
||||
}
|
||||
|
||||
static int _raid_target_present(struct cmd_context *cmd,
|
||||
const struct lv_segment *seg __attribute__((unused)),
|
||||
unsigned *attributes)
|
||||
{
|
||||
/* List of features with their kernel target version */
|
||||
static const struct feature {
|
||||
uint32_t maj;
|
||||
uint32_t min;
|
||||
unsigned raid_feature;
|
||||
const char *feature;
|
||||
} _features[] = {
|
||||
{ 1, 3, RAID_FEATURE_RAID10, SEG_TYPE_NAME_RAID10 },
|
||||
{ 1, 7, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
|
||||
const struct raid_feature _features[] = {
|
||||
{ 1, 3, 0, RAID_FEATURE_RAID10, SEG_TYPE_NAME_RAID10 },
|
||||
{ 1, 7, 0, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
|
||||
{ 1, 10, 1, RAID_FEATURE_RESHAPE, "reshaping" },
|
||||
};
|
||||
|
||||
static int _raid_checked = 0;
|
||||
@ -438,13 +495,19 @@ static int _raid_target_present(struct cmd_context *cmd,
|
||||
return_0;
|
||||
|
||||
for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
|
||||
if ((maj > _features[i].maj) ||
|
||||
(maj == _features[i].maj && min >= _features[i].min))
|
||||
if (_check_feature(_features + i, maj, min, patchlevel))
|
||||
_raid_attrs |= _features[i].raid_feature;
|
||||
else
|
||||
log_very_verbose("Target raid does not support %s.",
|
||||
_features[i].feature);
|
||||
|
||||
/*
|
||||
* Seperate check for proper raid4 mapping supported
|
||||
*
|
||||
* If we get more of these range checks, avoid them
|
||||
* altogether by enhancing 'struct raid_feature'
|
||||
* and _check_feature() to handle them.
|
||||
*/
|
||||
if (!(maj == 1 && (min == 8 || (min == 9 && patchlevel == 0))))
|
||||
_raid_attrs |= RAID_FEATURE_RAID4;
|
||||
else
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -69,7 +69,7 @@ FIELD(LVS, lv, BIN, "ActExcl", lvid, 10, lvactiveexclusively, lv_active_exclusiv
|
||||
FIELD(LVS, lv, SNUM, "Maj", major, 0, int32, lv_major, "Persistent major number or -1 if not persistent.", 0)
|
||||
FIELD(LVS, lv, SNUM, "Min", minor, 0, int32, lv_minor, "Persistent minor number or -1 if not persistent.", 0)
|
||||
FIELD(LVS, lv, SIZ, "Rahead", lvid, 0, lvreadahead, lv_read_ahead, "Read ahead setting in current units.", 0)
|
||||
FIELD(LVS, lv, SIZ, "LSize", size, 0, size64, lv_size, "Size of LV in current units.", 0)
|
||||
FIELD(LVS, lv, SIZ, "LSize", lvid, 0, lv_size, lv_size, "Size of LV in current units.", 0)
|
||||
FIELD(LVS, lv, SIZ, "MSize", lvid, 0, lvmetadatasize, lv_metadata_size, "For thin and cache pools, the size of the LV that holds the metadata.", 0)
|
||||
FIELD(LVS, lv, NUM, "#Seg", lvid, 0, lvsegcount, seg_count, "Number of segments in LV.", 0)
|
||||
FIELD(LVS, lv, STR, "Origin", lvid, 0, origin, origin, "For snapshots and thins, the origin device of this LV.", 0)
|
||||
@ -140,6 +140,7 @@ FIELD(LVSSTATUS, lv, NUM, "CacheWriteHits", lvid, 16, cache_write_hits, cache_wr
|
||||
FIELD(LVSSTATUS, lv, NUM, "CacheWriteMisses", lvid, 0, cache_write_misses, cache_write_misses, "Cache write misses.", 0)
|
||||
FIELD(LVSSTATUS, lv, STR_LIST, "KCacheSettings", lvid, 18, kernel_cache_settings, kernel_cache_settings, "Cache settings/parameters as set in kernel, including default values (cached segments only).", 0)
|
||||
FIELD(LVSSTATUS, lv, STR, "KCachePolicy", lvid, 18, kernel_cache_policy, kernel_cache_policy, "Cache policy used in kernel.", 0)
|
||||
FIELD(LVSSTATUS, lv, NUM, "KMFmt", lvid, 0, kernelmetadataformat, kernel_metadata_format, "Cache metadata format used in kernel.", 0)
|
||||
FIELD(LVSSTATUS, lv, STR, "Health", lvid, 15, lvhealthstatus, lv_health_status, "LV health status.", 0)
|
||||
FIELD(LVSSTATUS, lv, STR, "KDiscards", lvid, 0, kdiscards, kernel_discards, "For thin pools, how discards are handled in kernel.", 0)
|
||||
FIELD(LVSSTATUS, lv, BIN, "CheckNeeded", lvid, 15, lvcheckneeded, lv_check_needed, "For thin pools and cache volumes, whether metadata check is needed.", 0)
|
||||
@ -241,13 +242,21 @@ FIELD(VGS, vg, NUM, "#VMdaCps", cmd, 0, vgmdacopies, vg_mda_copies, "Target numb
|
||||
* SEGS type fields
|
||||
*/
|
||||
FIELD(SEGS, seg, STR, "Type", list, 0, segtype, segtype, "Type of LV segment.", 0)
|
||||
FIELD(SEGS, seg, NUM, "#Str", area_count, 0, uint32, stripes, "Number of stripes or mirror legs.", 0)
|
||||
FIELD(SEGS, seg, NUM, "#Str", list, 0, seg_stripes, stripes, "Number of stripes or mirror/raid1 legs.", 0)
|
||||
FIELD(SEGS, seg, NUM, "#DStr", list, 0, seg_data_stripes, data_stripes, "Number of data stripes or mirror/raid1 legs.", 0)
|
||||
FIELD(SEGS, seg, SIZ, "RSize", list, 0, seg_reshape_len, reshape_len, "Size of out-of-place reshape space in current units.", 0)
|
||||
FIELD(SEGS, seg, NUM, "RSize", list, 0, seg_reshape_len_le, reshape_len_le, "Size of out-of-place reshape space in logical extents.", 0)
|
||||
FIELD(SEGS, seg, NUM, "#Cpy", list, 0, seg_data_copies, data_copies, "Number of data copies.", 0)
|
||||
FIELD(SEGS, seg, NUM, "DOff", list, 0, seg_data_offset, data_offset, "Data offset on each image device.", 0)
|
||||
FIELD(SEGS, seg, NUM, "NOff", list, 0, seg_new_data_offset, new_data_offset, "New data offset after any reshape on each image device.", 0)
|
||||
FIELD(SEGS, seg, NUM, "#Par", list, 0, seg_parity_chunks, parity_chunks, "Number of (rotating) parity chunks.", 0)
|
||||
FIELD(SEGS, seg, SIZ, "Stripe", stripe_size, 0, size32, stripe_size, "For stripes, amount of data placed on one device before switching to the next.", 0)
|
||||
FIELD(SEGS, seg, SIZ, "Region", region_size, 0, size32, region_size, "For mirrors, the unit of data copied when synchronising devices.", 0)
|
||||
FIELD(SEGS, seg, SIZ, "Region", region_size, 0, size32, region_size, "For mirrors/raids, the unit of data per leg when synchronizing devices.", 0)
|
||||
FIELD(SEGS, seg, SIZ, "Chunk", list, 0, chunksize, chunk_size, "For snapshots, the unit of data used when tracking changes.", 0)
|
||||
FIELD(SEGS, seg, NUM, "#Thins", list, 0, thincount, thin_count, "For thin pools, the number of thin volumes in this pool.", 0)
|
||||
FIELD(SEGS, seg, STR, "Discards", list, 0, discards, discards, "For thin pools, how discards are handled.", 0)
|
||||
FIELD(SEGS, seg, STR, "CacheMode", list, 0, cachemode, cache_mode, "For cache pools, how writes are cached.", 0)
|
||||
FIELD(SEGS, seg, NUM, "CMFmt", list, 0, cachemetadataformat, cache_metadata_format, "For cache, metadata format in use.", 0)
|
||||
FIELD(SEGS, seg, STR, "CacheMode", list, 0, cachemode, cache_mode, "For cache, how writes are cached.", 0)
|
||||
FIELD(SEGS, seg, BIN, "Zero", list, 0, thinzero, zero, "For thin pools and volumes, if zeroing is enabled.", 0)
|
||||
FIELD(SEGS, seg, NUM, "TransId", list, 0, transactionid, transaction_id, "For thin pools, the transaction id and creation transaction id for thins.", 0)
|
||||
FIELD(SEGS, seg, NUM, "ThId", list, 0, thinid, thin_id, "For thin volume, the thin device id.", 0)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -446,8 +446,22 @@ GET_VG_NUM_PROPERTY_FN(vg_missing_pv_count, vg_missing_pv_count(vg))
|
||||
/* LVSEG */
|
||||
GET_LVSEG_STR_PROPERTY_FN(segtype, lvseg_segtype_dup(lvseg->lv->vg->vgmem, lvseg))
|
||||
#define _segtype_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(data_copies, lvseg->data_copies)
|
||||
#define _data_copies_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(reshape_len, lvseg->reshape_len)
|
||||
#define _reshape_len_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(reshape_len_le, lvseg->reshape_len)
|
||||
#define _reshape_len_le_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(data_offset, lvseg->data_offset)
|
||||
#define _data_offset_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(new_data_offset, lvseg->data_offset)
|
||||
#define _new_data_offset_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(parity_chunks, lvseg->data_offset)
|
||||
#define _parity_chunks_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(stripes, lvseg->area_count)
|
||||
#define _stripes_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(data_stripes, lvseg->area_count)
|
||||
#define _data_stripes_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(stripe_size, (SECTOR_SIZE * lvseg->stripe_size))
|
||||
#define _stripe_size_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(region_size, (SECTOR_SIZE * lvseg->region_size))
|
||||
@ -456,7 +470,7 @@ GET_LVSEG_NUM_PROPERTY_FN(chunk_size, (SECTOR_SIZE * lvseg_chunksize(lvseg)))
|
||||
#define _chunk_size_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(thin_count, dm_list_size(&lvseg->lv->segs_using_this_lv))
|
||||
#define _thin_count_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(zero, lvseg->zero_new_blocks)
|
||||
GET_LVSEG_NUM_PROPERTY_FN(zero, (lvseg->zero_new_blocks == THIN_ZERO_YES))
|
||||
#define _zero_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(transaction_id, lvseg->transaction_id)
|
||||
#define _transaction_id_set prop_not_implemented_set
|
||||
@ -468,6 +482,8 @@ GET_LVSEG_STR_PROPERTY_FN(kernel_discards, lvseg_kernel_discards_dup(lvseg->lv->
|
||||
#define _kernel_discards_set prop_not_implemented_set
|
||||
GET_LVSEG_STR_PROPERTY_FN(cache_mode, lvseg_cachemode_dup(lvseg->lv->vg->vgmem, lvseg))
|
||||
#define _cache_mode_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(cache_metadata_format, lvseg->cache_metadata_format)
|
||||
#define _cache_metadata_format_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(seg_start, (SECTOR_SIZE * lvseg_start(lvseg)))
|
||||
#define _seg_start_set prop_not_implemented_set
|
||||
GET_LVSEG_NUM_PROPERTY_FN(seg_start_pe, lvseg->le)
|
||||
@ -499,6 +515,8 @@ GET_LVSEG_STR_PROPERTY_FN(seg_monitor, lvseg_monitor_dup(lvseg->lv->vg->vgmem, l
|
||||
#define _kernel_cache_settings_set prop_not_implemented_set
|
||||
#define _kernel_cache_policy_get prop_not_implemented_get
|
||||
#define _kernel_cache_policy_set prop_not_implemented_set
|
||||
#define _kernel_metadata_format_get prop_not_implemented_get
|
||||
#define _kernel_metadata_format_set prop_not_implemented_set
|
||||
|
||||
/* PVSEG */
|
||||
GET_PVSEG_NUM_PROPERTY_FN(pvseg_start, pvseg->pe)
|
||||
|
@ -54,6 +54,7 @@ enum {
|
||||
|
||||
static const uint64_t _zero64 = UINT64_C(0);
|
||||
static const uint64_t _one64 = UINT64_C(1);
|
||||
static const uint64_t _two64 = UINT64_C(2);
|
||||
static const char _str_zero[] = "0";
|
||||
static const char _str_one[] = "1";
|
||||
static const char _str_no[] = "no";
|
||||
@ -1537,6 +1538,21 @@ static int _kernel_cache_policy_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
GET_FIELD_RESERVED_VALUE(cache_policy_undef));
|
||||
}
|
||||
|
||||
static int _kernelmetadataformat_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct lv_with_info_and_seg_status *lvdm = (const struct lv_with_info_and_seg_status *) data;
|
||||
unsigned format;
|
||||
|
||||
if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
|
||||
format = (lvdm->seg_status.cache->feature_flags & DM_CACHE_FEATURE_METADATA2);
|
||||
return dm_report_field_uint64(rh, field, format ? &_two64 : &_one64);
|
||||
}
|
||||
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
static int _cache_policy_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
@ -2296,6 +2312,22 @@ static int _size64_disp(struct dm_report *rh __attribute__((unused)),
|
||||
return _field_set_value(field, repstr, sortval);
|
||||
}
|
||||
|
||||
static int _lv_size_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
const struct lv_segment *seg = first_seg(lv);
|
||||
uint64_t size = lv->le_count;
|
||||
|
||||
if (seg && !lv_is_raid_image(lv))
|
||||
size -= seg->reshape_len * (seg->area_count > 2 ? (seg->area_count - seg->segtype->parity_devs) : 1);
|
||||
|
||||
size *= lv->vg->extent_size;
|
||||
|
||||
return _size64_disp(rh, mem, field, &size, private);
|
||||
}
|
||||
|
||||
static int _uint32_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private __attribute__((unused)))
|
||||
@ -2412,6 +2444,197 @@ static int _segstartpe_disp(struct dm_report *rh,
|
||||
return dm_report_field_uint32(rh, field, &seg->le);
|
||||
}
|
||||
|
||||
/* Hepler: get used stripes = total stripes minux any to remove after reshape */
|
||||
static int _get_seg_used_stripes(const struct lv_segment *seg)
|
||||
{
|
||||
uint32_t s;
|
||||
uint32_t stripes = seg->area_count;
|
||||
|
||||
for (s = seg->area_count - 1; stripes && s; s--) {
|
||||
if (seg_type(seg, s) == AREA_LV &&
|
||||
seg_lv(seg, s)->status & LV_REMOVE_AFTER_RESHAPE)
|
||||
stripes--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return stripes;
|
||||
}
|
||||
|
||||
static int _seg_stripes_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct lv_segment *seg = ((const struct lv_segment *) data);
|
||||
|
||||
return dm_report_field_uint32(rh, field, &seg->area_count);
|
||||
}
|
||||
|
||||
/* Report the number of data stripes, which is less than total stripes (e.g. 2 less for raid6) */
|
||||
static int _seg_data_stripes_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
uint32_t stripes = _get_seg_used_stripes(seg) - seg->segtype->parity_devs;
|
||||
|
||||
/* FIXME: in case of odd numbers of raid10 stripes */
|
||||
if (seg_is_raid10(seg))
|
||||
stripes /= seg->data_copies;
|
||||
|
||||
return dm_report_field_uint32(rh, field, &stripes);
|
||||
}
|
||||
|
||||
/* Helper: return the top-level, reshapable raid LV in case @seg belongs to an raid rimage LV */
|
||||
static struct logical_volume *_lv_for_raid_image_seg(const struct lv_segment *seg, struct dm_pool *mem)
|
||||
{
|
||||
char *lv_name;
|
||||
|
||||
if (seg_is_reshapable_raid(seg))
|
||||
return seg->lv;
|
||||
|
||||
if (seg->lv &&
|
||||
lv_is_raid_image(seg->lv) && !seg->le &&
|
||||
(lv_name = dm_pool_strdup(mem, seg->lv->name))) {
|
||||
char *p = strchr(lv_name, '_');
|
||||
|
||||
if (p) {
|
||||
/* Handle duplicated sub LVs */
|
||||
if (strstr(p, "_dup_"))
|
||||
p = strchr(p + 5, '_');
|
||||
|
||||
if (p) {
|
||||
struct lv_list *lvl;
|
||||
|
||||
*p = '\0';
|
||||
if ((lvl = find_lv_in_vg(seg->lv->vg, lv_name)) &&
|
||||
seg_is_reshapable_raid(first_seg(lvl->lv)))
|
||||
return lvl->lv;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Helper: return the top-level raid LV in case it is reshapale for @seg or @seg if it is */
|
||||
static const struct lv_segment *_get_reshapable_seg(const struct lv_segment *seg, struct dm_pool *mem)
|
||||
{
|
||||
return _lv_for_raid_image_seg(seg, mem) ? seg : NULL;
|
||||
}
|
||||
|
||||
/* Display segment reshape length in current units */
|
||||
static int _seg_reshape_len_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct lv_segment *seg = _get_reshapable_seg((const struct lv_segment *) data, mem);
|
||||
|
||||
if (seg) {
|
||||
uint32_t reshape_len = seg->reshape_len * seg->area_count * seg->lv->vg->extent_size;
|
||||
|
||||
return _size32_disp(rh, mem, field, &reshape_len, private);
|
||||
}
|
||||
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
/* Display segment reshape length of in logical extents */
|
||||
static int _seg_reshape_len_le_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct lv_segment *seg = _get_reshapable_seg((const struct lv_segment *) data, mem);
|
||||
|
||||
if (seg) {
|
||||
uint32_t reshape_len = seg->reshape_len* seg->area_count;
|
||||
|
||||
return dm_report_field_uint32(rh, field, &reshape_len);
|
||||
}
|
||||
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
/* Display segment data copies (e.g. 3 for raid6) */
|
||||
static int _seg_data_copies_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
|
||||
if (seg->data_copies)
|
||||
return dm_report_field_uint32(rh, field, &seg->data_copies);
|
||||
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
/* Helper: display segment data offset/new data offset in sectors */
|
||||
static int _segdata_offset(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private, int new_data_offset)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
struct logical_volume *lv;
|
||||
|
||||
if ((lv = _lv_for_raid_image_seg(seg, mem))) {
|
||||
uint64_t data_offset;
|
||||
|
||||
if (lv_raid_data_offset(lv, &data_offset)) {
|
||||
if (new_data_offset && !lv_raid_image_in_sync(seg->lv))
|
||||
data_offset = data_offset ? 0 : seg->reshape_len * lv->vg->extent_size;
|
||||
|
||||
return dm_report_field_uint64(rh, field, &data_offset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
static int _seg_data_offset_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
return _segdata_offset(rh, mem, field, data, private, 0);
|
||||
}
|
||||
|
||||
static int _seg_new_data_offset_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
return _segdata_offset(rh, mem, field, data, private, 1);
|
||||
}
|
||||
|
||||
static int _seg_parity_chunks_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
uint32_t parity_chunks = seg->segtype->parity_devs ?: seg->data_copies - 1;
|
||||
|
||||
if (parity_chunks) {
|
||||
uint32_t s, resilient_sub_lvs = 0;
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg_type(seg, s) == AREA_LV) {
|
||||
struct lv_segment *seg1 = first_seg(seg_lv(seg, s));
|
||||
|
||||
if (seg1->segtype->parity_devs ||
|
||||
seg1->data_copies > 1)
|
||||
resilient_sub_lvs++;
|
||||
}
|
||||
}
|
||||
|
||||
if (resilient_sub_lvs && resilient_sub_lvs == seg->area_count)
|
||||
parity_chunks++;
|
||||
|
||||
return dm_report_field_uint32(rh, field, &parity_chunks);
|
||||
}
|
||||
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
@ -2511,6 +2734,29 @@ static int _cachemode_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
return _field_string(rh, field, display_cache_mode(seg));
|
||||
}
|
||||
|
||||
static int _cachemetadataformat_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
const uint64_t *fmt;
|
||||
|
||||
if (seg_is_cache(seg))
|
||||
seg = first_seg(seg->pool_lv);
|
||||
|
||||
if (seg_is_cache_pool(seg)) {
|
||||
switch (seg->cache_metadata_format) {
|
||||
case CACHE_METADATA_FORMAT_1:
|
||||
case CACHE_METADATA_FORMAT_2:
|
||||
fmt = (seg->cache_metadata_format == CACHE_METADATA_FORMAT_2) ? &_two64 : &_one64;
|
||||
return dm_report_field_uint64(rh, field, fmt);
|
||||
default: /* unselected/undefined for all other cases */;
|
||||
}
|
||||
}
|
||||
|
||||
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
|
||||
}
|
||||
|
||||
static int _originsize_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
struct dm_report_field *field,
|
||||
const void *data, void *private)
|
||||
@ -3447,7 +3693,7 @@ static int _thinzero_disp(struct dm_report *rh, struct dm_pool *mem,
|
||||
seg = first_seg(seg->pool_lv);
|
||||
|
||||
if (seg_is_thin_pool(seg))
|
||||
return _binary_disp(rh, mem, field, seg->zero_new_blocks, GET_FIRST_RESERVED_NAME(zero_y), private);
|
||||
return _binary_disp(rh, mem, field, (seg->zero_new_blocks == THIN_ZERO_YES), GET_FIRST_RESERVED_NAME(zero_y), private);
|
||||
|
||||
return _binary_undef_disp(rh, mem, field, private);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ static void _thin_pool_display(const struct lv_segment *seg)
|
||||
dm_list_size(&seg->lv->segs_using_this_lv));
|
||||
log_print(" Transaction ID\t%" PRIu64, seg->transaction_id);
|
||||
log_print(" Zero new blocks\t%s",
|
||||
seg->zero_new_blocks ? "yes" : "no");
|
||||
(seg->zero_new_blocks == THIN_ZERO_YES) ? "yes" : "no");
|
||||
|
||||
log_print(" ");
|
||||
}
|
||||
@ -84,6 +84,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
|
||||
const char *lv_name;
|
||||
struct logical_volume *pool_data_lv, *pool_metadata_lv;
|
||||
const char *discards_str = NULL;
|
||||
uint32_t zero = 0;
|
||||
|
||||
if (!dm_config_get_str(sn, "metadata", &lv_name))
|
||||
return SEG_LOG_ERROR("Metadata must be a string in");
|
||||
@ -124,9 +125,11 @@ static int _thin_pool_text_import(struct lv_segment *seg,
|
||||
seg->device_id);
|
||||
|
||||
if (dm_config_has_node(sn, "zero_new_blocks") &&
|
||||
!dm_config_get_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks))
|
||||
!dm_config_get_uint32(sn, "zero_new_blocks", &zero))
|
||||
return SEG_LOG_ERROR("Could not read zero_new_blocks for");
|
||||
|
||||
seg->zero_new_blocks = (zero) ? THIN_ZERO_YES : THIN_ZERO_NO;
|
||||
|
||||
/* Read messages */
|
||||
for (; sn; sn = sn->sib)
|
||||
if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
|
||||
@ -165,8 +168,13 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (seg->zero_new_blocks)
|
||||
if (seg->zero_new_blocks == THIN_ZERO_YES)
|
||||
outf(f, "zero_new_blocks = 1");
|
||||
else if (seg->zero_new_blocks != THIN_ZERO_NO) {
|
||||
log_error(INTERNAL_ERROR "Invalid zero new blocks value %d.",
|
||||
seg->zero_new_blocks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(tmsg, &seg->thin_messages) {
|
||||
/* Extra validation */
|
||||
@ -304,7 +312,7 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
|
||||
seg->transaction_id,
|
||||
metadata_dlid, pool_dlid,
|
||||
seg->chunk_size, low_water_mark,
|
||||
seg->zero_new_blocks ? 0 : 1))
|
||||
(seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1))
|
||||
return_0;
|
||||
|
||||
if (attr & THIN_FEATURE_DISCARDS) {
|
||||
|
@ -260,7 +260,7 @@ struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
|
||||
key[fmt - next] = '\0';
|
||||
fmt += 2;
|
||||
|
||||
if (!strcmp(fmt, "%d") || !strcmp(fmt, FMTd64)) {
|
||||
if (!strcmp(fmt, FMTd64)) {
|
||||
int64_t value = va_arg(ap, int64_t);
|
||||
if (!(cn = make_int_node(cft, key, value, parent, pre_sib)))
|
||||
return 0;
|
||||
|
@ -234,7 +234,6 @@ dm_tree_free
|
||||
dm_tree_get_cookie
|
||||
dm_tree_children_use_uuid
|
||||
dm_tree_next_child
|
||||
dm_tree_node_add_cache_target
|
||||
dm_tree_node_add_crypt_target
|
||||
dm_tree_node_add_error_target
|
||||
dm_tree_node_add_linear_target
|
||||
|
@ -1,5 +1,9 @@
|
||||
dm_bit_get_last
|
||||
dm_bit_get_prev
|
||||
dm_filemapd_mode_from_string
|
||||
dm_stats_update_regions_from_fd
|
||||
dm_bitset_parse_list
|
||||
dm_stats_bind_from_fd
|
||||
dm_stats_start_filemapd
|
||||
dm_tree_node_add_raid_target_with_params_v2
|
||||
dm_tree_node_add_cache_target
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2006 Rackable Systems All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
@ -331,6 +331,7 @@ struct dm_status_raid {
|
||||
char *dev_health;
|
||||
/* idle, frozen, resync, recover, check, repair */
|
||||
char *sync_action;
|
||||
uint64_t data_offset; /* RAID out-of-place reshaping */
|
||||
};
|
||||
|
||||
int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
@ -358,7 +359,7 @@ struct dm_status_cache {
|
||||
uint64_t demotions;
|
||||
uint64_t promotions;
|
||||
|
||||
uint64_t feature_flags;
|
||||
uint64_t feature_flags; /* DM_CACHE_FEATURE_? */
|
||||
|
||||
int core_argc;
|
||||
char **core_argv;
|
||||
@ -1368,6 +1369,73 @@ uint64_t *dm_stats_create_regions_from_fd(struct dm_stats *dms, int fd,
|
||||
uint64_t *dm_stats_update_regions_from_fd(struct dm_stats *dms, int fd,
|
||||
uint64_t group_id);
|
||||
|
||||
|
||||
/*
|
||||
* The file map monitoring daemon can monitor files in two distinct
|
||||
* ways: the mode affects the behaviour of the daemon when a file
|
||||
* under monitoring is renamed or unlinked, and the conditions which
|
||||
* cause the daemon to terminate.
|
||||
*
|
||||
* In both modes, the daemon will always shut down when the group
|
||||
* being monitored is deleted.
|
||||
*
|
||||
* Follow inode:
|
||||
* The daemon follows the inode of the file, as it was at the time the
|
||||
* daemon started. The file descriptor referencing the file is kept
|
||||
* open at all times, and the daemon will exit when it detects that
|
||||
* the file has been unlinked and it is the last holder of a reference
|
||||
* to the file.
|
||||
*
|
||||
* This mode is useful if the file is expected to be renamed, or moved
|
||||
* within the file system, while it is being monitored.
|
||||
*
|
||||
* Follow path:
|
||||
* The daemon follows the path that was given on the daemon command
|
||||
* line. The file descriptor referencing the file is re-opened on each
|
||||
* iteration of the daemon, and the daemon will exit if no file exists
|
||||
* at this location (a tolerance is allowed so that a brief delay
|
||||
* between unlink() and creat() is permitted).
|
||||
*
|
||||
* This mode is useful if the file is updated by unlinking the original
|
||||
* and placing a new file at the same path.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
DM_FILEMAPD_FOLLOW_INODE,
|
||||
DM_FILEMAPD_FOLLOW_PATH,
|
||||
DM_FILEMAPD_FOLLOW_NONE
|
||||
} dm_filemapd_mode_t;
|
||||
|
||||
/*
|
||||
* Parse a string representation of a dmfilemapd mode.
|
||||
*
|
||||
* Returns a valid dm_filemapd_mode_t value on success, or
|
||||
* DM_FILEMAPD_FOLLOW_NONE on error.
|
||||
*/
|
||||
dm_filemapd_mode_t dm_filemapd_mode_from_string(const char *mode_str);
|
||||
|
||||
/*
|
||||
* Start the dmfilemapd filemap monitoring daemon for the specified
|
||||
* file descriptor, group, and file system path. The daemon will
|
||||
* monitor the file for allocation changes, and when a change is
|
||||
* detected, call dm_stats_update_regions_from_fd() to update the
|
||||
* mapped regions for the file.
|
||||
*
|
||||
* The path provided to dm_stats_start_filemapd() must be an absolute
|
||||
* path, and should reflect the path of 'fd' at the time that it was
|
||||
* opened.
|
||||
*
|
||||
* The mode parameter controls the behaviour of the daemon when the
|
||||
* file being monitored is unlinked or moved: see the comments for
|
||||
* dm_filemapd_mode_t for a full description and possible values.
|
||||
*
|
||||
* The daemon can be stopped at any time by sending SIGTERM to the
|
||||
* daemon pid.
|
||||
*/
|
||||
int dm_stats_start_filemapd(int fd, uint64_t group_id, const char *path,
|
||||
dm_filemapd_mode_t mode, unsigned foreground,
|
||||
unsigned verbose);
|
||||
|
||||
/*
|
||||
* Call this to actually run the ioctl.
|
||||
*/
|
||||
@ -1738,6 +1806,11 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
|
||||
*/
|
||||
#define DM_CACHE_METADATA_MAX_SECTORS DM_THIN_METADATA_MAX_SECTORS
|
||||
|
||||
/*
|
||||
* Define number of elements in rebuild and writemostly arrays
|
||||
* 'of struct dm_tree_node_raid_params'.
|
||||
*/
|
||||
|
||||
struct dm_tree_node_raid_params {
|
||||
const char *raid_type;
|
||||
|
||||
@ -1749,29 +1822,75 @@ struct dm_tree_node_raid_params {
|
||||
/*
|
||||
* 'rebuilds' and 'writemostly' are bitfields that signify
|
||||
* which devices in the array are to be rebuilt or marked
|
||||
* writemostly. By choosing a 'uint64_t', we limit ourself
|
||||
* to RAID arrays with 64 devices.
|
||||
* writemostly. The kernel supports up to 253 legs.
|
||||
* We limit ourselves by choosing a lower value
|
||||
* for DEFAULT_RAID{1}_MAX_IMAGES in defaults.h.
|
||||
*/
|
||||
uint64_t rebuilds;
|
||||
uint64_t writemostly;
|
||||
uint32_t writebehind; /* I/Os (kernel default COUNTER_MAX / 2) */
|
||||
uint32_t writebehind; /* I/Os (kernel default COUNTER_MAX / 2) */
|
||||
uint32_t sync_daemon_sleep; /* ms (kernel default = 5sec) */
|
||||
uint32_t max_recovery_rate; /* kB/sec/disk */
|
||||
uint32_t min_recovery_rate; /* kB/sec/disk */
|
||||
uint32_t stripe_cache; /* sectors */
|
||||
|
||||
uint64_t flags; /* [no]sync */
|
||||
uint32_t reserved2;
|
||||
};
|
||||
|
||||
/*
|
||||
* Version 2 of above node raid params struct to keeep API compatibility.
|
||||
*
|
||||
* Extended for more than 64 legs (max 253 in the MD kernel runtime!),
|
||||
* delta_disks for disk add/remove reshaping,
|
||||
* data_offset for out-of-place reshaping
|
||||
* and data_copies for odd number of raid10 legs.
|
||||
*/
|
||||
#define RAID_BITMAP_SIZE 4 /* 4 * 64 bit elements in rebuilds/writemostly arrays */
|
||||
struct dm_tree_node_raid_params_v2 {
|
||||
const char *raid_type;
|
||||
|
||||
uint32_t stripes;
|
||||
uint32_t mirrors;
|
||||
uint32_t region_size;
|
||||
uint32_t stripe_size;
|
||||
|
||||
int delta_disks; /* +/- number of disks to add/remove (reshaping) */
|
||||
int data_offset; /* data offset to set (out-of-place reshaping) */
|
||||
|
||||
/*
|
||||
* 'rebuilds' and 'writemostly' are bitfields that signify
|
||||
* which devices in the array are to be rebuilt or marked
|
||||
* writemostly. The kernel supports up to 253 legs.
|
||||
* We limit ourselvs by choosing a lower value
|
||||
* for DEFAULT_RAID_MAX_IMAGES.
|
||||
*/
|
||||
uint64_t rebuilds[RAID_BITMAP_SIZE];
|
||||
uint64_t writemostly[RAID_BITMAP_SIZE];
|
||||
uint32_t writebehind; /* I/Os (kernel default COUNTER_MAX / 2) */
|
||||
uint32_t data_copies; /* RAID # of data copies */
|
||||
uint32_t sync_daemon_sleep; /* ms (kernel default = 5sec) */
|
||||
uint32_t max_recovery_rate; /* kB/sec/disk */
|
||||
uint32_t min_recovery_rate; /* kB/sec/disk */
|
||||
uint32_t stripe_cache; /* sectors */
|
||||
|
||||
uint64_t flags; /* [no]sync */
|
||||
uint64_t reserved2;
|
||||
};
|
||||
|
||||
int dm_tree_node_add_raid_target_with_params(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
const struct dm_tree_node_raid_params *p);
|
||||
|
||||
/* Version 2 API function taking dm_tree_node_raid_params_v2 for aforementioned extensions. */
|
||||
int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
const struct dm_tree_node_raid_params_v2 *p);
|
||||
|
||||
/* Cache feature_flags */
|
||||
#define DM_CACHE_FEATURE_WRITEBACK 0x00000001
|
||||
#define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002
|
||||
#define DM_CACHE_FEATURE_PASSTHROUGH 0x00000004
|
||||
#define DM_CACHE_FEATURE_METADATA2 0x00000008 /* cache v1.10 */
|
||||
|
||||
struct dm_config_node;
|
||||
/*
|
||||
|
@ -205,11 +205,14 @@ struct load_segment {
|
||||
struct dm_tree_node *replicator;/* Replicator-dev */
|
||||
uint64_t rdevice_index; /* Replicator-dev */
|
||||
|
||||
uint64_t rebuilds; /* raid */
|
||||
uint64_t writemostly; /* raid */
|
||||
int delta_disks; /* raid reshape number of disks */
|
||||
int data_offset; /* raid reshape data offset on disk to set */
|
||||
uint64_t rebuilds[RAID_BITMAP_SIZE]; /* raid */
|
||||
uint64_t writemostly[RAID_BITMAP_SIZE]; /* raid */
|
||||
uint32_t writebehind; /* raid */
|
||||
uint32_t max_recovery_rate; /* raid kB/sec/disk */
|
||||
uint32_t min_recovery_rate; /* raid kB/sec/disk */
|
||||
uint32_t data_copies; /* raid10 data_copies */
|
||||
|
||||
struct dm_tree_node *metadata; /* Thin_pool + Cache */
|
||||
struct dm_tree_node *pool; /* Thin_pool, Thin */
|
||||
@ -2353,16 +2356,21 @@ static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *s
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Is parameter non-zero? */
|
||||
#define PARAM_IS_SET(p) ((p) ? 1 : 0)
|
||||
static int _2_if_value(unsigned p)
|
||||
{
|
||||
return p ? 2 : 0;
|
||||
}
|
||||
|
||||
/* Return number of bits assuming 4 * 64 bit size */
|
||||
static int _get_params_count(uint64_t bits)
|
||||
/* Return number of bits passed in @bits assuming 2 * 64 bit size */
|
||||
static int _get_params_count(uint64_t *bits)
|
||||
{
|
||||
int r = 0;
|
||||
int i = RAID_BITMAP_SIZE;
|
||||
|
||||
r += 2 * hweight32(bits & 0xFFFFFFFF);
|
||||
r += 2 * hweight32(bits >> 32);
|
||||
while (i--) {
|
||||
r += 2 * hweight32(bits[i] & 0xFFFFFFFF);
|
||||
r += 2 * hweight32(bits[i] >> 32);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -2373,32 +2381,60 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
|
||||
size_t paramsize)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t area_count = seg->area_count / 2;
|
||||
int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */
|
||||
int pos = 0;
|
||||
unsigned type = seg->type;
|
||||
unsigned type;
|
||||
|
||||
if (seg->area_count % 2)
|
||||
return 0;
|
||||
|
||||
if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC))
|
||||
param_count++;
|
||||
|
||||
param_count += 2 * (PARAM_IS_SET(seg->region_size) +
|
||||
PARAM_IS_SET(seg->writebehind) +
|
||||
PARAM_IS_SET(seg->min_recovery_rate) +
|
||||
PARAM_IS_SET(seg->max_recovery_rate));
|
||||
param_count += _2_if_value(seg->data_offset) +
|
||||
_2_if_value(seg->delta_disks) +
|
||||
_2_if_value(seg->region_size) +
|
||||
_2_if_value(seg->writebehind) +
|
||||
_2_if_value(seg->min_recovery_rate) +
|
||||
_2_if_value(seg->max_recovery_rate) +
|
||||
_2_if_value(seg->data_copies > 1);
|
||||
|
||||
/* rebuilds and writemostly are 64 bits */
|
||||
/* rebuilds and writemostly are BITMAP_SIZE * 64 bits */
|
||||
param_count += _get_params_count(seg->rebuilds);
|
||||
param_count += _get_params_count(seg->writemostly);
|
||||
|
||||
if ((type == SEG_RAID1) && seg->stripe_size)
|
||||
log_error("WARNING: Ignoring RAID1 stripe size");
|
||||
if ((seg->type == SEG_RAID1) && seg->stripe_size)
|
||||
log_info("WARNING: Ignoring RAID1 stripe size");
|
||||
|
||||
/* Kernel only expects "raid0", not "raid0_meta" */
|
||||
type = seg->type;
|
||||
if (type == SEG_RAID0_META)
|
||||
type = SEG_RAID0;
|
||||
#if 0
|
||||
/* Kernel only expects "raid10", not "raid10_{far,offset}" */
|
||||
else if (type == SEG_RAID10_FAR ||
|
||||
type == SEG_RAID10_OFFSET) {
|
||||
param_count += 2;
|
||||
type = SEG_RAID10_NEAR;
|
||||
}
|
||||
#endif
|
||||
|
||||
EMIT_PARAMS(pos, "%s %d %u", _dm_segtypes[type].target,
|
||||
EMIT_PARAMS(pos, "%s %d %u",
|
||||
// type == SEG_RAID10_NEAR ? "raid10" : _dm_segtypes[type].target,
|
||||
type == SEG_RAID10 ? "raid10" : _dm_segtypes[type].target,
|
||||
param_count, seg->stripe_size);
|
||||
|
||||
#if 0
|
||||
if (seg->type == SEG_RAID10_FAR)
|
||||
EMIT_PARAMS(pos, " raid10_format far");
|
||||
else if (seg->type == SEG_RAID10_OFFSET)
|
||||
EMIT_PARAMS(pos, " raid10_format offset");
|
||||
#endif
|
||||
|
||||
if (seg->data_copies > 1 && type == SEG_RAID10)
|
||||
EMIT_PARAMS(pos, " raid10_copies %u", seg->data_copies);
|
||||
|
||||
if (seg->flags & DM_NOSYNC)
|
||||
EMIT_PARAMS(pos, " nosync");
|
||||
else if (seg->flags & DM_FORCESYNC)
|
||||
@ -2407,27 +2443,38 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
|
||||
if (seg->region_size)
|
||||
EMIT_PARAMS(pos, " region_size %u", seg->region_size);
|
||||
|
||||
for (i = 0; i < (seg->area_count / 2); i++)
|
||||
if (seg->rebuilds & (1ULL << i))
|
||||
/* If seg-data_offset == 1, kernel needs a zero offset to adjust to it */
|
||||
if (seg->data_offset)
|
||||
EMIT_PARAMS(pos, " data_offset %d", seg->data_offset == 1 ? 0 : seg->data_offset);
|
||||
|
||||
if (seg->delta_disks)
|
||||
EMIT_PARAMS(pos, " delta_disks %d", seg->delta_disks);
|
||||
|
||||
for (i = 0; i < area_count; i++)
|
||||
if (seg->rebuilds[i/64] & (1ULL << (i%64)))
|
||||
EMIT_PARAMS(pos, " rebuild %u", i);
|
||||
|
||||
if (seg->min_recovery_rate)
|
||||
EMIT_PARAMS(pos, " min_recovery_rate %u",
|
||||
seg->min_recovery_rate);
|
||||
|
||||
if (seg->max_recovery_rate)
|
||||
EMIT_PARAMS(pos, " max_recovery_rate %u",
|
||||
seg->max_recovery_rate);
|
||||
|
||||
for (i = 0; i < (seg->area_count / 2); i++)
|
||||
if (seg->writemostly & (1ULL << i))
|
||||
for (i = 0; i < area_count; i++)
|
||||
if (seg->writemostly[i/64] & (1ULL << (i%64)))
|
||||
EMIT_PARAMS(pos, " write_mostly %u", i);
|
||||
|
||||
if (seg->writebehind)
|
||||
EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
|
||||
|
||||
/*
|
||||
* Has to be before "min_recovery_rate" or the kernels
|
||||
* check will fail when both set and min > previous max
|
||||
*/
|
||||
if (seg->max_recovery_rate)
|
||||
EMIT_PARAMS(pos, " max_recovery_rate %u",
|
||||
seg->max_recovery_rate);
|
||||
|
||||
if (seg->min_recovery_rate)
|
||||
EMIT_PARAMS(pos, " min_recovery_rate %u",
|
||||
seg->min_recovery_rate);
|
||||
|
||||
/* Print number of metadata/data device pairs */
|
||||
EMIT_PARAMS(pos, " %u", seg->area_count/2);
|
||||
EMIT_PARAMS(pos, " %u", area_count);
|
||||
|
||||
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
|
||||
return_0;
|
||||
@ -2467,12 +2514,17 @@ static int _cache_emit_segment_line(struct dm_task *dmt,
|
||||
/* Features */
|
||||
/* feature_count = hweight32(seg->flags); */
|
||||
/* EMIT_PARAMS(pos, " %u", feature_count); */
|
||||
if (seg->flags & DM_CACHE_FEATURE_METADATA2)
|
||||
EMIT_PARAMS(pos, " 2 metadata2 ");
|
||||
else
|
||||
EMIT_PARAMS(pos, " 1 ");
|
||||
|
||||
if (seg->flags & DM_CACHE_FEATURE_PASSTHROUGH)
|
||||
EMIT_PARAMS(pos, " 1 passthrough");
|
||||
else if (seg->flags & DM_CACHE_FEATURE_WRITETHROUGH)
|
||||
EMIT_PARAMS(pos, " 1 writethrough");
|
||||
else if (seg->flags & DM_CACHE_FEATURE_WRITEBACK)
|
||||
EMIT_PARAMS(pos, " 1 writeback");
|
||||
EMIT_PARAMS(pos, "passthrough");
|
||||
else if (seg->flags & DM_CACHE_FEATURE_WRITEBACK)
|
||||
EMIT_PARAMS(pos, "writeback");
|
||||
else
|
||||
EMIT_PARAMS(pos, "writethrough");
|
||||
|
||||
/* Cache Policy */
|
||||
name = seg->policy_name ? : "default";
|
||||
@ -3267,8 +3319,10 @@ int dm_tree_node_add_raid_target_with_params(struct dm_tree_node *node,
|
||||
seg->region_size = p->region_size;
|
||||
seg->stripe_size = p->stripe_size;
|
||||
seg->area_count = 0;
|
||||
seg->rebuilds = p->rebuilds;
|
||||
seg->writemostly = p->writemostly;
|
||||
memset(seg->rebuilds, 0, sizeof(seg->rebuilds));
|
||||
seg->rebuilds[0] = p->rebuilds;
|
||||
memset(seg->writemostly, 0, sizeof(seg->writemostly));
|
||||
seg->writemostly[0] = p->writemostly;
|
||||
seg->writebehind = p->writebehind;
|
||||
seg->min_recovery_rate = p->min_recovery_rate;
|
||||
seg->max_recovery_rate = p->max_recovery_rate;
|
||||
@ -3296,6 +3350,47 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
|
||||
return dm_tree_node_add_raid_target_with_params(node, size, ¶ms);
|
||||
}
|
||||
|
||||
/*
|
||||
* Version 2 of dm_tree_node_add_raid_target() allowing for:
|
||||
*
|
||||
* - maximum 253 legs in a raid set (MD kernel limitation)
|
||||
* - delta_disks for disk add/remove reshaping
|
||||
* - data_offset for out-of-place reshaping
|
||||
* - data_copies to cope witth odd numbers of raid10 disks
|
||||
*/
|
||||
int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
const struct dm_tree_node_raid_params_v2 *p)
|
||||
{
|
||||
unsigned i;
|
||||
struct load_segment *seg = NULL;
|
||||
|
||||
for (i = 0; i < DM_ARRAY_SIZE(_dm_segtypes) && !seg; ++i)
|
||||
if (!strcmp(p->raid_type, _dm_segtypes[i].target))
|
||||
if (!(seg = _add_segment(node,
|
||||
_dm_segtypes[i].type, size)))
|
||||
return_0;
|
||||
if (!seg) {
|
||||
log_error("Unsupported raid type %s.", p->raid_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->region_size = p->region_size;
|
||||
seg->stripe_size = p->stripe_size;
|
||||
seg->area_count = 0;
|
||||
seg->delta_disks = p->delta_disks;
|
||||
seg->data_offset = p->data_offset;
|
||||
memcpy(seg->rebuilds, p->rebuilds, sizeof(seg->rebuilds));
|
||||
memcpy(seg->writemostly, p->writemostly, sizeof(seg->writemostly));
|
||||
seg->writebehind = p->writebehind;
|
||||
seg->data_copies = p->data_copies;
|
||||
seg->min_recovery_rate = p->min_recovery_rate;
|
||||
seg->max_recovery_rate = p->max_recovery_rate;
|
||||
seg->flags = p->flags;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_tree_node_add_cache_target(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
uint64_t feature_flags, /* DM_CACHE_FEATURE_* */
|
||||
@ -3308,19 +3403,33 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
|
||||
{
|
||||
struct dm_config_node *cn;
|
||||
struct load_segment *seg;
|
||||
static const uint64_t _modemask =
|
||||
DM_CACHE_FEATURE_PASSTHROUGH |
|
||||
DM_CACHE_FEATURE_WRITETHROUGH |
|
||||
DM_CACHE_FEATURE_WRITEBACK;
|
||||
|
||||
switch (feature_flags &
|
||||
(DM_CACHE_FEATURE_PASSTHROUGH |
|
||||
DM_CACHE_FEATURE_WRITETHROUGH |
|
||||
DM_CACHE_FEATURE_WRITEBACK)) {
|
||||
case DM_CACHE_FEATURE_PASSTHROUGH:
|
||||
case DM_CACHE_FEATURE_WRITETHROUGH:
|
||||
case DM_CACHE_FEATURE_WRITEBACK:
|
||||
break;
|
||||
default:
|
||||
log_error("Invalid cache's feature flag " FMTu64 ".",
|
||||
feature_flags);
|
||||
return 0;
|
||||
/* Detect unknown (bigger) feature bit */
|
||||
if (feature_flags >= (DM_CACHE_FEATURE_METADATA2 * 2)) {
|
||||
log_error("Unsupported cache's feature flags set " FMTu64 ".",
|
||||
feature_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (feature_flags & _modemask) {
|
||||
case DM_CACHE_FEATURE_PASSTHROUGH:
|
||||
case DM_CACHE_FEATURE_WRITEBACK:
|
||||
if (strcmp(policy_name, "cleaner") == 0) {
|
||||
/* Enforce writethrough mode for cleaner policy */
|
||||
feature_flags = ~_modemask;
|
||||
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
|
||||
}
|
||||
/* Fall through */
|
||||
case DM_CACHE_FEATURE_WRITETHROUGH:
|
||||
break;
|
||||
default:
|
||||
log_error("Invalid cache's feature flag " FMTu64 ".",
|
||||
feature_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data_block_size < DM_CACHE_MIN_DATA_BLOCK_SIZE) {
|
||||
@ -3366,8 +3475,7 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
|
||||
return_0;
|
||||
|
||||
seg->data_block_size = data_block_size;
|
||||
/* Enforce WriteThough mode for cleaner policy */
|
||||
seg->flags = (strcmp(policy_name, "cleaner") == 0) ? DM_CACHE_FEATURE_WRITETHROUGH : feature_flags;
|
||||
seg->flags = feature_flags;
|
||||
seg->policy_name = policy_name;
|
||||
|
||||
/* FIXME: better validation missing */
|
||||
@ -3926,13 +4034,15 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode,
|
||||
dnode->callback_data = data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Backward compatible dm_tree_node_size_changed() implementations.
|
||||
*
|
||||
* Keep these at the end of the file to avoid adding clutter around the
|
||||
* current dm_tree_node_size_changed() version.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
/*
|
||||
* Backward compatible implementations.
|
||||
*
|
||||
* Keep these at the end of the file to make sure that
|
||||
* no code in this file accidentally calls it.
|
||||
*/
|
||||
|
||||
/* Backward compatible dm_tree_node_size_changed() implementations. */
|
||||
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode);
|
||||
DM_EXPORT_SYMBOL_BASE(dm_tree_node_size_changed);
|
||||
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
|
||||
@ -3940,4 +4050,43 @@ int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
|
||||
/* Base does not make difference between smaller and bigger */
|
||||
return dm_tree_node_size_changed(dnode) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retain ABI compatibility after adding the DM_CACHE_FEATURE_METADATA2
|
||||
* in version 1.02.138.
|
||||
*
|
||||
* Binaries compiled against version 1.02.138 onwards will use
|
||||
* the new function dm_tree_node_add_cache_target which detects unknown
|
||||
* feature flags and returns error for them.
|
||||
*/
|
||||
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
uint64_t feature_flags, /* DM_CACHE_FEATURE_* */
|
||||
const char *metadata_uuid,
|
||||
const char *data_uuid,
|
||||
const char *origin_uuid,
|
||||
const char *policy_name,
|
||||
const struct dm_config_node *policy_settings,
|
||||
uint32_t data_block_size);
|
||||
DM_EXPORT_SYMBOL_BASE(dm_tree_node_add_cache_target);
|
||||
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
uint64_t feature_flags,
|
||||
const char *metadata_uuid,
|
||||
const char *data_uuid,
|
||||
const char *origin_uuid,
|
||||
const char *policy_name,
|
||||
const struct dm_config_node *policy_settings,
|
||||
uint32_t data_block_size)
|
||||
{
|
||||
/* Old version supported only these FEATURE bits, others were ignored so masked them */
|
||||
static const uint64_t _mask =
|
||||
DM_CACHE_FEATURE_WRITEBACK |
|
||||
DM_CACHE_FEATURE_WRITETHROUGH |
|
||||
DM_CACHE_FEATURE_PASSTHROUGH;
|
||||
|
||||
return dm_tree_node_add_cache_target(node, size, feature_flags & _mask,
|
||||
metadata_uuid, data_uuid, origin_uuid,
|
||||
policy_name, policy_settings, data_block_size);
|
||||
}
|
||||
#endif
|
||||
|
@ -264,9 +264,12 @@ static int _stats_group_id_present(const struct dm_stats *dms, uint64_t id)
|
||||
if (id == DM_STATS_GROUP_NOT_PRESENT)
|
||||
return 0;
|
||||
|
||||
if (!dms || !dms->regions)
|
||||
if (!dms)
|
||||
return_0;
|
||||
|
||||
if (!dms->regions)
|
||||
return 0;
|
||||
|
||||
if (id > dms->max_region)
|
||||
return 0;
|
||||
|
||||
@ -2384,6 +2387,9 @@ bad:
|
||||
*/
|
||||
void dm_stats_destroy(struct dm_stats *dms)
|
||||
{
|
||||
if (!dms)
|
||||
return;
|
||||
|
||||
_stats_regions_destroy(dms);
|
||||
_stats_groups_destroy(dms);
|
||||
_stats_clear_binding(dms);
|
||||
@ -3312,8 +3318,8 @@ static struct dm_histogram *_aggregate_histogram(const struct dm_stats *dms,
|
||||
uint64_t area_id)
|
||||
{
|
||||
struct dm_histogram *dmh_aggr, *dmh_cur, **dmh_cachep;
|
||||
uint64_t group_id = DM_STATS_GROUP_NOT_PRESENT;
|
||||
int bin, nr_bins, group = 1;
|
||||
uint64_t group_id;
|
||||
size_t hist_size;
|
||||
|
||||
if (area_id == DM_STATS_WALK_REGION) {
|
||||
@ -4874,9 +4880,7 @@ out:
|
||||
dm_free((char *) alias);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else /* HAVE_LINUX_FIEMAP */
|
||||
|
||||
#else /* !HAVE_LINUX_FIEMAP */
|
||||
uint64_t *dm_stats_create_regions_from_fd(struct dm_stats *dms, int fd,
|
||||
int group, int precise,
|
||||
struct dm_histogram *bounds,
|
||||
@ -4894,6 +4898,158 @@ uint64_t *dm_stats_update_regions_from_fd(struct dm_stats *dms, int fd,
|
||||
}
|
||||
#endif /* HAVE_LINUX_FIEMAP */
|
||||
|
||||
#ifdef DMFILEMAPD
|
||||
static const char *_filemapd_mode_names[] = {
|
||||
"inode",
|
||||
"path",
|
||||
NULL
|
||||
};
|
||||
|
||||
dm_filemapd_mode_t dm_filemapd_mode_from_string(const char *mode_str)
|
||||
{
|
||||
dm_filemapd_mode_t mode = DM_FILEMAPD_FOLLOW_INODE;
|
||||
const char **mode_name;
|
||||
|
||||
if (mode_str) {
|
||||
for (mode_name = _filemapd_mode_names; *mode_name; mode_name++)
|
||||
if (!strcmp(*mode_name, mode_str))
|
||||
break;
|
||||
if (*mode_name)
|
||||
mode = DM_FILEMAPD_FOLLOW_INODE
|
||||
+ (mode_name - _filemapd_mode_names);
|
||||
else {
|
||||
log_error("Could not parse dmfilemapd mode: %s",
|
||||
mode_str);
|
||||
return DM_FILEMAPD_FOLLOW_NONE;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
#define DM_FILEMAPD "dmfilemapd"
|
||||
#define NR_FILEMAPD_ARGS 7 /* includes argv[0] */
|
||||
/*
|
||||
* Start dmfilemapd to monitor the specified file descriptor, and to
|
||||
* update the group given by 'group_id' when the file's allocation
|
||||
* changes.
|
||||
*
|
||||
* usage: dmfilemapd <fd> <group_id> <mode> [<foreground>[<log_level>]]
|
||||
*/
|
||||
int dm_stats_start_filemapd(int fd, uint64_t group_id, const char *path,
|
||||
dm_filemapd_mode_t mode, unsigned foreground,
|
||||
unsigned verbose)
|
||||
{
|
||||
char fd_str[8], group_str[8], fg_str[2], verb_str[2];
|
||||
const char *mode_str = _filemapd_mode_names[mode];
|
||||
char *args[NR_FILEMAPD_ARGS + 1];
|
||||
pid_t pid = 0;
|
||||
int argc = 0;
|
||||
|
||||
if (fd < 0) {
|
||||
log_error("dmfilemapd file descriptor must be "
|
||||
"non-negative: %d", fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (path[0] != '/') {
|
||||
log_error("Path argument must specify an absolute path.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode > DM_FILEMAPD_FOLLOW_PATH) {
|
||||
log_error("Invalid dmfilemapd mode argument: "
|
||||
"Must be DM_FILEMAPD_FOLLOW_INODE or "
|
||||
"DM_FILEMAPD_FOLLOW_PATH");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (foreground > 1) {
|
||||
log_error("Invalid dmfilemapd foreground argument. "
|
||||
"Must be 0 or 1: %d.", foreground);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (verbose > 3) {
|
||||
log_error("Invalid dmfilemapd verbose argument. "
|
||||
"Must be 0..3: %d.", verbose);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set argv[0] */
|
||||
args[argc++] = (char *) DM_FILEMAPD;
|
||||
|
||||
/* set <fd> */
|
||||
if ((dm_snprintf(fd_str, sizeof(fd_str), "%d", fd)) < 0) {
|
||||
log_error("Could not format fd argument.");
|
||||
return 0;
|
||||
}
|
||||
args[argc++] = fd_str;
|
||||
|
||||
/* set <group_id> */
|
||||
if ((dm_snprintf(group_str, sizeof(group_str), FMTu64, group_id)) < 0) {
|
||||
log_error("Could not format group_id argument.");
|
||||
return 0;
|
||||
}
|
||||
args[argc++] = group_str;
|
||||
|
||||
/* set <path> */
|
||||
args[argc++] = (char *) path;
|
||||
|
||||
/* set <mode> */
|
||||
args[argc++] = (char *) mode_str;
|
||||
|
||||
/* set <foreground> */
|
||||
if ((dm_snprintf(fg_str, sizeof(fg_str), "%u", foreground)) < 0) {
|
||||
log_error("Could not format foreground argument.");
|
||||
return 0;
|
||||
}
|
||||
args[argc++] = fg_str;
|
||||
|
||||
/* set <verbose> */
|
||||
if ((dm_snprintf(verb_str, sizeof(verb_str), "%u", verbose)) < 0) {
|
||||
log_error("Could not format verbose argument.");
|
||||
return 0;
|
||||
}
|
||||
args[argc++] = verb_str;
|
||||
|
||||
/* terminate args[argc] */
|
||||
args[argc] = NULL;
|
||||
|
||||
log_very_verbose("Spawning daemon as '%s %d " FMTu64 " %s %s %u %u'",
|
||||
*args, fd, group_id, path, mode_str,
|
||||
foreground, verbose);
|
||||
|
||||
if (!foreground && ((pid = fork()) < 0)) {
|
||||
log_error("Failed to fork dmfilemapd process.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
log_very_verbose("Forked dmfilemapd process as pid %d", pid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
execvp(args[0], args);
|
||||
log_error("execvp() failed.");
|
||||
if (!foreground)
|
||||
_exit(127);
|
||||
return 0;
|
||||
}
|
||||
# else /* !DMFILEMAPD */
|
||||
dm_filemapd_mode_t dm_filemapd_mode_from_string(const char *mode_str)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
int dm_stats_start_filemapd(int fd, uint64_t group_id, const char *path,
|
||||
dm_filemapd_mode_t mode, unsigned foreground,
|
||||
unsigned verbose)
|
||||
{
|
||||
log_error("dmfilemapd support disabled.");
|
||||
return 0;
|
||||
}
|
||||
#endif /* DMFILEMAPD */
|
||||
|
||||
/*
|
||||
* Backward compatible dm_stats_create_region() implementations.
|
||||
*
|
||||
|
@ -89,6 +89,8 @@ static unsigned _count_fields(const char *p)
|
||||
* <raid_type> <#devs> <health_str> <sync_ratio>
|
||||
* Versions 1.5.0+ (6 fields):
|
||||
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt>
|
||||
* Versions 1.9.0+ (7 fields):
|
||||
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt> <data_offset>
|
||||
*/
|
||||
int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
struct dm_status_raid **status)
|
||||
@ -117,7 +119,7 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
goto_bad;
|
||||
|
||||
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
|
||||
if (sscanf(params, "%s %u %s %" PRIu64 "/%" PRIu64,
|
||||
if (sscanf(params, "%s %u %s " FMTu64 "/" FMTu64,
|
||||
s->raid_type,
|
||||
&s->dev_count,
|
||||
s->dev_health,
|
||||
@ -144,9 +146,25 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
if (!(s->sync_action = dm_pool_zalloc(mem, pp - p)))
|
||||
goto_bad;
|
||||
|
||||
if (sscanf(p, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2)
|
||||
if (sscanf(p, "%s " FMTu64, s->sync_action, &s->mismatch_count) != 2)
|
||||
goto_bad;
|
||||
|
||||
if (num_fields < 7)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* All pre-1.9.0 version parameters are read. Now we check
|
||||
* for additional 1.9.0+ parameters (i.e. nr_fields at least 7).
|
||||
*
|
||||
* Note that data_offset will be 0 if the
|
||||
* kernel returns a pre-1.9.0 status.
|
||||
*/
|
||||
msg_fields = "<data_offset>";
|
||||
if (!(p = _skip_fields(params, 6))) /* skip pre-1.9.0 params */
|
||||
goto bad;
|
||||
if (sscanf(p, FMTu64, &s->data_offset) != 1)
|
||||
goto bad;
|
||||
|
||||
out:
|
||||
*status = s;
|
||||
|
||||
@ -226,14 +244,14 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
|
||||
|
||||
/* Read in args that have definitive placement */
|
||||
if (sscanf(params,
|
||||
" %" PRIu32
|
||||
" %" PRIu64 "/%" PRIu64
|
||||
" %" PRIu32
|
||||
" %" PRIu64 "/%" PRIu64
|
||||
" %" PRIu64 " %" PRIu64
|
||||
" %" PRIu64 " %" PRIu64
|
||||
" %" PRIu64 " %" PRIu64
|
||||
" %" PRIu64
|
||||
" " FMTu32
|
||||
" " FMTu64 "/" FMTu64
|
||||
" " FMTu32
|
||||
" " FMTu64 "/" FMTu64
|
||||
" " FMTu64 " " FMTu64
|
||||
" " FMTu64 " " FMTu64
|
||||
" " FMTu64 " " FMTu64
|
||||
" " FMTu64
|
||||
" %d",
|
||||
&s->metadata_block_size,
|
||||
&s->metadata_used_blocks, &s->metadata_total_blocks,
|
||||
@ -256,8 +274,10 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
|
||||
s->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
|
||||
else if (!strncmp(p, "writeback ", 10))
|
||||
s->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
|
||||
else if (!strncmp(p, "passthrough ", 11))
|
||||
else if (!strncmp(p, "passthrough ", 12))
|
||||
s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
|
||||
else if (!strncmp(p, "metadata2 ", 10))
|
||||
s->feature_flags |= DM_CACHE_FEATURE_METADATA2;
|
||||
else
|
||||
log_error("Unknown feature in status: %s", params);
|
||||
|
||||
|
@ -44,6 +44,8 @@ EGREP = @EGREP@
|
||||
GREP = @GREP@
|
||||
SORT = @SORT@
|
||||
WC = @WC@
|
||||
AR = ar
|
||||
RM = rm -f
|
||||
|
||||
PYTHON2 = @PYTHON2@
|
||||
PYTHON3 = @PYTHON3@
|
||||
@ -156,6 +158,7 @@ INSTALL_ROOT_DIR = $(INSTALL) -m 700 -d
|
||||
INSTALL_ROOT_DATA = $(INSTALL) -m 600
|
||||
INSTALL_SCRIPT = $(INSTALL) -p $(M_INSTALL_PROGRAM)
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .cpp .d .o .so .a .po .pot .mo .dylib
|
||||
|
||||
WFLAGS +=\
|
||||
@ -410,6 +413,8 @@ cflow: $(CFLOW_TARGET).cflow $(CFLOW_TARGET).tree $(CFLOW_TARGET).rxref $(CFLOW_
|
||||
endif
|
||||
endif
|
||||
|
||||
.LIBPATTERNS = lib%.so lib%.a
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(INCLUDES) $(DEFS) $(WFLAGS) $(WCFLAGS) $(CFLAGS) $(CFLAGS_$@) $< -o $@
|
||||
|
||||
@ -461,7 +466,7 @@ endif
|
||||
|
||||
$(LIB_STATIC): $(OBJECTS)
|
||||
$(RM) $@
|
||||
$(AR) rs $@ $(OBJECTS)
|
||||
$(AR) rsv $@ $(OBJECTS)
|
||||
|
||||
%.d: %.c $(INC_LNS)
|
||||
$(MKDIR_P) $(dir $@); \
|
||||
|
2
man/.gitignore
vendored
Normal file
2
man/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.gen
|
||||
man-generator
|
109
man/Makefile.in
109
man/Makefile.in
@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@ -31,20 +31,19 @@ LVMRAIDMAN = lvmraid.7
|
||||
|
||||
MAN5=lvm.conf.5
|
||||
MAN7=lvmsystemid.7 lvmreport.7
|
||||
MAN8=lvm.8 lvmconf.8 lvmdump.8
|
||||
MAN8DM=dmsetup.8 dmstats.8
|
||||
MAN8=lvm.8 lvmconf.8 lvmdump.8 lvm-config.8 lvm-dumpconfig.8 lvm-fullreport.8 \
|
||||
lvm-lvpoll.8 lvcreate.8 lvchange.8 lvmconfig.8 lvconvert.8 lvdisplay.8 \
|
||||
lvextend.8 lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
|
||||
lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
|
||||
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
|
||||
vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
|
||||
vgimport.8 vgimportclone.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 \
|
||||
vgrename.8 vgs.8 vgscan.8 vgsplit.8 \
|
||||
lvmsar.8 lvmsadc.8 lvmdiskscan.8 lvmchange.8
|
||||
MAN8DM=dmsetup.8 dmstats.8 dmfilemapd.8
|
||||
MAN8CLUSTER=
|
||||
MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8
|
||||
|
||||
MAN8GEN=lvm-config.8 lvm-dumpconfig.8 lvm-fullreport.8 lvm-lvpoll.8 \
|
||||
lvcreate.8 lvchange.8 lvmconfig.8 lvconvert.8 lvdisplay.8 lvextend.8 \
|
||||
lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
|
||||
lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
|
||||
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
|
||||
vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
|
||||
vgimport.8 vgimportclone.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 \
|
||||
vgrename.8 vgs.8 vgscan.8 vgsplit.8 \
|
||||
lvmsar.8 lvmsadc.8 lvmdiskscan.8 lvmchange.8
|
||||
|
||||
ifeq ($(MAKECMDGOALS),all_man)
|
||||
MAN_ALL="yes"
|
||||
@ -113,46 +112,73 @@ MAN5DIR=$(mandir)/man5
|
||||
MAN7DIR=$(mandir)/man7
|
||||
MAN8DIR=$(mandir)/man8
|
||||
|
||||
MANGENERATOR=./man-generator
|
||||
TESTMAN=test.gen
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
CLEAN_TARGETS+=$(MAN5) $(MAN7) $(MAN8) $(MAN8GEN) $(MAN8CLUSTER) \
|
||||
$(MAN8SYSTEMD_GENERATORS) $(MAN8DM) *.gen man-generator
|
||||
CLEAN_TARGETS+=$(MAN5) $(MAN7) $(MAN8) $(MAN8:%.8_gen=%.8) $(MAN8CLUSTER) \
|
||||
$(MAN8SYSTEMD_GENERATORS) $(MAN8DM) $(MANGENERATOR) $(TESTMAN)
|
||||
DISTCLEAN_TARGETS+=$(FSADMMAN) $(BLKDEACTIVATEMAN) $(DMEVENTDMAN) \
|
||||
$(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(CLVMDMAN) $(CMIRRORDMAN) \
|
||||
$(LVMCACHEMAN) $(LVMTHINMAN) $(LVMDBUSDMAN) $(LVMRAIDMAN)
|
||||
|
||||
all: man device-mapper
|
||||
|
||||
.PHONY: man install_man5 install_man7 install_man8
|
||||
.PHONY: man install_man5 install_man7 install_man8 pregenerated_man
|
||||
|
||||
device-mapper: $(MAN8DM)
|
||||
|
||||
man: $(MAN5) $(MAN7) $(MAN8) $(MAN8GEN) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS)
|
||||
man: $(MAN5) $(MAN7) $(MAN8) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS)
|
||||
|
||||
all_man: man
|
||||
|
||||
$(MAN5) $(MAN7) $(MAN8) $(MAN8GEN) $(MAN8DM) $(MAN8CLUSTER): Makefile
|
||||
$(MAN5) $(MAN7) $(MAN8) $(MAN8DM) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS): Makefile
|
||||
|
||||
Makefile: Makefile.in
|
||||
@:
|
||||
|
||||
%: %.in
|
||||
@case "$@" in \
|
||||
*/*) ;; \
|
||||
*) echo "Creating $@" ; $(SED) -e "s+#VERSION#+$(LVM_VERSION)+;s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+;s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+;s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+;s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+;s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+;s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+;s+#CLVMD_PATH#+@CLVMD_PATH@+;s+#LVM_PATH#+@LVM_PATH@+;s+#DEFAULT_RUN_DIR#+@DEFAULT_RUN_DIR@+;s+#DEFAULT_PID_DIR#+@DEFAULT_PID_DIR@+;s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+;s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+;" $< > $@ ;; \
|
||||
esac
|
||||
|
||||
man-generator:
|
||||
$(MANGENERATOR): Makefile
|
||||
$(CC) -DMAN_PAGE_GENERATOR -I$(top_builddir)/tools $(CFLAGS) $(top_srcdir)/tools/command.c -o $@
|
||||
- ./man-generator lvmconfig > test.gen
|
||||
if [ ! -s test.gen ] ; then cp genfiles/*.gen $(top_builddir)/man; fi;
|
||||
|
||||
$(MAN8GEN): man-generator
|
||||
echo "Generating $@" ;
|
||||
if [ ! -e $@.gen ]; then ./man-generator $(basename $@) $(top_srcdir)/man/$@.des > $@.gen; fi
|
||||
if [ -f $(top_srcdir)/man/$@.end ]; then cat $(top_srcdir)/man/$@.end >> $@.gen; fi;
|
||||
cat $(top_srcdir)/man/see_also.end >> $@.gen
|
||||
$(SED) -e "s+#VERSION#+$(LVM_VERSION)+;s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+;s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+;s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+;s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+;s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+;s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+;s+#CLVMD_PATH#+@CLVMD_PATH@+;s+#LVM_PATH#+@LVM_PATH@+;s+#DEFAULT_RUN_DIR#+@DEFAULT_RUN_DIR@+;s+#DEFAULT_PID_DIR#+@DEFAULT_PID_DIR@+;s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+;s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+;" $@.gen > $@
|
||||
# Test whether or not the man page generator works
|
||||
$(TESTMAN): $(MANGENERATOR)
|
||||
- $(MANGENERATOR) --primary lvmconfig > $@
|
||||
|
||||
SEE_ALSO=$(srcdir)/see_also.end
|
||||
|
||||
%.8_gen: $(srcdir)/%.8_des $(srcdir)/%.8_end $(MANGENERATOR) $(TESTMAN)
|
||||
( \
|
||||
if [ ! -s $(TESTMAN) ] ; then \
|
||||
echo "Copying pre-generated $@" ; \
|
||||
else \
|
||||
echo "Generating $@" ; \
|
||||
fi \
|
||||
)
|
||||
( \
|
||||
if [ ! -s $(TESTMAN) ] ; then \
|
||||
cat $(srcdir)/$(@:%.8_gen=%.8_pregen) ; \
|
||||
else \
|
||||
MANCMD=$(basename $@) && \
|
||||
$(MANGENERATOR) --primary $$MANCMD $< && \
|
||||
$(MANGENERATOR) --secondary $$MANCMD && \
|
||||
cat $(srcdir)/$(basename $@).8_end && \
|
||||
cat $(SEE_ALSO) ; \
|
||||
fi \
|
||||
) > $@
|
||||
|
||||
define SUBSTVARS
|
||||
echo "Generating $@" ; $(SED) -e "s+#VERSION#+$(LVM_VERSION)+;s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+;s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+;s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+;s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+;s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+;s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+;s+#CLVMD_PATH#+/data/lvmtest/usr/sbin/clvmd+;s+#LVM_PATH#+/data/lvmtest/sbin/lvm+;s+#DEFAULT_RUN_DIR#+/var/run/lvm+;s+#DEFAULT_PID_DIR#+/var/run+;s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+;s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+;" $< > $@
|
||||
endef
|
||||
|
||||
%.5: $(srcdir)/%.5_main
|
||||
$(SUBSTVARS)
|
||||
|
||||
%.7: $(srcdir)/%.7_main
|
||||
$(SUBSTVARS)
|
||||
|
||||
%.8: $(srcdir)/%.8_main
|
||||
$(SUBSTVARS)
|
||||
|
||||
%.8: %.8_gen
|
||||
$(SUBSTVARS)
|
||||
|
||||
install_man5: $(MAN5)
|
||||
$(INSTALL) -d $(MAN5DIR)
|
||||
@ -162,10 +188,10 @@ install_man7: $(MAN7)
|
||||
$(INSTALL) -d $(MAN7DIR)
|
||||
$(INSTALL_DATA) $(MAN7) $(MAN7DIR)/
|
||||
|
||||
install_man8: $(MAN8) $(MAN8GEN)
|
||||
install_man8: $(MAN8) $(MAN8GENERATED)
|
||||
$(INSTALL) -d $(MAN8DIR)
|
||||
$(INSTALL_DATA) $(MAN8) $(MAN8DIR)/
|
||||
$(INSTALL_DATA) $(MAN8GEN) $(MAN8DIR)/
|
||||
$(INSTALL_DATA) $(MAN8GENERATED) $(MAN8DIR)/
|
||||
|
||||
install_lvm2: install_man5 install_man7 install_man8
|
||||
|
||||
@ -186,3 +212,12 @@ install_systemd_generators: $(MAN8SYSTEMD_GENERATORS)
|
||||
install: install_lvm2 install_device-mapper install_cluster
|
||||
|
||||
install_all_man: install install_systemd_generators
|
||||
|
||||
# Copy generated man pages back to source tree as fallback for machines where generator doesn't work
|
||||
pregenerated_man: all
|
||||
for i in $(srcdir)/*.8_des; do \
|
||||
CMD=`basename $$i .8_des`; \
|
||||
cat $${CMD}.8 > $(srcdir)/$$CMD.8_pregen ; \
|
||||
done
|
||||
|
||||
generate: pregenerated_man
|
||||
|
@ -12,8 +12,8 @@ blkdeactivate \(em utility to deactivate block devices
|
||||
.RB [ \-v ]
|
||||
.RI [ device ]
|
||||
.SH DESCRIPTION
|
||||
blkdeactivate utility deactivates block devices. If a device
|
||||
is mounted, the utility can unmount it automatically before
|
||||
The blkdeactivate utility deactivates block devices. For mounted
|
||||
block devices, it attempts to unmount it automatically before
|
||||
trying to deactivate. The utility currently supports
|
||||
device-mapper devices (DM), including LVM volumes and
|
||||
software RAID MD devices. LVM volumes are handled directly
|
||||
@ -35,30 +35,30 @@ Force device removal.
|
||||
.BR \-e ", " \-\-errors
|
||||
Show errors reported from tools called by \fBblkdeactivate\fP. Without this
|
||||
option, any error messages from these external tools are suppressed and the
|
||||
\fBblkdeactivate\fP itself provides only a summary message about device being
|
||||
skipped or not.
|
||||
\fBblkdeactivate\fP itself provides only a summary message to indicate
|
||||
the device was skipped.
|
||||
.TP
|
||||
.BR \-h ", " \-\-help
|
||||
Display the help text.
|
||||
.TP
|
||||
.BR \-l ", " \-\-lvmoption \ \fIlvm_options\fP
|
||||
Comma separated list of LVM specific options:
|
||||
Comma-separated list of LVM specific options:
|
||||
.RS
|
||||
.IP \fIretry\fP
|
||||
Retry removal several times in case of failure.
|
||||
.IP \fIwholevg\fP
|
||||
Deactivate the whole LVM Volume Group when processing a Logical Volume.
|
||||
Deactivating Volume Group as a whole takes less time than deactivating each
|
||||
Logical Volume separately.
|
||||
Deactivating the Volume Group as a whole is quicker than deactivating
|
||||
each Logical Volume separately.
|
||||
.RE
|
||||
.TP
|
||||
.BR \-m ", " \-\-mpathoption \ \fImpath_options\fP
|
||||
Comma separated list of device-mapper multipath specific options:
|
||||
Comma-separated list of device-mapper multipath specific options:
|
||||
.RS
|
||||
.IP \fIdisablequeueing\fP
|
||||
Disable queueing on all multipath devices first before deactivation.
|
||||
Disable queueing on all multipath devices before deactivation.
|
||||
This avoids a situation where blkdeactivate may end up waiting if
|
||||
all paths are unavailable for any underlying device-mapper multipath
|
||||
all the paths are unavailable for any underlying device-mapper multipath
|
||||
device.
|
||||
.RE
|
||||
.TP
|
||||
@ -69,33 +69,42 @@ Without this option used, a device that is mounted is not deactivated.
|
||||
.BR \-v ", " \-\-verbose
|
||||
Run in verbose mode. Use \-\-vv for even more verbose mode.
|
||||
.SH EXAMPLES
|
||||
.sp
|
||||
Deactivate all supported block devices found in the system. If a device
|
||||
is mounted, skip its deactivation.
|
||||
.sp
|
||||
.
|
||||
Deactivate all supported block devices found in the system, skipping mounted
|
||||
devices.
|
||||
.BR
|
||||
#
|
||||
.B blkdeactivate
|
||||
|
||||
Deactivate all supported block devices found in the system. If a device
|
||||
is mounted, unmount it first if possible.
|
||||
.sp
|
||||
.BR
|
||||
.P
|
||||
Deactivate all supported block devices found in the system, unmounting any
|
||||
mounted devices first, if possible.
|
||||
.BR
|
||||
#
|
||||
.B blkdeactivate \-u
|
||||
|
||||
Deactivate supplied device together with all its holders. If any of the
|
||||
devices processed is mounted, unmount it first if possible.
|
||||
.sp
|
||||
.BR
|
||||
.P
|
||||
Deactivate the device /dev/vg/lvol0 together with all its holders, unmounting
|
||||
any mounted devices first, if possible.
|
||||
.BR
|
||||
#
|
||||
.B blkdeactivate \-u /dev/vg/lvol0
|
||||
|
||||
Deactivate all supported block devices found in the system. Retry deactivation
|
||||
of device-mapper devices in case the deactivation fails. Deactivate the whole
|
||||
.BR
|
||||
.P
|
||||
Deactivate all supported block devices found in the system. If the deactivation
|
||||
of a device-mapper device fails, retry it. Deactivate the whole
|
||||
Volume Group at once when processing an LVM Logical Volume.
|
||||
.sp
|
||||
.BR
|
||||
#
|
||||
.B blkdeactivate \-u \-d retry \-l wholevg
|
||||
|
||||
Deactivate all supported block devices found in the system. Retry deactivation
|
||||
of device-mapper devices in case the deactivation fails and force removal.
|
||||
.sp
|
||||
.BR
|
||||
.P
|
||||
Deactivate all supported block devices found in the system. If the deactivation
|
||||
of a device-mapper device fails, retry it and force removal.
|
||||
.BR
|
||||
#
|
||||
.B blkdeactivate \-d force,retry
|
||||
|
||||
.
|
||||
.SH SEE ALSO
|
||||
.BR dmsetup (8),
|
||||
.BR lsblk (8),
|
@ -176,9 +176,9 @@ clvmd attempts to activate the LV only on the local node.
|
||||
If the LV type allows concurrent access, then shared mode is used,
|
||||
otherwise exclusive.
|
||||
.IP \fBn\fP
|
||||
clvmd deactivates the LV on all nodes.
|
||||
clvmd attempts to deactivate the LV on all nodes.
|
||||
.IP \fBln\fP
|
||||
clvmd deactivates the LV on the local node.
|
||||
clvmd attempts to deactivate the LV on the local node.
|
||||
.
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.TP
|
212
man/dmfilemapd.8_main
Normal file
212
man/dmfilemapd.8_main
Normal file
@ -0,0 +1,212 @@
|
||||
.TH DMFILEMAPD 8 "Dec 17 2016" "Linux" "MAINTENANCE COMMANDS"
|
||||
|
||||
.de OPT_FD
|
||||
. RB [ file_descriptor ]
|
||||
..
|
||||
.
|
||||
.de OPT_GROUP
|
||||
. RB [ group_id ]
|
||||
..
|
||||
.de OPT_PATH
|
||||
. RB [ abs_path ]
|
||||
..
|
||||
.
|
||||
.de OPT_MODE
|
||||
. RB [ mode ]
|
||||
..
|
||||
.
|
||||
.de OPT_DEBUG
|
||||
. RB [ foreground [ verbose ] ]
|
||||
..
|
||||
.
|
||||
.SH NAME
|
||||
.
|
||||
dmfilemapd \(em device-mapper filemap monitoring daemon
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
.
|
||||
.de CMD_DMFILEMAPD
|
||||
. ad l
|
||||
. IR dmfilemapd
|
||||
. OPT_FD
|
||||
. OPT_GROUP
|
||||
. OPT_PATH
|
||||
. OPT_MODE
|
||||
. OPT_DEBUG
|
||||
. ad b
|
||||
..
|
||||
.CMD_DMFILEMAPD
|
||||
.
|
||||
.PD
|
||||
.ad b
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
.
|
||||
The dmfilemapd daemon monitors groups of \fIdmstats\fP regions that
|
||||
correspond to the extents of a file, adding and removing regions to
|
||||
reflect the changing state of the file on-disk.
|
||||
|
||||
The daemon is normally launched automatically by the \fPdmstats
|
||||
create\fP command, but can be run manually, either to create a new
|
||||
daemon where one did not previously exist, or to change the options
|
||||
previously used, by killing the existing daemon and starting a new
|
||||
one.
|
||||
.
|
||||
.SH OPTIONS
|
||||
.
|
||||
.HP
|
||||
.BR file_descriptor
|
||||
.br
|
||||
Specify the file descriptor number for the file to be monitored.
|
||||
The file descriptor must reference a regular file, open for reading,
|
||||
in a local file system that supports the FIEMAP ioctl, and that
|
||||
returns data describing the physical location of extents.
|
||||
|
||||
The process that executes \fBdmfilemapd\fP is responsible for
|
||||
opening the file descriptor that is handed to the daemon.
|
||||
.
|
||||
.HP
|
||||
.BR group_id
|
||||
.br
|
||||
The \fBdmstats\fP group identifier of the group that \fBdmfilemapd\fP
|
||||
should update. The group must exist and it should correspond to
|
||||
a set of regions created by a previous filemap operation.
|
||||
.
|
||||
.HP
|
||||
.BR abs_path
|
||||
.br
|
||||
The absolute path to the file being monitored, at the time that
|
||||
it was opened. The use of \fBpath\fP by the daemon differs,
|
||||
depending on the filemap following mode in use; see \fBMODES\fP
|
||||
and the \fBmode\fP option for more information.
|
||||
|
||||
.br
|
||||
.HP
|
||||
.BR mode
|
||||
.br
|
||||
The filemap monitoring mode the daemon should use: either "inode"
|
||||
(\fBDM_FILEMAP_FOLLOW_INODE\fP), or "path"
|
||||
(\fBDM_FILEMAP_FOLLOW_PATH\fP), to enable follow-inode or
|
||||
follow-path mode respectively.
|
||||
.
|
||||
.HP
|
||||
.BR [foreground]
|
||||
.br
|
||||
If set to 1, disable forking and allow the daemon to run in the
|
||||
foreground.
|
||||
.
|
||||
.HP
|
||||
.BR [verbose]
|
||||
Control daemon logging. If set to zero, the daemon will close all
|
||||
stdio streams and run silently. If \fBverbose\fP is a number
|
||||
between 1 and 3, stdio will be retained and the daemon will log
|
||||
messages to stdout and stderr that match the specified verbosity
|
||||
level.
|
||||
.
|
||||
.
|
||||
.SH MODES
|
||||
.
|
||||
The file map monitoring daemon can monitor files in two distinct
|
||||
ways: the mode affects the behaviour of the daemon when a file
|
||||
under monitoring is renamed or unlinked, and the conditions which
|
||||
cause the daemon to terminate.
|
||||
|
||||
In both modes, the daemon will always shut down when the group
|
||||
being monitored is deleted.
|
||||
|
||||
.P
|
||||
.B Follow inode
|
||||
.P
|
||||
The daemon follows the inode of the file, as it was at the time the
|
||||
daemon started. The file descriptor referencing the file is kept
|
||||
open at all times, and the daemon will exit when it detects that
|
||||
the file has been unlinked and it is the last holder of a reference
|
||||
to the file.
|
||||
|
||||
This mode is useful if the file is expected to be renamed, or moved
|
||||
within the file system, while it is being monitored.
|
||||
|
||||
.P
|
||||
.B Follow path
|
||||
.P
|
||||
The daemon follows the path that was given on the daemon command
|
||||
line. The file descriptor referencing the file is re-opened on each
|
||||
iteration of the daemon, and the daemon will exit if no file exists
|
||||
at this location (a tolerance is allowed so that a brief delay
|
||||
between removal and replacement is permitted).
|
||||
|
||||
This mode is useful if the file is updated by unlinking the original
|
||||
and placing a new file at the same path.
|
||||
.
|
||||
.SH LIMITATIONS
|
||||
.
|
||||
The daemon attempts to maintain good synchronisation between the file
|
||||
extents and the regions contained in the group, however, since the
|
||||
daemon can only react to new allocations once they have been written,
|
||||
there are inevitably some IO events that cannot be counted when a
|
||||
file is growing, particularly if the file is being extended by a
|
||||
single thread writing beyond EOF (for example, the \fBdd\fP program).
|
||||
|
||||
There is a further loss of events in that there is currently no way
|
||||
to atomically resize a \fBdmstats\fP region and preserve its current
|
||||
counter values. This affects files when they grow by extending the
|
||||
final extent, rather than allocating a new extent: any events that
|
||||
had accumulated in the region between any prior operation and the
|
||||
resize are lost.
|
||||
|
||||
File mapping is currently most effective in cases where the majority
|
||||
of IO does not trigger extent allocation. Future updates may address
|
||||
these limitations when kernel support is available.
|
||||
.
|
||||
.SH EXAMPLES
|
||||
.
|
||||
Normally the daemon is started automatically by the \fBdmstats\fP
|
||||
\fBcreate\fP or \fBupdate_filemap\fP commands but it can be run
|
||||
manually for debugging or testing purposes.
|
||||
.P
|
||||
Start the daemon in the background, in follow-path mode
|
||||
.br
|
||||
#
|
||||
.B dmfilemapd 3 0 /srv/images/vm.img path 0 0 3< /srv/images/vm.img
|
||||
.br
|
||||
.P
|
||||
Start the daemon in follow-inode mode, disable forking and enable
|
||||
verbose logging
|
||||
.br
|
||||
#
|
||||
.B dmfilemapd 3 0 /var/tmp/data inode 1 3 3< /var/tmp/data
|
||||
.br
|
||||
Starting dmfilemapd with fd=3, group_id=0 mode=inode, path=/var/tmp/data
|
||||
.br
|
||||
dm version [ opencount flush ] [16384] (*1)
|
||||
.br
|
||||
dm info (253:0) [ opencount flush ] [16384] (*1)
|
||||
.br
|
||||
dm message (253:0) [ opencount flush ] @stats_list dmstats [16384] (*1)
|
||||
.br
|
||||
Read alias 'data' from aux_data
|
||||
.br
|
||||
Found group_id 0: alias="data"
|
||||
.br
|
||||
dm_stats_walk_init: initialised flags to 4000000000000
|
||||
.br
|
||||
starting stats walk with GROUP
|
||||
.br
|
||||
exiting _filemap_monitor_get_events() with deleted=0, check=0
|
||||
.br
|
||||
Waiting for check interval
|
||||
.br
|
||||
.P
|
||||
.
|
||||
.SH AUTHORS
|
||||
.
|
||||
Bryn M. Reeves <bmr@redhat.com>
|
||||
.
|
||||
.SH SEE ALSO
|
||||
.
|
||||
.BR dmstats (8)
|
||||
|
||||
LVM2 resource page: https://www.sourceware.org/lvm2/
|
||||
.br
|
||||
Device-mapper resource page: http://sources.redhat.com/dm/
|
||||
.br
|
@ -14,6 +14,9 @@
|
||||
. RB [ \-\-region ]
|
||||
. RB [ \-\-group ]
|
||||
..
|
||||
.de OPT_FOREGROUND
|
||||
. RB [ \-\-foreground ]
|
||||
..
|
||||
.
|
||||
.\" Print units suffix, use with arg to print human
|
||||
.\" man2html can't handle too many changes per command
|
||||
@ -89,6 +92,10 @@ dmstats \(em device-mapper statistics management
|
||||
. RB [ \-\-bounds
|
||||
. IR \%histogram_boundaries ]
|
||||
. RB [ \-\-filemap ]
|
||||
. RB [ \-\-follow
|
||||
. IR follow_mode ]
|
||||
. OPT_FOREGROUND
|
||||
. RB [ \-\-nomonitor ]
|
||||
. RB [ \-\-nogroup ]
|
||||
. RB [ \-\-precise ]
|
||||
. RB [ \-\-start
|
||||
@ -215,6 +222,9 @@ dmstats \(em device-mapper statistics management
|
||||
. IR file_path
|
||||
. RB [ \-\-groupid
|
||||
. IR id ]
|
||||
. RB [ \-\-follow
|
||||
. IR follow_mode ]
|
||||
. OPT_FOREGROUND
|
||||
. ad b
|
||||
..
|
||||
.CMD_UPDATE_FILEMAP
|
||||
@ -314,6 +324,60 @@ create regions corresponding to the locations of the on-disk extents
|
||||
allocated to the file(s).
|
||||
.
|
||||
.HP
|
||||
.BR \-\-nomonitor
|
||||
.br
|
||||
Disable the \fBdmfilemapd\fP daemon when creating new file mapped
|
||||
groups. Normally the device-mapper filemap monitoring daemon,
|
||||
\fBdmfilemapd\fP, is started for each file mapped group to update the
|
||||
set of regions as the file changes on-disk: use of this option
|
||||
disables this behaviour.
|
||||
|
||||
Regions in the group may still be updated with the
|
||||
\fBupdate_filemap\fP command, or by starting the daemon manually.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-follow
|
||||
.IR follow_mode
|
||||
.br
|
||||
Specify the \fBdmfilemapd\fP file following mode. The file map
|
||||
monitoring daemon can monitor files in two distinct ways: the mode
|
||||
affects the behaviour of the daemon when a file under monitoring is
|
||||
renamed or unlinked, and the conditions which cause the daemon to
|
||||
terminate.
|
||||
|
||||
The \fBfollow_mode\fP argument is either "inode", for follow-inode
|
||||
mode, or "path", for follow-path.
|
||||
|
||||
If follow-inode mode is used, the daemon will hold the file open, and
|
||||
continue to update regions from the same file descriptor. This means
|
||||
that the mapping will follow rename, move (within the same file
|
||||
system), and unlink operations. This mode is useful if the file is
|
||||
expected to be moved, renamed, or unlinked while it is being
|
||||
monitored.
|
||||
|
||||
In follow-inode mode, the daemon will exit once it detects that the
|
||||
file has been unlinked and it is the last holder of a reference to it.
|
||||
|
||||
If follow-path is used, the daemon will re-open the provided path on
|
||||
each monitoring iteration. This means that the group will be updated
|
||||
to reflect a new file being moved to the same path as the original
|
||||
file. This mode is useful for files that are expected to be updated
|
||||
via unlink and rename.
|
||||
|
||||
In follow-path mode, the daemon will exit if the file is removed and
|
||||
not replaced within a brief tolerance interval.
|
||||
|
||||
In either mode, the daemon exits automatically if the monitored group
|
||||
is removed.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-foreground
|
||||
.br
|
||||
Specify that the \fBdmfilemapd\fP daemon should run in the foreground.
|
||||
The daemon will not fork into the background, and will replace the
|
||||
\fBdmstats\fP command that started it.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-groupid
|
||||
.IR id
|
||||
.br
|
||||
@ -568,6 +632,11 @@ By default regions that map a file are placed into a group and the
|
||||
group alias is set to the basename of the file. This behaviour can be
|
||||
overridden with the \fB\-\-alias\fP and \fB\-\-nogroup\fP options.
|
||||
|
||||
Creating a group that maps a file automatically starts a daemon,
|
||||
\fBdmfilemapd\fP to monitor the file and update the mapping as the
|
||||
extents allocated to the file change. This behaviour can be disabled
|
||||
using the \fB\-\-nomonitor\fP option.
|
||||
|
||||
Use the \fB\-\-group\fP option to only display information for groups
|
||||
when listing and reporting.
|
||||
.
|
||||
@ -678,17 +747,23 @@ The group to be removed is specified using \fB\-\-groupid\fP.
|
||||
.CMD_UPDATE_FILEMAP
|
||||
.br
|
||||
Update a group of \fBdmstats\fP regions specified by \fBgroup_id\fP,
|
||||
that were previously created with \fB\-\-filemap\fP. This will add
|
||||
and remove regions to reflect changes in the allocated extents of
|
||||
the file on-disk, since the time that it was crated or last updated.
|
||||
that were previously created with \fB\-\-filemap\fP, either directly,
|
||||
or by starting the monitoring daemon, \fBdmfilemapd\fP.
|
||||
|
||||
This will add and remove regions to reflect changes in the allocated
|
||||
extents of the file on-disk, since the time that it was crated or last
|
||||
updated.
|
||||
|
||||
Use of this command is not normally needed since the \fBdmfilemapd\fP
|
||||
daemon will automatically monitor filemap groups and perform these
|
||||
updates when required.
|
||||
|
||||
If a filemapped group was created with \fB\-\-nominitor\fP, or the
|
||||
If a filemapped group was created with \fB\-\-nomonitor\fP, or the
|
||||
daemon has been killed, the \fBupdate_filemap\fP can be used to
|
||||
manually force an update.
|
||||
manually force an update or start a new daemon.
|
||||
|
||||
Use \fB\-\-nomonitor\fP to force a direct update and disable starting
|
||||
the monitoring daemon.
|
||||
.
|
||||
.SH REGIONS, AREAS, AND GROUPS
|
||||
.
|
||||
@ -750,6 +825,93 @@ containing device.
|
||||
The \fBgroup_id\fP should be treated as an opaque identifier used to
|
||||
reference the group.
|
||||
.
|
||||
.SH FILE MAPPING
|
||||
.
|
||||
Using \fB\-\-filemap\fP, it is possible to create regions that
|
||||
correspond to the extents of a file in the file system. This allows
|
||||
IO statistics to be monitored on a per-file basis, for example to
|
||||
observe large database files, virtual machine images, or other files
|
||||
of interest.
|
||||
|
||||
To be able to use file mapping, the file must be backed by a
|
||||
device-mapper device, and in a file system that supports the FIEMAP
|
||||
ioctl (and which returns data describing the physical location of
|
||||
extents). This currently includes \fBxfs(5)\fP and \fBext4(5)\fP.
|
||||
|
||||
By default the regions making up a file are placed together in a
|
||||
group, and the group alias is set to the \fBbasename(3)\fP of the
|
||||
file. This allows statistics to be reported for the file as a whole,
|
||||
aggregating values for the regions making up the group. To see only
|
||||
the whole file (group) when using the \fBlist\fP and \fBreport\fP
|
||||
commands, use \fB\-\-group\fP.
|
||||
|
||||
Since it is possible for the file to change after the initial
|
||||
group of regions is created, the \fBupdate_filemap\fP command, and
|
||||
\fBdmfilemapd\fP daemon are provided to update file mapped groups
|
||||
either manually or automatically.
|
||||
.
|
||||
.P
|
||||
.B File follow modes
|
||||
.P
|
||||
The file map monitoring daemon can monitor files in two distinct ways:
|
||||
follow-inode mode, and follow-path mode.
|
||||
|
||||
The mode affects the behaviour of the daemon when a file under
|
||||
monitoring is renamed or unlinked, and the conditions which cause the
|
||||
daemon to terminate.
|
||||
|
||||
If follow-inode mode is used, the daemon will hold the file open, and
|
||||
continue to update regions from the same file descriptor. This means
|
||||
that the mapping will follow rename, move (within the same file
|
||||
system), and unlink operations. This mode is useful if the file is
|
||||
expected to be moved, renamed, or unlinked while it is being
|
||||
monitored.
|
||||
|
||||
In follow-inode mode, the daemon will exit once it detects that the
|
||||
file has been unlinked and it is the last holder of a reference to it.
|
||||
|
||||
If follow-path is used, the daemon will re-open the provided path on
|
||||
each monitoring iteration. This means that the group will be updated
|
||||
to reflect a new file being moved to the same path as the original
|
||||
file. This mode is useful for files that are expected to be updated
|
||||
via unlink and rename.
|
||||
|
||||
In follow-path mode, the daemon will exit if the file is removed and
|
||||
not replaced within a brief tolerance interval (one second).
|
||||
|
||||
To stop the daemon, delete the group containing the mapped regions:
|
||||
the daemon will automatically shut down.
|
||||
|
||||
The daemon can also be safely killed at any time and the group kept:
|
||||
if the file is still being allocated the mapping will become
|
||||
progressively out-of-date as extents are added and removed (in this
|
||||
case the daemon can be re-started or the group updated manually with
|
||||
the \fBupdate_filemap\fP command).
|
||||
|
||||
See the \fBcreate\fP command and \fB\-\-filemap\fP, \fB\-\-follow\fP,
|
||||
and \fB\-\-nomonitor\fP options for further information.
|
||||
.
|
||||
.P
|
||||
.B Limitations
|
||||
.P
|
||||
The daemon attempts to maintain good synchronisation between the file
|
||||
extents and the regions contained in the group, however, since it can
|
||||
only react to new allocations once they have been written, there are
|
||||
inevitably some IO events that cannot be counted when a file is
|
||||
growing, particularly if the file is being extended by a single thread
|
||||
writing beyond end-of-file (for example, the \fBdd\fP program).
|
||||
|
||||
There is a further loss of events in that there is currently no way
|
||||
to atomically resize a \fBdmstats\fP region and preserve its current
|
||||
counter values. This affects files when they grow by extending the
|
||||
final extent, rather than allocating a new extent: any events that
|
||||
had accumulated in the region between any prior operation and the
|
||||
resize are lost.
|
||||
|
||||
File mapping is currently most effective in cases where the majority
|
||||
of IO does not trigger extent allocation. Future updates may address
|
||||
these limitations when kernel support is available.
|
||||
.
|
||||
.SH REPORT FIELDS
|
||||
.
|
||||
The dmstats report provides several types of field that may be added to
|
@ -3,4 +3,3 @@
|
||||
Change LV permission to read-only:
|
||||
.sp
|
||||
.B lvchange \-pr vg00/lvol1
|
||||
|
1272
man/lvchange.8_pregen
Normal file
1272
man/lvchange.8_pregen
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,32 +0,0 @@
|
||||
lvconvert changes the LV type and includes utilities for LV data
|
||||
maintenance. The LV type controls data layout and redundancy.
|
||||
The LV type is also called the segment type or segtype.
|
||||
|
||||
To display the current LV type, run the command:
|
||||
|
||||
.B lvs \-o name,segtype
|
||||
.I LV
|
||||
|
||||
The
|
||||
.B linear
|
||||
type is equivalent to the
|
||||
.B striped
|
||||
type when one stripe exists.
|
||||
In that case, the types can sometimes be used interchangably.
|
||||
|
||||
In most cases, the
|
||||
.B mirror
|
||||
type is deprecated and the
|
||||
.B raid1
|
||||
type should be used. They are both implementations of mirroring.
|
||||
|
||||
In some cases, an LV is a single device mapper (dm) layer above physical
|
||||
devices. In other cases, hidden LVs (dm devices) are layered between the
|
||||
visible LV and physical devices. LVs in the middle layers are called sub LVs.
|
||||
A command run on a visible LV sometimes operates on a sub LV rather than
|
||||
the specified LV. In other cases, a sub LV must be specified directly on
|
||||
the command line.
|
||||
|
||||
Sub LVs can be displayed with the command
|
||||
.B lvs -a
|
||||
|
65
man/lvconvert.8_des
Normal file
65
man/lvconvert.8_des
Normal file
@ -0,0 +1,65 @@
|
||||
lvconvert changes the LV type and includes utilities for LV data
|
||||
maintenance. The LV type controls data layout and redundancy.
|
||||
The LV type is also called the segment type or segtype.
|
||||
|
||||
To display the current LV type, run the command:
|
||||
|
||||
.B lvs \-o name,segtype
|
||||
.I LV
|
||||
|
||||
The
|
||||
.B linear
|
||||
type is equivalent to the
|
||||
.B striped
|
||||
type when one stripe exists.
|
||||
In that case, the types can sometimes be used interchangably.
|
||||
|
||||
In most cases, the
|
||||
.B mirror
|
||||
type is deprecated and the
|
||||
.B raid1
|
||||
type should be used. They are both implementations of mirroring.
|
||||
|
||||
In some cases, an LV is a single device mapper (dm) layer above physical
|
||||
devices. In other cases, hidden LVs (dm devices) are layered between the
|
||||
visible LV and physical devices. LVs in the middle layers are called sub LVs.
|
||||
A command run on a visible LV sometimes operates on a sub LV rather than
|
||||
the specified LV. In other cases, a sub LV must be specified directly on
|
||||
the command line.
|
||||
|
||||
Striped raid types are
|
||||
.B raid0/raid0_meta
|
||||
,
|
||||
.B raid5
|
||||
(an alias for raid5_ls),
|
||||
.B raid6
|
||||
(an alias for raid6_zr) and
|
||||
.B raid10
|
||||
(an alias for raid10_near).
|
||||
|
||||
As opposed to mirroring, raid5 and raid6 stripe data and calculate parity
|
||||
blocks. The parity blocks can be used for data block recovery in case devices
|
||||
fail. A maximum number of one device in a raid5 LV may fail and two in case
|
||||
of raid6. Striped raid types typically rotate the parity blocks for performance
|
||||
reasons thus avoiding contention on a single device. Layouts of raid5 rotating
|
||||
parity blocks can be one of left-asymmetric (raid5_la), left-symmetric (raid5_ls
|
||||
with alias raid5), right-asymmetric (raid5_ra), right-symmetric (raid5_rs) and raid5_n,
|
||||
which doesn't rotate parity blocks. Any \"_n\" layouts allow for conversion between
|
||||
raid levels (raid5_n -> raid6 or raid5_n -> striped/raid0/raid0_meta).
|
||||
raid6 layouts are zero-restart (raid6_zr with alias raid6), next-restart (raid6_nr),
|
||||
next-continue (raid6_nc). Additionally, special raid6 layouts for raid level conversions
|
||||
between raid5 and raid6 are raid6_ls_6, raid6_rs_6, raid6_la_6 and raid6_ra_6. Those
|
||||
correspond to their raid5 counterparts (e.g. raid5_rs can be directly converted to raid6_rs_6
|
||||
and vice-versa).
|
||||
raid10 (an alias for raid10_near) is currently limited to one data copy and even number of
|
||||
sub LVs. This is a mirror group layout thus a single sub LV may fail per mirror group
|
||||
without data loss.
|
||||
Striped raid types support converting the layout, their stripesize
|
||||
and their number of stripes.
|
||||
|
||||
The striped raid types combined with raid1 allow for conversion from linear -> striped/raid0/raid0_meta
|
||||
and vice-versa by e.g. linear <-> raid1 <-> raid5_n (then adding stripes) <-> striped/raid0/raid0_meta.
|
||||
|
||||
Sub LVs can be displayed with the command
|
||||
.B lvs -a
|
||||
|
@ -1,5 +1,4 @@
|
||||
.SH NOTES
|
||||
|
||||
This previous command syntax would perform two different operations:
|
||||
.br
|
||||
\fBlvconvert --thinpool\fP \fILV1\fP \fB--poolmetadata\fP \fILV2\fP
|
||||
@ -20,7 +19,6 @@ But, if LV1 was already a cache pool, the command would swap
|
||||
the current metadata LV with LV2 (for repair purposes.)
|
||||
|
||||
.SH EXAMPLES
|
||||
|
||||
Convert a linear LV to a two-way mirror LV.
|
||||
.br
|
||||
.B lvconvert \-\-type mirror \-\-mirrors 1 vg/lvol1
|
||||
@ -113,4 +111,3 @@ Detach and keep the cache pool from a cache LV.
|
||||
Detach and remove the cache pool from a cache LV.
|
||||
.br
|
||||
.B lvconvert \-\-uncache vg/lvol1
|
||||
|
2059
man/lvconvert.8_pregen
Normal file
2059
man/lvconvert.8_pregen
Normal file
File diff suppressed because it is too large
Load Diff
@ -25,15 +25,12 @@ Thin LVs are thinly provisioned from a thin pool, and are created with a
|
||||
virtual size rather than a physical size. A cache LV is the combination of
|
||||
a standard LV with a cache pool, used to cache active portions of the LV
|
||||
to improve performance.
|
||||
|
||||
.SS Usage notes
|
||||
|
||||
In the usage section below, \fB--size\fP \fINumber\fP can be replaced
|
||||
in each case with \fB--extents\fP \fINumberExtents\fP. Also see both
|
||||
descriptions the options section.
|
||||
In the usage section below, \fB--size\fP \fISize\fP can be replaced
|
||||
with \fB--extents\fP \fINumber\fP. See both descriptions
|
||||
the options section.
|
||||
|
||||
In the usage section below, \fB--name\fP is omitted from the required
|
||||
options, even though it is typically used. When the name is not
|
||||
specified, a new LV name is generated with the "lvol" prefix and a unique
|
||||
numeric suffix. Also see the description in the options section.
|
||||
|
@ -95,4 +95,3 @@ then combining the new origin LV with an existing cache pool.
|
||||
.RS
|
||||
.B \-L 100G \-n mylv vg00 /dev/slow1
|
||||
.RE
|
||||
|
2865
man/lvcreate.8_pregen
Normal file
2865
man/lvcreate.8_pregen
Normal file
File diff suppressed because it is too large
Load Diff
0
man/lvdisplay.8_end
Normal file
0
man/lvdisplay.8_end
Normal file
639
man/lvdisplay.8_pregen
Normal file
639
man/lvdisplay.8_pregen
Normal file
@ -0,0 +1,639 @@
|
||||
.TH LVDISPLAY 8 "LVM TOOLS 2.02.169(2)-git (2016-11-30)" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
.
|
||||
lvdisplay \- Display information about a logical volume
|
||||
.P
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvdisplay\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
[ \fIposition_args\fP ]
|
||||
.br
|
||||
.P
|
||||
|
||||
.SH DESCRIPTION
|
||||
lvdisplay shows the attributes of LVs, like size, read/write status,
|
||||
snapshot information, etc.
|
||||
|
||||
\fBlvs\fP(8) is a preferred alternative that shows the same information
|
||||
and more, using a more compact and configurable output format.
|
||||
|
||||
.P
|
||||
.SH USAGE
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvdisplay\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-a\fP|\fB--all\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-c\fP|\fB--colon\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-C\fP|\fB--columns\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-H\fP|\fB--history\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-m\fP|\fB--maps\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-o\fP|\fB--options\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-O\fP|\fB--sort\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-P\fP|\fB--partial\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-S\fP|\fB--select\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--aligned\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--binary\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--configreport\fP \fBlog\fP|\fBvg\fP|\fBlv\fP|\fBpv\fP|\fBpvseg\fP|\fBseg\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--foreign\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignorelockingfailure\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignoreskippedcluster\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--logonly\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--noheadings\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--nosuffix\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--readonly\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--segments\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--separator\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--shared\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unbuffered\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--units\fP \fBr\fP|\fBR\fP|\fBh\fP|\fBH\fP|\fBb\fP|\fBB\fP|\fBs\fP|\fBS\fP|\fBk\fP|\fBK\fP|\fBm\fP|\fBM\fP|\fBg\fP|\fBG\fP|\fBt\fP|\fBT\fP|\fBp\fP|\fBP\fP|\fBe\fP|\fBE\fP ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
.RS 4
|
||||
[ \fIVG\fP|\fILV\fP|\fITag\fP ... ]
|
||||
.RE
|
||||
|
||||
|
||||
Common options for lvm:
|
||||
.
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-d\fP|\fB--debug\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-h\fP|\fB--help\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-q\fP|\fB--quiet\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-t\fP|\fB--test\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-v\fP|\fB--verbose\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-y\fP|\fB--yes\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--commandprofile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--config\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--driverloaded\fP \fBy\fP|\fBn\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--longhelp\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--profile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--version\fP ]
|
||||
.ad b
|
||||
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
.br
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--aligned\fP
|
||||
.br
|
||||
Use with --separator to align the output columns
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-a\fP|\fB--all\fP
|
||||
.br
|
||||
Show information about internal LVs.
|
||||
These are components of normal LVs, such as mirrors,
|
||||
which are not independently accessible, e.g. not mountable.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--binary\fP
|
||||
.br
|
||||
Use binary values "0" or "1" instead of descriptive literal values
|
||||
for columns that have exactly two valid values to report (not counting
|
||||
the "unknown" value which denotes that the value could not be determined).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-c\fP|\fB--colon\fP
|
||||
.br
|
||||
Generate colon separated output for easier parsing in scripts or programs.
|
||||
Also see vgs(8) which provides considerably more control over the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-C\fP|\fB--columns\fP
|
||||
.br
|
||||
Display output in columns, the equivalent of vgs(8).
|
||||
Options listed are the same as options given in vgs(8).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
.br
|
||||
The command profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--config\fP \fIString\fP
|
||||
.br
|
||||
Config settings for the command. These override lvm.conf settings.
|
||||
The String arg uses the same format as lvm.conf,
|
||||
or may use section/field syntax.
|
||||
See \fBlvm.conf\fP(5) for more information about config.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--configreport\fP \fBlog\fP|\fBvg\fP|\fBlv\fP|\fBpv\fP|\fBpvseg\fP|\fBseg\fP
|
||||
.br
|
||||
See lvmreport(7).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-d\fP|\fB--debug\fP ...
|
||||
.br
|
||||
Set debug level. Repeat from 1 to 6 times to increase the detail of
|
||||
messages sent to the log file and/or syslog (if configured).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
If set to no, the command will not attempt to use device-mapper.
|
||||
For testing and debugging.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--foreign\fP
|
||||
.br
|
||||
Report/display foreign VGs that would otherwise be skipped.
|
||||
See lvmsystemid(7) for more information about foreign VGs.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-h\fP|\fB--help\fP
|
||||
.br
|
||||
Display help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-H\fP|\fB--history\fP
|
||||
.br
|
||||
Include historical LVs in the output.
|
||||
(This has no effect unless LVs were removed while
|
||||
lvm.conf metadata/record_lvs_history was enabled.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignorelockingfailure\fP
|
||||
.br
|
||||
Allows a command to continue with read-only metadata
|
||||
operations after locking failures.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignoreskippedcluster\fP
|
||||
.br
|
||||
Use to avoid exiting with an non-zero status code if the command is run
|
||||
without clustered locking and clustered VGs are skipped.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--logonly\fP
|
||||
.br
|
||||
Suppress command report and display only log report.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--longhelp\fP
|
||||
.br
|
||||
Display long help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-m\fP|\fB--maps\fP
|
||||
.br
|
||||
Display the mapping of logical extents to PVs and physical extents.
|
||||
To map physical extents to logical extents use:
|
||||
pvs --segments -o+lv_name,seg_start_pe,segtype
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--noheadings\fP
|
||||
.br
|
||||
Suppress the headings line that is normally the first line of output.
|
||||
Useful if grepping the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--nosuffix\fP
|
||||
.br
|
||||
Suppress the suffix on output sizes. Use with --units
|
||||
(except h and H) if processing the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-o\fP|\fB--options\fP \fIString\fP
|
||||
.br
|
||||
Comma-separated, ordered list of fields to display in columns.
|
||||
String arg syntax is: [+|-|#]Field1[,Field2 ...]
|
||||
The prefix \fB+\fP will append the specified fields to the default fields,
|
||||
\fB-\fP will remove the specified fields from the default fields, and
|
||||
\fB#\fP will compact specified fields (removing them when empty for all rows.)
|
||||
Use \fB-o help\fP to view the list of all available fields.
|
||||
The -o option can be repeated, providing several lists.
|
||||
These lists are evaluated from left to right.
|
||||
Use field name \fBlv_all\fP to view all LV fields,
|
||||
\fBvg_all\fP all VG fields,
|
||||
\fBpv_all\fP all PV fields,
|
||||
\fBpvseg_all\fP all PV segment fields,
|
||||
\fBseg_all\fP all LV segment fields, and
|
||||
\fBpvseg_all\fP all PV segment columns.
|
||||
See the lvm.conf report section for more config options.
|
||||
See lvmreport(7) for more information about reporting.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-P\fP|\fB--partial\fP
|
||||
.br
|
||||
When set, the tools will do their best to provide access to VGs
|
||||
that are only partially available (one or more PVs belonging
|
||||
to the VG are missing from the system). Metadata may not be
|
||||
changed with this option.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--profile\fP \fIString\fP
|
||||
.br
|
||||
An alias for --commandprofile or --metadataprofile, depending
|
||||
on the command.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP ...
|
||||
.br
|
||||
Suppress output and log messages. Overrides --debug and --verbose.
|
||||
Repeat once to also suppress any prompts with answer no.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--readonly\fP
|
||||
.br
|
||||
Run the command in a special read-only mode which will read on-disk
|
||||
metadata without needing to take any locks. This can be used to peek
|
||||
inside metadata used by a virtual machine image while the virtual
|
||||
machine is running.
|
||||
It can also be used to peek inside the metadata of clustered VGs
|
||||
when clustered locking is not configured or running. No attempt
|
||||
will be made to communicate with the device-mapper kernel driver, so
|
||||
this option is unable to report whether or not LVs are
|
||||
actually in use.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
|
||||
.br
|
||||
Overrides current output format for reports which is defined globally by
|
||||
the report/output_format setting in lvm.conf.
|
||||
\fBbasic\fP is the original format with columns and rows.
|
||||
If there is more than one report per command, each report is prefixed
|
||||
with the report name for identification. \fBjson\fP produces report
|
||||
output in JSON format. See \fBlvmreport\fP(7) for more information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--segments\fP
|
||||
.br
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-S\fP|\fB--select\fP \fIString\fP
|
||||
.br
|
||||
Select objects for processing and reporting based on specified criteria.
|
||||
The criteria syntax is described by \fB--select help\fP and \fBlvmreport\fP(7).
|
||||
For reporting commands, one row is displayed for each object matching the criteria.
|
||||
See \fB--options help\fP for selectable object fields.
|
||||
Rows can be displayed with an additional "selected" field (-o selected)
|
||||
showing 1 if the row matches the selection and 0 otherwise.
|
||||
For non-reporting commands which process LVM entities, the selection is
|
||||
used to choose items to process.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--separator\fP \fIString\fP
|
||||
.br
|
||||
String to use to separate each column. Useful if grepping the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--shared\fP
|
||||
.br
|
||||
Report/display shared VGs that would otherwise be skipped when
|
||||
lvmlockd is not being used on the host.
|
||||
See lvmlockd(8) for more information about shared VGs.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-O\fP|\fB--sort\fP \fIString\fP
|
||||
.br
|
||||
Comma-separated ordered list of columns to sort by. Replaces the default
|
||||
selection. Precede any column with \fB-\fP for a reverse sort on that column.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-t\fP|\fB--test\fP
|
||||
.br
|
||||
Run in test mode. Commands will not update metadata.
|
||||
This is implemented by disabling all metadata writing but nevertheless
|
||||
returning success to the calling function. This may lead to unusual
|
||||
error messages in multi-stage operations if a tool relies on reading
|
||||
back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unbuffered\fP
|
||||
.br
|
||||
Produce output immediately without sorting or aligning the columns properly.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--units\fP \fBr\fP|\fBR\fP|\fBh\fP|\fBH\fP|\fBb\fP|\fBB\fP|\fBs\fP|\fBS\fP|\fBk\fP|\fBK\fP|\fBm\fP|\fBM\fP|\fBg\fP|\fBG\fP|\fBt\fP|\fBT\fP|\fBp\fP|\fBP\fP|\fBe\fP|\fBE\fP
|
||||
.br
|
||||
All sizes are output in these units:
|
||||
human-(r)eadable with '<' rounding indicator,
|
||||
(h)uman-readable, (b)ytes, (s)ectors, (k)ilobytes, (m)egabytes,
|
||||
(g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.
|
||||
Capitalise to use multiples of 1000 (S.I.) instead of 1024.
|
||||
Custom units can be specified, e.g. --units 3M.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
of messages sent to stdout and stderr.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--version\fP
|
||||
.br
|
||||
Display version information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.br
|
||||
Do not prompt for confirmation interactively but always assume the
|
||||
answer yes. Use with extreme caution.
|
||||
(For automatic no, see -qq.)
|
||||
.ad b
|
||||
.SH VARIABLES
|
||||
.br
|
||||
|
||||
.HP
|
||||
\fIVG\fP
|
||||
.br
|
||||
Volume Group name. See \fBlvm\fP(8) for valid names.
|
||||
|
||||
.HP
|
||||
\fILV\fP
|
||||
.br
|
||||
Logical Volume name. See \fBlvm\fP(8) for valid names.
|
||||
An LV positional arg generally includes the VG name and LV name, e.g. VG/LV.
|
||||
|
||||
.HP
|
||||
\fITag\fP
|
||||
.br
|
||||
Tag name. See \fBlvm\fP(8) for information about tag names and using tags
|
||||
in place of a VG, LV or PV.
|
||||
|
||||
.HP
|
||||
\fIString\fP
|
||||
.br
|
||||
See the option description for information about the string content.
|
||||
|
||||
.HP
|
||||
\fISize\fP[UNIT]
|
||||
.br
|
||||
Size is an input number that accepts an optional unit.
|
||||
Input units are always treated as base two values, regardless of
|
||||
capitalization, e.g. 'k' and 'K' both refer to 1024.
|
||||
The default input unit is specified by letter, followed by |UNIT.
|
||||
UNIT represents other possible input units: \fBbBsSkKmMgGtTpPeE\fP.
|
||||
b|B is bytes, s|S is sectors of 512 bytes, k|K is kilobytes,
|
||||
m|M is megabytes, g|G is gigabytes, t|T is terabytes,
|
||||
p|P is petabytes, e|E is exabytes.
|
||||
(This should not be confused with the output control --units, where
|
||||
capital letters mean multiple of 1000.)
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.br
|
||||
See \fBlvm\fP(8) for information about environment variables used by lvm.
|
||||
For example, LVM_VG_NAME can generally be substituted for a required VG parameter.
|
||||
.SH SEE ALSO
|
||||
|
||||
.BR lvm (8)
|
||||
.BR lvm.conf (5)
|
||||
.BR lvmconfig (8)
|
||||
|
||||
.BR pvchange (8)
|
||||
.BR pvck (8)
|
||||
.BR pvcreate (8)
|
||||
.BR pvdisplay (8)
|
||||
.BR pvmove (8)
|
||||
.BR pvremove (8)
|
||||
.BR pvresize (8)
|
||||
.BR pvs (8)
|
||||
.BR pvscan (8)
|
||||
|
||||
.BR vgcfgbackup (8)
|
||||
.BR vgcfgrestore (8)
|
||||
.BR vgchange (8)
|
||||
.BR vgck (8)
|
||||
.BR vgcreate (8)
|
||||
.BR vgconvert (8)
|
||||
.BR vgdisplay (8)
|
||||
.BR vgexport (8)
|
||||
.BR vgextend (8)
|
||||
.BR vgimport (8)
|
||||
.BR vgimportclone (8)
|
||||
.BR vgmerge (8)
|
||||
.BR vgmknodes (8)
|
||||
.BR vgreduce (8)
|
||||
.BR vgremove (8)
|
||||
.BR vgrename (8)
|
||||
.BR vgs (8)
|
||||
.BR vgscan (8)
|
||||
.BR vgsplit (8)
|
||||
|
||||
.BR lvcreate (8)
|
||||
.BR lvchange (8)
|
||||
.BR lvconvert (8)
|
||||
.BR lvdisplay (8)
|
||||
.BR lvextend (8)
|
||||
.BR lvreduce (8)
|
||||
.BR lvremove (8)
|
||||
.BR lvrename (8)
|
||||
.BR lvresize (8)
|
||||
.BR lvs (8)
|
||||
.BR lvscan (8)
|
||||
|
||||
.BR lvm2-activation-generator (8)
|
||||
.BR blkdeactivate (8)
|
||||
.BR lvmdump (8)
|
||||
|
||||
.BR dmeventd (8)
|
||||
.BR lvmetad (8)
|
||||
.BR lvmpolld (8)
|
||||
.BR lvmlockd (8)
|
||||
.BR lvmlockctl (8)
|
||||
.BR clvmd (8)
|
||||
.BR cmirrord (8)
|
||||
.BR lvmdbusd (8)
|
||||
|
||||
.BR lvmsystemid (7)
|
||||
.BR lvmreport (7)
|
||||
.BR lvmraid (7)
|
||||
.BR lvmthin (7)
|
||||
.BR lvmcache (7)
|
||||
|
@ -1,5 +0,0 @@
|
||||
lvextend extends the size of an LV. This requires allocating logical
|
||||
extents from the VG's free physical extents. A copy\-on\-write snapshot LV
|
||||
can also be extended to provide more space to hold COW blocks. Use
|
||||
\fBlvconvert\fP(8) to change the number of data images in a RAID or
|
||||
mirrored LV.
|
12
man/lvextend.8_des
Normal file
12
man/lvextend.8_des
Normal file
@ -0,0 +1,12 @@
|
||||
lvextend extends the size of an LV. This requires allocating logical
|
||||
extents from the VG's free physical extents. If the extension adds a new
|
||||
LV segment, the new segment will use the existing segment type of the LV.
|
||||
|
||||
Extending a copy\-on\-write snapshot LV adds space for COW blocks.
|
||||
|
||||
Use \fBlvconvert\fP(8) to change the number of data images in a RAID or
|
||||
mirrored LV.
|
||||
|
||||
In the usage section below, \fB--size\fP \fISize\fP can be replaced
|
||||
with \fB--extents\fP \fINumber\fP. See both descriptions
|
||||
the options section.
|
@ -1,5 +1,4 @@
|
||||
.SH EXAMPLES
|
||||
|
||||
Extend the size of an LV by 54MiB, using a specific PV.
|
||||
.br
|
||||
.B lvextend \-L +54 vg01/lvol10 /dev/sdk3
|
||||
@ -13,4 +12,3 @@ space on PV /dev/sdk3. This is equivalent to specifying
|
||||
Extend an LV by 16MiB using specific physical extents.
|
||||
.br
|
||||
.B lvextend \-L+16m vg01/lvol01 /dev/sda:8\-9 /dev/sdb:8\-9
|
||||
|
781
man/lvextend.8_pregen
Normal file
781
man/lvextend.8_pregen
Normal file
@ -0,0 +1,781 @@
|
||||
.TH LVEXTEND 8 "LVM TOOLS 2.02.169(2)-git (2016-11-30)" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
.
|
||||
lvextend \- Add space to a logical volume
|
||||
.P
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvextend\fP \fIoption_args\fP \fIposition_args\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
[ \fIposition_args\fP ]
|
||||
.br
|
||||
.P
|
||||
|
||||
.P
|
||||
.ad l
|
||||
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--config\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-d\fP|\fB--debug\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-l\fP|\fB--extents\fP [\fB+\fP]\fINumber\fP[PERCENT]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-f\fP|\fB--force\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-h\fP|\fB--help\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--longhelp\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-m\fP|\fB--mirrors\fP \fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-n\fP|\fB--nofsck\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--nosync\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--noudevsync\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--poolmetadatasize\fP [\fB+\fP]\fISize\fP[m|UNIT]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--profile\fP \fIString\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-r\fP|\fB--resizefs\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-L\fP|\fB--size\fP [\fB+\fP]\fISize\fP[m|UNIT]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-i\fP|\fB--stripes\fP \fINumber\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-t\fP|\fB--test\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--type\fP \fBlinear\fP|\fBstriped\fP|\fBsnapshot\fP|\fBmirror\fP|\fBraid\fP|\fBthin\fP|\fBcache\fP|\fBthin-pool\fP|\fBcache-pool\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--usepolicies\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB--version\fP
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.ad b
|
||||
|
||||
.P
|
||||
|
||||
.SH DESCRIPTION
|
||||
lvextend extends the size of an LV. This requires allocating logical
|
||||
extents from the VG's free physical extents. If the extension adds a new
|
||||
LV segment, the new segment will use the existing segment type of the LV.
|
||||
|
||||
Extending a copy\-on\-write snapshot LV adds space for COW blocks.
|
||||
|
||||
Use \fBlvconvert\fP(8) to change the number of data images in a RAID or
|
||||
mirrored LV.
|
||||
|
||||
In the usage section below, \fB--size\fP \fISize\fP can be replaced
|
||||
with \fB--extents\fP \fINumber\fP. See both descriptions
|
||||
the options section.
|
||||
|
||||
.P
|
||||
.SH USAGE
|
||||
.br
|
||||
.P
|
||||
.
|
||||
Extend an LV by a specified size.
|
||||
.br
|
||||
.P
|
||||
\fBlvextend\fP \fB-L\fP|\fB--size\fP [\fB+\fP]\fISize\fP[m|UNIT] \fILV\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-l\fP|\fB--extents\fP [\fB+\fP]\fINumber\fP[PERCENT] ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-r\fP|\fB--resizefs\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-i\fP|\fB--stripes\fP \fINumber\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT] ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--poolmetadatasize\fP [\fB+\fP]\fISize\fP[m|UNIT] ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
.RS 4
|
||||
[ \fIPV\fP ... ]
|
||||
.RE
|
||||
|
||||
--
|
||||
|
||||
.br
|
||||
|
||||
Extend an LV by specified PV extents.
|
||||
.br
|
||||
.P
|
||||
\fBlvextend\fP \fILV\fP \fIPV\fP ...
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-r\fP|\fB--resizefs\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-i\fP|\fB--stripes\fP \fINumber\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT] ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
|
||||
--
|
||||
|
||||
.br
|
||||
|
||||
Extend a pool metadata SubLV by a specified size.
|
||||
.br
|
||||
.P
|
||||
\fBlvextend\fP \fB--poolmetadatasize\fP [\fB+\fP]\fISize\fP[m|UNIT] \fILV\fP\fI_thinpool\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-i\fP|\fB--stripes\fP \fINumber\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT] ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
.RS 4
|
||||
[ \fIPV\fP ... ]
|
||||
.RE
|
||||
|
||||
--
|
||||
|
||||
.br
|
||||
|
||||
Extend an LV according to a predefined policy.
|
||||
.br
|
||||
.P
|
||||
\fBlvextend\fP \fB--usepolicies\fP \fILV\fP\fI_snapshot_thinpool\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-r\fP|\fB--resizefs\fP ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
.RS 4
|
||||
[ \fIPV\fP ... ]
|
||||
.RE
|
||||
|
||||
--
|
||||
|
||||
.br
|
||||
|
||||
Common options for command:
|
||||
.
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-f\fP|\fB--force\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-m\fP|\fB--mirrors\fP \fINumber\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-n\fP|\fB--nofsck\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--nosync\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--noudevsync\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--type\fP \fBlinear\fP|\fBstriped\fP|\fBsnapshot\fP|\fBmirror\fP|\fBraid\fP|\fBthin\fP|\fBcache\fP|\fBthin-pool\fP|\fBcache-pool\fP ]
|
||||
.ad b
|
||||
|
||||
.RE
|
||||
.br
|
||||
|
||||
Common options for lvm:
|
||||
.
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-d\fP|\fB--debug\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-h\fP|\fB--help\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-q\fP|\fB--quiet\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-t\fP|\fB--test\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-v\fP|\fB--verbose\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-y\fP|\fB--yes\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--commandprofile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--config\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--driverloaded\fP \fBy\fP|\fBn\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--longhelp\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--profile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--version\fP ]
|
||||
.ad b
|
||||
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
.br
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
|
||||
.br
|
||||
Determines the allocation policy when a command needs to allocate
|
||||
Physical Extents (PEs) from the VG. Each VG and LV has an allocation policy
|
||||
which can be changed with vgchange/lvchange, or overriden on the
|
||||
command line.
|
||||
\fBnormal\fP applies common sense rules such as not placing parallel stripes
|
||||
on the same PV.
|
||||
\fBinherit\fP applies the VG policy to an LV.
|
||||
\fBcontiguous\fP requires new PEs be placed adjacent to existing PEs.
|
||||
\fBcling\fP places new PEs on the same PV as existing PEs in the same
|
||||
stripe of the LV.
|
||||
If there are sufficient PEs for an allocation, but normal does not
|
||||
use them, \fBanywhere\fP will use them even if it reduces performance,
|
||||
e.g. by placing two stripes on the same PV.
|
||||
Optional positional PV args on the command line can also be used to limit
|
||||
which PVs the command will use for allocation.
|
||||
See \fBlvm\fP(8) for more information about allocation.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
Specifies if metadata should be backed up automatically after a change.
|
||||
Enabling this is strongly advised! See vgcfgbackup(8) for more information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
.br
|
||||
The command profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--config\fP \fIString\fP
|
||||
.br
|
||||
Config settings for the command. These override lvm.conf settings.
|
||||
The String arg uses the same format as lvm.conf,
|
||||
or may use section/field syntax.
|
||||
See \fBlvm.conf\fP(5) for more information about config.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-d\fP|\fB--debug\fP ...
|
||||
.br
|
||||
Set debug level. Repeat from 1 to 6 times to increase the detail of
|
||||
messages sent to the log file and/or syslog (if configured).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
If set to no, the command will not attempt to use device-mapper.
|
||||
For testing and debugging.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-l\fP|\fB--extents\fP [\fB+\fP]\fINumber\fP[PERCENT]
|
||||
.br
|
||||
Specifies the new size of the LV in logical extents.
|
||||
The --size and --extents options are alternate methods of specifying size.
|
||||
The total number of physical extents used will be
|
||||
greater when redundant data is needed for RAID levels.
|
||||
An alternate syntax allows the size to be determined indirectly
|
||||
as a percentage of the size of a related VG, LV, or set of PVs. The
|
||||
suffix \fB%VG\fP denotes the total size of the VG, the suffix \fB%FREE\fP
|
||||
the remaining free space in the VG, and the suffix \fB%PVS\fP the free
|
||||
space in the specified PVs. For a snapshot, the size
|
||||
can be expressed as a percentage of the total size of the origin LV
|
||||
with the suffix \fB%ORIGIN\fP (\fB100%ORIGIN\fP provides space for
|
||||
the whole origin).
|
||||
When expressed as a percentage, the size defines an upper limit for the
|
||||
number of logical extents in the new LV. The precise number of logical
|
||||
extents in the new LV is not determined until the command has completed.
|
||||
When the plus \fB+\fP or minus \fB-\fP prefix is used,
|
||||
the value is not an absolute size, but is relative and added or subtracted
|
||||
from the current size.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-f\fP|\fB--force\fP ...
|
||||
.br
|
||||
Override various checks, confirmations and protections.
|
||||
Use with extreme caution.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-h\fP|\fB--help\fP
|
||||
.br
|
||||
Display help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--longhelp\fP
|
||||
.br
|
||||
Display long help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-m\fP|\fB--mirrors\fP \fINumber\fP
|
||||
.br
|
||||
Not used.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-n\fP|\fB--nofsck\fP
|
||||
.br
|
||||
Do not perform fsck before resizing filesystem when filesystem
|
||||
requires it. You may need to use --force to proceed with
|
||||
this option.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--nosync\fP
|
||||
.br
|
||||
Causes the creation of mirror, raid1, raid4, raid5 and raid10 to skip the
|
||||
initial synchronization. In case of mirror, raid1 and raid10, any data
|
||||
written afterwards will be mirrored, but the original contents will not be
|
||||
copied. In case of raid4 and raid5, no parity blocks will be written,
|
||||
though any data written afterwards will cause parity blocks to be stored.
|
||||
This is useful for skipping a potentially long and resource intensive initial
|
||||
sync of an empty mirror/raid1/raid4/raid5 and raid10 LV.
|
||||
This option is not valid for raid6, because raid6 relies on proper parity
|
||||
(P and Q Syndromes) being created during initial synchronization in order
|
||||
to reconstruct proper user date in case of device failures.
|
||||
raid0 and raid0_meta do not provide any data copies or parity support
|
||||
and thus do not support initial synchronization.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--noudevsync\fP
|
||||
.br
|
||||
Disables udev synchronisation. The process will not wait for notification
|
||||
from udev. It will continue irrespective of any possible udev processing
|
||||
in the background. Only use this if udev is not running or has rules that
|
||||
ignore the devices LVM creates.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--poolmetadatasize\fP [\fB+\fP]\fISize\fP[m|UNIT]
|
||||
.br
|
||||
Specifies the new size of the pool metadata LV.
|
||||
The plus prefix \fB+\fP can be used, in which case
|
||||
the value is added to the current size.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--profile\fP \fIString\fP
|
||||
.br
|
||||
An alias for --commandprofile or --metadataprofile, depending
|
||||
on the command.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP ...
|
||||
.br
|
||||
Suppress output and log messages. Overrides --debug and --verbose.
|
||||
Repeat once to also suppress any prompts with answer no.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
|
||||
.br
|
||||
Overrides current output format for reports which is defined globally by
|
||||
the report/output_format setting in lvm.conf.
|
||||
\fBbasic\fP is the original format with columns and rows.
|
||||
If there is more than one report per command, each report is prefixed
|
||||
with the report name for identification. \fBjson\fP produces report
|
||||
output in JSON format. See \fBlvmreport\fP(7) for more information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-r\fP|\fB--resizefs\fP
|
||||
.br
|
||||
Resize underlying filesystem together with the LV using fsadm(8).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-L\fP|\fB--size\fP [\fB+\fP]\fISize\fP[m|UNIT]
|
||||
.br
|
||||
Specifies the new size of the LV.
|
||||
The --size and --extents options are alternate methods of specifying size.
|
||||
The total number of physical extents used will be
|
||||
greater when redundant data is needed for RAID levels.
|
||||
When the plus \fB+\fP or minus \fB-\fP prefix is used,
|
||||
the value is not an absolute size, but is relative and added or subtracted
|
||||
from the current size.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-i\fP|\fB--stripes\fP \fINumber\fP
|
||||
.br
|
||||
Specifies the number of stripes in a striped LV. This is the number of
|
||||
PVs (devices) that a striped LV is spread across. Data that
|
||||
appears sequential in the LV is spread across multiple devices in units of
|
||||
the stripe size (see --stripesize). This does not change existing
|
||||
allocated space, but only applies to space being allocated by the command.
|
||||
When creating a RAID 4/5/6 LV, this number does not include the extra
|
||||
devices that are required for parity. The largest number depends on
|
||||
the RAID type (raid0: 64, raid10: 32, raid4/5: 63, raid6: 62), and
|
||||
when unspecified, the default depends on the RAID type
|
||||
(raid0: 2, raid10: 4, raid4/5: 3, raid6: 5.)
|
||||
To stripe a new raid LV across all PVs by default,
|
||||
see lvm.conf allocation/raid_stripe_all_devices.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT]
|
||||
.br
|
||||
The amount of data that is written to one device before
|
||||
moving to the next in a striped LV.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-t\fP|\fB--test\fP
|
||||
.br
|
||||
Run in test mode. Commands will not update metadata.
|
||||
This is implemented by disabling all metadata writing but nevertheless
|
||||
returning success to the calling function. This may lead to unusual
|
||||
error messages in multi-stage operations if a tool relies on reading
|
||||
back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--type\fP \fBlinear\fP|\fBstriped\fP|\fBsnapshot\fP|\fBmirror\fP|\fBraid\fP|\fBthin\fP|\fBcache\fP|\fBthin-pool\fP|\fBcache-pool\fP
|
||||
.br
|
||||
The LV type, also known as "segment type" or "segtype".
|
||||
See usage descriptions for the specific ways to use these types.
|
||||
For more information about redundancy and performance (\fBraid\fP<N>, \fBmirror\fP, \fBstriped\fP, \fBlinear\fP) see \fBlvmraid\fP(7).
|
||||
For thin provisioning (\fBthin\fP, \fBthin-pool\fP) see \fBlvmthin\fP(7).
|
||||
For performance caching (\fBcache\fP, \fBcache-pool\fP) see \fBlvmcache\fP(7).
|
||||
For copy-on-write snapshots (\fBsnapshot\fP) see usage definitions.
|
||||
Several commands omit an explicit type option because the type
|
||||
is inferred from other options or shortcuts
|
||||
(e.g. --stripes, --mirrors, --snapshot, --virtualsize, --thin, --cache).
|
||||
Use inferred types with care because it can lead to unexpected results.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--usepolicies\fP
|
||||
.br
|
||||
Perform an operation according to the policy configured in lvm.conf
|
||||
or a profile.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
of messages sent to stdout and stderr.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--version\fP
|
||||
.br
|
||||
Display version information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.br
|
||||
Do not prompt for confirmation interactively but always assume the
|
||||
answer yes. Use with extreme caution.
|
||||
(For automatic no, see -qq.)
|
||||
.ad b
|
||||
.SH VARIABLES
|
||||
.br
|
||||
|
||||
.HP
|
||||
\fILV\fP
|
||||
.br
|
||||
Logical Volume name. See \fBlvm\fP(8) for valid names.
|
||||
An LV positional arg generally includes the VG name and LV name, e.g. VG/LV.
|
||||
LV followed by _<type> indicates that an LV of the
|
||||
given type is required. (raid represents raid<N> type)
|
||||
|
||||
.HP
|
||||
\fIPV\fP
|
||||
.br
|
||||
Physical Volume name, a device path under /dev.
|
||||
For commands managing physical extents, a PV positional arg
|
||||
generally accepts a suffix indicating a range (or multiple ranges)
|
||||
of physical extents (PEs). When the first PE is omitted, it defaults
|
||||
to the start of the device, and when the last PE is omitted it defaults to end.
|
||||
Start and end range (inclusive): \fIPV\fP[\fB:\fP\fIPE\fP\fB-\fP\fIPE\fP]...
|
||||
Start and length range (counting from 0): \fIPV\fP[\fB:\fP\fIPE\fP\fB+\fP\fIPE\fP]...
|
||||
|
||||
.HP
|
||||
\fIString\fP
|
||||
.br
|
||||
See the option description for information about the string content.
|
||||
|
||||
.HP
|
||||
\fISize\fP[UNIT]
|
||||
.br
|
||||
Size is an input number that accepts an optional unit.
|
||||
Input units are always treated as base two values, regardless of
|
||||
capitalization, e.g. 'k' and 'K' both refer to 1024.
|
||||
The default input unit is specified by letter, followed by |UNIT.
|
||||
UNIT represents other possible input units: \fBbBsSkKmMgGtTpPeE\fP.
|
||||
b|B is bytes, s|S is sectors of 512 bytes, k|K is kilobytes,
|
||||
m|M is megabytes, g|G is gigabytes, t|T is terabytes,
|
||||
p|P is petabytes, e|E is exabytes.
|
||||
(This should not be confused with the output control --units, where
|
||||
capital letters mean multiple of 1000.)
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.br
|
||||
See \fBlvm\fP(8) for information about environment variables used by lvm.
|
||||
For example, LVM_VG_NAME can generally be substituted for a required VG parameter.
|
||||
.SH EXAMPLES
|
||||
|
||||
Extend the size of an LV by 54MiB, using a specific PV.
|
||||
.br
|
||||
.B lvextend \-L +54 vg01/lvol10 /dev/sdk3
|
||||
|
||||
Extend the size of an LV by the amount of free
|
||||
space on PV /dev/sdk3. This is equivalent to specifying
|
||||
"\-l +100%PVS" on the command line.
|
||||
.br
|
||||
.B lvextend vg01/lvol01 /dev/sdk3
|
||||
|
||||
Extend an LV by 16MiB using specific physical extents.
|
||||
.br
|
||||
.B lvextend \-L+16m vg01/lvol01 /dev/sda:8\-9 /dev/sdb:8\-9
|
||||
|
||||
.SH SEE ALSO
|
||||
|
||||
.BR lvm (8)
|
||||
.BR lvm.conf (5)
|
||||
.BR lvmconfig (8)
|
||||
|
||||
.BR pvchange (8)
|
||||
.BR pvck (8)
|
||||
.BR pvcreate (8)
|
||||
.BR pvdisplay (8)
|
||||
.BR pvmove (8)
|
||||
.BR pvremove (8)
|
||||
.BR pvresize (8)
|
||||
.BR pvs (8)
|
||||
.BR pvscan (8)
|
||||
|
||||
.BR vgcfgbackup (8)
|
||||
.BR vgcfgrestore (8)
|
||||
.BR vgchange (8)
|
||||
.BR vgck (8)
|
||||
.BR vgcreate (8)
|
||||
.BR vgconvert (8)
|
||||
.BR vgdisplay (8)
|
||||
.BR vgexport (8)
|
||||
.BR vgextend (8)
|
||||
.BR vgimport (8)
|
||||
.BR vgimportclone (8)
|
||||
.BR vgmerge (8)
|
||||
.BR vgmknodes (8)
|
||||
.BR vgreduce (8)
|
||||
.BR vgremove (8)
|
||||
.BR vgrename (8)
|
||||
.BR vgs (8)
|
||||
.BR vgscan (8)
|
||||
.BR vgsplit (8)
|
||||
|
||||
.BR lvcreate (8)
|
||||
.BR lvchange (8)
|
||||
.BR lvconvert (8)
|
||||
.BR lvdisplay (8)
|
||||
.BR lvextend (8)
|
||||
.BR lvreduce (8)
|
||||
.BR lvremove (8)
|
||||
.BR lvrename (8)
|
||||
.BR lvresize (8)
|
||||
.BR lvs (8)
|
||||
.BR lvscan (8)
|
||||
|
||||
.BR lvm2-activation-generator (8)
|
||||
.BR blkdeactivate (8)
|
||||
.BR lvmdump (8)
|
||||
|
||||
.BR dmeventd (8)
|
||||
.BR lvmetad (8)
|
||||
.BR lvmpolld (8)
|
||||
.BR lvmlockd (8)
|
||||
.BR lvmlockctl (8)
|
||||
.BR clvmd (8)
|
||||
.BR cmirrord (8)
|
||||
.BR lvmdbusd (8)
|
||||
|
||||
.BR lvmsystemid (7)
|
||||
.BR lvmreport (7)
|
||||
.BR lvmraid (7)
|
||||
.BR lvmthin (7)
|
||||
.BR lvmcache (7)
|
||||
|
0
man/lvm-config.8_end
Normal file
0
man/lvm-config.8_end
Normal file
522
man/lvm-config.8_pregen
Normal file
522
man/lvm-config.8_pregen
Normal file
@ -0,0 +1,522 @@
|
||||
.TH LVM CONFIG 8 "LVM TOOLS 2.02.169(2)-git (2016-11-30)" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
.
|
||||
lvm config \- Display and manipulate configuration information
|
||||
.P
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvm config\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
[ \fIposition_args\fP ]
|
||||
.br
|
||||
.P
|
||||
|
||||
.SH DESCRIPTION
|
||||
This command is the same as \fBlvmconfig\fP(8).
|
||||
|
||||
lvm config produces formatted output from the LVM configuration tree. The
|
||||
sources of the configuration data include \fBlvm.conf\fP(5) and command
|
||||
line settings from \-\-config.
|
||||
|
||||
.P
|
||||
.SH USAGE
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvm config\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-f\fP|\fB--file\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-l\fP|\fB--list\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--atversion\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--typeconfig\fP \fBcurrent\fP|\fBdefault\fP|\fBdiff\fP|\fBfull\fP|\fBlist\fP|\fBmissing\fP|\fBnew\fP|\fBprofilable\fP|\fBprofilable-command\fP|\fBprofilable-metadata\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignoreadvanced\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignoreunsupported\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignorelocal\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--mergedconfig\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--metadataprofile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--sinceversion\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--showdeprecated\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--showunsupported\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--validate\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--withsummary\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--withcomments\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--withspaces\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unconfigured\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--withversions\fP ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
.RS 4
|
||||
[ \fIString\fP ... ]
|
||||
.RE
|
||||
|
||||
|
||||
Common options for lvm:
|
||||
.
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-d\fP|\fB--debug\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-h\fP|\fB--help\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-q\fP|\fB--quiet\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-t\fP|\fB--test\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-v\fP|\fB--verbose\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-y\fP|\fB--yes\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--commandprofile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--config\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--driverloaded\fP \fBy\fP|\fBn\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--longhelp\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--profile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--version\fP ]
|
||||
.ad b
|
||||
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
.br
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--atversion\fP \fIString\fP
|
||||
.br
|
||||
Specify an LVM version in x.y.z format where x is the major version,
|
||||
the y is the minor version and z is the patchlevel (e.g. 2.2.106).
|
||||
When configuration is displayed, the configuration settings recognized
|
||||
at this LVM version will be considered only. This can be used
|
||||
to display a configuration that a certain LVM version understands and
|
||||
which does not contain any newer settings for which LVM would
|
||||
issue a warning message when checking the configuration.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
.br
|
||||
The command profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--config\fP \fIString\fP
|
||||
.br
|
||||
Config settings for the command. These override lvm.conf settings.
|
||||
The String arg uses the same format as lvm.conf,
|
||||
or may use section/field syntax.
|
||||
See \fBlvm.conf\fP(5) for more information about config.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-d\fP|\fB--debug\fP ...
|
||||
.br
|
||||
Set debug level. Repeat from 1 to 6 times to increase the detail of
|
||||
messages sent to the log file and/or syslog (if configured).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
If set to no, the command will not attempt to use device-mapper.
|
||||
For testing and debugging.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-f\fP|\fB--file\fP \fIString\fP
|
||||
.br
|
||||
Write output to the named file.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-h\fP|\fB--help\fP
|
||||
.br
|
||||
Display help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignoreadvanced\fP
|
||||
.br
|
||||
Exclude advanced configuration settings from the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignorelocal\fP
|
||||
.br
|
||||
Ignore local section.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignoreunsupported\fP
|
||||
.br
|
||||
Exclude unsupported configuration settings from the output. These settings are
|
||||
either used for debugging and development purposes only or their support is not
|
||||
yet complete and they are not meant to be used in production. The \fBcurrent\fP
|
||||
and \fBdiff\fP types include unsupported settings in their output by default,
|
||||
all the other types ignore unsupported settings.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-l\fP|\fB--list\fP
|
||||
.br
|
||||
List config settings with summarizing comment. This is the same as using
|
||||
options --typeconfig list --withsummary.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--longhelp\fP
|
||||
.br
|
||||
Display long help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--mergedconfig\fP
|
||||
.br
|
||||
When the command is run with --config
|
||||
and/or --commandprofile (or using LVM_COMMAND_PROFILE
|
||||
environment variable), --profile, or --metadataprofile,
|
||||
merge all the contents of the "config cascade" before displaying it.
|
||||
Without merging, only the configuration at the front of the
|
||||
cascade is displayed.
|
||||
See \fBlvm.conf\fP(5) for more information about config.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--metadataprofile\fP \fIString\fP
|
||||
.br
|
||||
The metadata profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--profile\fP \fIString\fP
|
||||
.br
|
||||
An alias for --commandprofile or --metadataprofile, depending
|
||||
on the command.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP ...
|
||||
.br
|
||||
Suppress output and log messages. Overrides --debug and --verbose.
|
||||
Repeat once to also suppress any prompts with answer no.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--showdeprecated\fP
|
||||
.br
|
||||
Include deprecated configuration settings in the output. These settings
|
||||
are deprecated after a certain version. If a concrete version is specified
|
||||
with --atversion, deprecated settings are automatically included
|
||||
if the specified version is lower than the version in which the settings were
|
||||
deprecated. The current and diff types include deprecated settings
|
||||
in their output by default, all the other types ignore deprecated settings.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--showunsupported\fP
|
||||
.br
|
||||
Include unsupported configuration settings in the output. These settings
|
||||
are either used for debugging or development purposes only, or their support
|
||||
is not yet complete and they are not meant to be used in production. The
|
||||
current and diff types include unsupported settings in their
|
||||
output by default, all the other types ignore unsupported settings.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--sinceversion\fP \fIString\fP
|
||||
.br
|
||||
Specify an LVM version in x.y.z format where x is the major version,
|
||||
the y is the minor version and z is the patchlevel (e.g. 2.2.106).
|
||||
This option is currently applicable only with --typeconfig new
|
||||
to display all configuration settings introduced since given version.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-t\fP|\fB--test\fP
|
||||
.br
|
||||
Run in test mode. Commands will not update metadata.
|
||||
This is implemented by disabling all metadata writing but nevertheless
|
||||
returning success to the calling function. This may lead to unusual
|
||||
error messages in multi-stage operations if a tool relies on reading
|
||||
back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--typeconfig\fP \fBcurrent\fP|\fBdefault\fP|\fBdiff\fP|\fBfull\fP|\fBlist\fP|\fBmissing\fP|\fBnew\fP|\fBprofilable\fP|\fBprofilable-command\fP|\fBprofilable-metadata\fP
|
||||
.br
|
||||
See lvmreport(7).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unconfigured\fP
|
||||
.br
|
||||
Internal option used for generating config file during build.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--validate\fP
|
||||
.br
|
||||
Validate current configuration used and exit with appropriate
|
||||
return code. The validation is done only for the configuration
|
||||
at the front of the "config cascade". To validate the whole
|
||||
merged configuration tree, also use --mergedconfig.
|
||||
The validation is done even if lvm.conf config/checks is disabled.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
of messages sent to stdout and stderr.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--version\fP
|
||||
.br
|
||||
Display version information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--withcomments\fP
|
||||
.br
|
||||
Display a full comment for each configuration node. For deprecated
|
||||
settings, also display comments about deprecation.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--withspaces\fP
|
||||
.br
|
||||
Where appropriate, add more spaces in output for better readability.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--withsummary\fP
|
||||
.br
|
||||
Display a one line comment for each configuration node.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--withversions\fP
|
||||
.br
|
||||
Also display a comment containing the version of introduction for
|
||||
each configuration node. If the setting is deprecated, also display
|
||||
the version since which it is deprecated.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.br
|
||||
Do not prompt for confirmation interactively but always assume the
|
||||
answer yes. Use with extreme caution.
|
||||
(For automatic no, see -qq.)
|
||||
.ad b
|
||||
.SH VARIABLES
|
||||
.br
|
||||
|
||||
.HP
|
||||
\fIString\fP
|
||||
.br
|
||||
See the option description for information about the string content.
|
||||
|
||||
.HP
|
||||
\fISize\fP[UNIT]
|
||||
.br
|
||||
Size is an input number that accepts an optional unit.
|
||||
Input units are always treated as base two values, regardless of
|
||||
capitalization, e.g. 'k' and 'K' both refer to 1024.
|
||||
The default input unit is specified by letter, followed by |UNIT.
|
||||
UNIT represents other possible input units: \fBbBsSkKmMgGtTpPeE\fP.
|
||||
b|B is bytes, s|S is sectors of 512 bytes, k|K is kilobytes,
|
||||
m|M is megabytes, g|G is gigabytes, t|T is terabytes,
|
||||
p|P is petabytes, e|E is exabytes.
|
||||
(This should not be confused with the output control --units, where
|
||||
capital letters mean multiple of 1000.)
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.br
|
||||
See \fBlvm\fP(8) for information about environment variables used by lvm.
|
||||
For example, LVM_VG_NAME can generally be substituted for a required VG parameter.
|
||||
.SH SEE ALSO
|
||||
|
||||
.BR lvm (8)
|
||||
.BR lvm.conf (5)
|
||||
.BR lvmconfig (8)
|
||||
|
||||
.BR pvchange (8)
|
||||
.BR pvck (8)
|
||||
.BR pvcreate (8)
|
||||
.BR pvdisplay (8)
|
||||
.BR pvmove (8)
|
||||
.BR pvremove (8)
|
||||
.BR pvresize (8)
|
||||
.BR pvs (8)
|
||||
.BR pvscan (8)
|
||||
|
||||
.BR vgcfgbackup (8)
|
||||
.BR vgcfgrestore (8)
|
||||
.BR vgchange (8)
|
||||
.BR vgck (8)
|
||||
.BR vgcreate (8)
|
||||
.BR vgconvert (8)
|
||||
.BR vgdisplay (8)
|
||||
.BR vgexport (8)
|
||||
.BR vgextend (8)
|
||||
.BR vgimport (8)
|
||||
.BR vgimportclone (8)
|
||||
.BR vgmerge (8)
|
||||
.BR vgmknodes (8)
|
||||
.BR vgreduce (8)
|
||||
.BR vgremove (8)
|
||||
.BR vgrename (8)
|
||||
.BR vgs (8)
|
||||
.BR vgscan (8)
|
||||
.BR vgsplit (8)
|
||||
|
||||
.BR lvcreate (8)
|
||||
.BR lvchange (8)
|
||||
.BR lvconvert (8)
|
||||
.BR lvdisplay (8)
|
||||
.BR lvextend (8)
|
||||
.BR lvreduce (8)
|
||||
.BR lvremove (8)
|
||||
.BR lvrename (8)
|
||||
.BR lvresize (8)
|
||||
.BR lvs (8)
|
||||
.BR lvscan (8)
|
||||
|
||||
.BR lvm2-activation-generator (8)
|
||||
.BR blkdeactivate (8)
|
||||
.BR lvmdump (8)
|
||||
|
||||
.BR dmeventd (8)
|
||||
.BR lvmetad (8)
|
||||
.BR lvmpolld (8)
|
||||
.BR lvmlockd (8)
|
||||
.BR lvmlockctl (8)
|
||||
.BR clvmd (8)
|
||||
.BR cmirrord (8)
|
||||
.BR lvmdbusd (8)
|
||||
|
||||
.BR lvmsystemid (7)
|
||||
.BR lvmreport (7)
|
||||
.BR lvmraid (7)
|
||||
.BR lvmthin (7)
|
||||
.BR lvmcache (7)
|
||||
|
0
man/lvm-dumpconfig.8_end
Normal file
0
man/lvm-dumpconfig.8_end
Normal file
522
man/lvm-dumpconfig.8_pregen
Normal file
522
man/lvm-dumpconfig.8_pregen
Normal file
@ -0,0 +1,522 @@
|
||||
.TH LVM DUMPCONFIG 8 "LVM TOOLS 2.02.169(2)-git (2016-11-30)" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
.
|
||||
lvm dumpconfig \- Display and manipulate configuration information
|
||||
.P
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvm dumpconfig\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
[ \fIposition_args\fP ]
|
||||
.br
|
||||
.P
|
||||
|
||||
.SH DESCRIPTION
|
||||
This command is the same as \fBlvmconfig\fP(8).
|
||||
|
||||
lvm dumpconfig produces formatted output from the LVM configuration tree. The
|
||||
sources of the configuration data include \fBlvm.conf\fP(5) and command
|
||||
line settings from \-\-config.
|
||||
|
||||
.P
|
||||
.SH USAGE
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvm dumpconfig\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-f\fP|\fB--file\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-l\fP|\fB--list\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--atversion\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--typeconfig\fP \fBcurrent\fP|\fBdefault\fP|\fBdiff\fP|\fBfull\fP|\fBlist\fP|\fBmissing\fP|\fBnew\fP|\fBprofilable\fP|\fBprofilable-command\fP|\fBprofilable-metadata\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignoreadvanced\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignoreunsupported\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignorelocal\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--mergedconfig\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--metadataprofile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--sinceversion\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--showdeprecated\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--showunsupported\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--validate\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--withsummary\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--withcomments\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--withspaces\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unconfigured\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--withversions\fP ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
.RS 4
|
||||
[ \fIString\fP ... ]
|
||||
.RE
|
||||
|
||||
|
||||
Common options for lvm:
|
||||
.
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-d\fP|\fB--debug\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-h\fP|\fB--help\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-q\fP|\fB--quiet\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-t\fP|\fB--test\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-v\fP|\fB--verbose\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-y\fP|\fB--yes\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--commandprofile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--config\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--driverloaded\fP \fBy\fP|\fBn\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--longhelp\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--profile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--version\fP ]
|
||||
.ad b
|
||||
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
.br
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--atversion\fP \fIString\fP
|
||||
.br
|
||||
Specify an LVM version in x.y.z format where x is the major version,
|
||||
the y is the minor version and z is the patchlevel (e.g. 2.2.106).
|
||||
When configuration is displayed, the configuration settings recognized
|
||||
at this LVM version will be considered only. This can be used
|
||||
to display a configuration that a certain LVM version understands and
|
||||
which does not contain any newer settings for which LVM would
|
||||
issue a warning message when checking the configuration.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
.br
|
||||
The command profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--config\fP \fIString\fP
|
||||
.br
|
||||
Config settings for the command. These override lvm.conf settings.
|
||||
The String arg uses the same format as lvm.conf,
|
||||
or may use section/field syntax.
|
||||
See \fBlvm.conf\fP(5) for more information about config.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-d\fP|\fB--debug\fP ...
|
||||
.br
|
||||
Set debug level. Repeat from 1 to 6 times to increase the detail of
|
||||
messages sent to the log file and/or syslog (if configured).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
If set to no, the command will not attempt to use device-mapper.
|
||||
For testing and debugging.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-f\fP|\fB--file\fP \fIString\fP
|
||||
.br
|
||||
Write output to the named file.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-h\fP|\fB--help\fP
|
||||
.br
|
||||
Display help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignoreadvanced\fP
|
||||
.br
|
||||
Exclude advanced configuration settings from the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignorelocal\fP
|
||||
.br
|
||||
Ignore local section.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignoreunsupported\fP
|
||||
.br
|
||||
Exclude unsupported configuration settings from the output. These settings are
|
||||
either used for debugging and development purposes only or their support is not
|
||||
yet complete and they are not meant to be used in production. The \fBcurrent\fP
|
||||
and \fBdiff\fP types include unsupported settings in their output by default,
|
||||
all the other types ignore unsupported settings.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-l\fP|\fB--list\fP
|
||||
.br
|
||||
List config settings with summarizing comment. This is the same as using
|
||||
options --typeconfig list --withsummary.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--longhelp\fP
|
||||
.br
|
||||
Display long help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--mergedconfig\fP
|
||||
.br
|
||||
When the command is run with --config
|
||||
and/or --commandprofile (or using LVM_COMMAND_PROFILE
|
||||
environment variable), --profile, or --metadataprofile,
|
||||
merge all the contents of the "config cascade" before displaying it.
|
||||
Without merging, only the configuration at the front of the
|
||||
cascade is displayed.
|
||||
See \fBlvm.conf\fP(5) for more information about config.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--metadataprofile\fP \fIString\fP
|
||||
.br
|
||||
The metadata profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--profile\fP \fIString\fP
|
||||
.br
|
||||
An alias for --commandprofile or --metadataprofile, depending
|
||||
on the command.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP ...
|
||||
.br
|
||||
Suppress output and log messages. Overrides --debug and --verbose.
|
||||
Repeat once to also suppress any prompts with answer no.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--showdeprecated\fP
|
||||
.br
|
||||
Include deprecated configuration settings in the output. These settings
|
||||
are deprecated after a certain version. If a concrete version is specified
|
||||
with --atversion, deprecated settings are automatically included
|
||||
if the specified version is lower than the version in which the settings were
|
||||
deprecated. The current and diff types include deprecated settings
|
||||
in their output by default, all the other types ignore deprecated settings.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--showunsupported\fP
|
||||
.br
|
||||
Include unsupported configuration settings in the output. These settings
|
||||
are either used for debugging or development purposes only, or their support
|
||||
is not yet complete and they are not meant to be used in production. The
|
||||
current and diff types include unsupported settings in their
|
||||
output by default, all the other types ignore unsupported settings.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--sinceversion\fP \fIString\fP
|
||||
.br
|
||||
Specify an LVM version in x.y.z format where x is the major version,
|
||||
the y is the minor version and z is the patchlevel (e.g. 2.2.106).
|
||||
This option is currently applicable only with --typeconfig new
|
||||
to display all configuration settings introduced since given version.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-t\fP|\fB--test\fP
|
||||
.br
|
||||
Run in test mode. Commands will not update metadata.
|
||||
This is implemented by disabling all metadata writing but nevertheless
|
||||
returning success to the calling function. This may lead to unusual
|
||||
error messages in multi-stage operations if a tool relies on reading
|
||||
back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--typeconfig\fP \fBcurrent\fP|\fBdefault\fP|\fBdiff\fP|\fBfull\fP|\fBlist\fP|\fBmissing\fP|\fBnew\fP|\fBprofilable\fP|\fBprofilable-command\fP|\fBprofilable-metadata\fP
|
||||
.br
|
||||
See lvmreport(7).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unconfigured\fP
|
||||
.br
|
||||
Internal option used for generating config file during build.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--validate\fP
|
||||
.br
|
||||
Validate current configuration used and exit with appropriate
|
||||
return code. The validation is done only for the configuration
|
||||
at the front of the "config cascade". To validate the whole
|
||||
merged configuration tree, also use --mergedconfig.
|
||||
The validation is done even if lvm.conf config/checks is disabled.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
of messages sent to stdout and stderr.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--version\fP
|
||||
.br
|
||||
Display version information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--withcomments\fP
|
||||
.br
|
||||
Display a full comment for each configuration node. For deprecated
|
||||
settings, also display comments about deprecation.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--withspaces\fP
|
||||
.br
|
||||
Where appropriate, add more spaces in output for better readability.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--withsummary\fP
|
||||
.br
|
||||
Display a one line comment for each configuration node.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--withversions\fP
|
||||
.br
|
||||
Also display a comment containing the version of introduction for
|
||||
each configuration node. If the setting is deprecated, also display
|
||||
the version since which it is deprecated.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.br
|
||||
Do not prompt for confirmation interactively but always assume the
|
||||
answer yes. Use with extreme caution.
|
||||
(For automatic no, see -qq.)
|
||||
.ad b
|
||||
.SH VARIABLES
|
||||
.br
|
||||
|
||||
.HP
|
||||
\fIString\fP
|
||||
.br
|
||||
See the option description for information about the string content.
|
||||
|
||||
.HP
|
||||
\fISize\fP[UNIT]
|
||||
.br
|
||||
Size is an input number that accepts an optional unit.
|
||||
Input units are always treated as base two values, regardless of
|
||||
capitalization, e.g. 'k' and 'K' both refer to 1024.
|
||||
The default input unit is specified by letter, followed by |UNIT.
|
||||
UNIT represents other possible input units: \fBbBsSkKmMgGtTpPeE\fP.
|
||||
b|B is bytes, s|S is sectors of 512 bytes, k|K is kilobytes,
|
||||
m|M is megabytes, g|G is gigabytes, t|T is terabytes,
|
||||
p|P is petabytes, e|E is exabytes.
|
||||
(This should not be confused with the output control --units, where
|
||||
capital letters mean multiple of 1000.)
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.br
|
||||
See \fBlvm\fP(8) for information about environment variables used by lvm.
|
||||
For example, LVM_VG_NAME can generally be substituted for a required VG parameter.
|
||||
.SH SEE ALSO
|
||||
|
||||
.BR lvm (8)
|
||||
.BR lvm.conf (5)
|
||||
.BR lvmconfig (8)
|
||||
|
||||
.BR pvchange (8)
|
||||
.BR pvck (8)
|
||||
.BR pvcreate (8)
|
||||
.BR pvdisplay (8)
|
||||
.BR pvmove (8)
|
||||
.BR pvremove (8)
|
||||
.BR pvresize (8)
|
||||
.BR pvs (8)
|
||||
.BR pvscan (8)
|
||||
|
||||
.BR vgcfgbackup (8)
|
||||
.BR vgcfgrestore (8)
|
||||
.BR vgchange (8)
|
||||
.BR vgck (8)
|
||||
.BR vgcreate (8)
|
||||
.BR vgconvert (8)
|
||||
.BR vgdisplay (8)
|
||||
.BR vgexport (8)
|
||||
.BR vgextend (8)
|
||||
.BR vgimport (8)
|
||||
.BR vgimportclone (8)
|
||||
.BR vgmerge (8)
|
||||
.BR vgmknodes (8)
|
||||
.BR vgreduce (8)
|
||||
.BR vgremove (8)
|
||||
.BR vgrename (8)
|
||||
.BR vgs (8)
|
||||
.BR vgscan (8)
|
||||
.BR vgsplit (8)
|
||||
|
||||
.BR lvcreate (8)
|
||||
.BR lvchange (8)
|
||||
.BR lvconvert (8)
|
||||
.BR lvdisplay (8)
|
||||
.BR lvextend (8)
|
||||
.BR lvreduce (8)
|
||||
.BR lvremove (8)
|
||||
.BR lvrename (8)
|
||||
.BR lvresize (8)
|
||||
.BR lvs (8)
|
||||
.BR lvscan (8)
|
||||
|
||||
.BR lvm2-activation-generator (8)
|
||||
.BR blkdeactivate (8)
|
||||
.BR lvmdump (8)
|
||||
|
||||
.BR dmeventd (8)
|
||||
.BR lvmetad (8)
|
||||
.BR lvmpolld (8)
|
||||
.BR lvmlockd (8)
|
||||
.BR lvmlockctl (8)
|
||||
.BR clvmd (8)
|
||||
.BR cmirrord (8)
|
||||
.BR lvmdbusd (8)
|
||||
|
||||
.BR lvmsystemid (7)
|
||||
.BR lvmreport (7)
|
||||
.BR lvmraid (7)
|
||||
.BR lvmthin (7)
|
||||
.BR lvmcache (7)
|
||||
|
0
man/lvm-fullreport.8_end
Normal file
0
man/lvm-fullreport.8_end
Normal file
623
man/lvm-fullreport.8_pregen
Normal file
623
man/lvm-fullreport.8_pregen
Normal file
@ -0,0 +1,623 @@
|
||||
.TH LVM FULLREPORT 8 "LVM TOOLS 2.02.169(2)-git (2016-11-30)" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
.
|
||||
lvm fullreport \- Display full report
|
||||
.P
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvm fullreport\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
[ \fIposition_args\fP ]
|
||||
.br
|
||||
.P
|
||||
|
||||
.SH DESCRIPTION
|
||||
lvm fullreport produces formatted output about PVs, PV segments, VGs, LVs
|
||||
and LV segments. The information is all gathered together for each VG
|
||||
(under a per-VG lock) so it is consistent. Information gathered from
|
||||
separate calls to \fBvgs\fP, \fBpvs\fP, and \fBlvs\fP can be inconsistent
|
||||
if information changes between commands.
|
||||
|
||||
|
||||
.P
|
||||
.SH USAGE
|
||||
.br
|
||||
.P
|
||||
.
|
||||
\fBlvm fullreport\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-a\fP|\fB--all\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-o\fP|\fB--options\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-P\fP|\fB--partial\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-S\fP|\fB--select\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-O\fP|\fB--sort\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--aligned\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--binary\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--configreport\fP \fBlog\fP|\fBvg\fP|\fBlv\fP|\fBpv\fP|\fBpvseg\fP|\fBseg\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--foreign\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignorelockingfailure\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--ignoreskippedcluster\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--logonly\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--nameprefixes\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--noheadings\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--nolocking\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--nosuffix\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--readonly\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--rows\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--separator\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--shared\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--trustcache\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unbuffered\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--units\fP \fBr\fP|\fBR\fP|\fBh\fP|\fBH\fP|\fBb\fP|\fBB\fP|\fBs\fP|\fBS\fP|\fBk\fP|\fBK\fP|\fBm\fP|\fBM\fP|\fBg\fP|\fBG\fP|\fBt\fP|\fBT\fP|\fBp\fP|\fBP\fP|\fBe\fP|\fBE\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--unquoted\fP ]
|
||||
.ad b
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.RE
|
||||
.br
|
||||
.RS 4
|
||||
[ \fIVG\fP ... ]
|
||||
.RE
|
||||
|
||||
|
||||
Common options for lvm:
|
||||
.
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB-d\fP|\fB--debug\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-h\fP|\fB--help\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-q\fP|\fB--quiet\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-t\fP|\fB--test\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-v\fP|\fB--verbose\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB-y\fP|\fB--yes\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--commandprofile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--config\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--driverloaded\fP \fBy\fP|\fBn\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--longhelp\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--profile\fP \fIString\fP ]
|
||||
.ad b
|
||||
.br
|
||||
.ad l
|
||||
[ \fB--version\fP ]
|
||||
.ad b
|
||||
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
.br
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--aligned\fP
|
||||
.br
|
||||
Use with --separator to align the output columns
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-a\fP|\fB--all\fP
|
||||
.br
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--binary\fP
|
||||
.br
|
||||
Use binary values "0" or "1" instead of descriptive literal values
|
||||
for columns that have exactly two valid values to report (not counting
|
||||
the "unknown" value which denotes that the value could not be determined).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--commandprofile\fP \fIString\fP
|
||||
.br
|
||||
The command profile to use for command configuration.
|
||||
See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--config\fP \fIString\fP
|
||||
.br
|
||||
Config settings for the command. These override lvm.conf settings.
|
||||
The String arg uses the same format as lvm.conf,
|
||||
or may use section/field syntax.
|
||||
See \fBlvm.conf\fP(5) for more information about config.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--configreport\fP \fBlog\fP|\fBvg\fP|\fBlv\fP|\fBpv\fP|\fBpvseg\fP|\fBseg\fP
|
||||
.br
|
||||
See lvmreport(7).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-d\fP|\fB--debug\fP ...
|
||||
.br
|
||||
Set debug level. Repeat from 1 to 6 times to increase the detail of
|
||||
messages sent to the log file and/or syslog (if configured).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--driverloaded\fP \fBy\fP|\fBn\fP
|
||||
.br
|
||||
If set to no, the command will not attempt to use device-mapper.
|
||||
For testing and debugging.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--foreign\fP
|
||||
.br
|
||||
Report/display foreign VGs that would otherwise be skipped.
|
||||
See lvmsystemid(7) for more information about foreign VGs.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-h\fP|\fB--help\fP
|
||||
.br
|
||||
Display help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignorelockingfailure\fP
|
||||
.br
|
||||
Allows a command to continue with read-only metadata
|
||||
operations after locking failures.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--ignoreskippedcluster\fP
|
||||
.br
|
||||
Use to avoid exiting with an non-zero status code if the command is run
|
||||
without clustered locking and clustered VGs are skipped.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--logonly\fP
|
||||
.br
|
||||
Suppress command report and display only log report.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--longhelp\fP
|
||||
.br
|
||||
Display long help text.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--nameprefixes\fP
|
||||
.br
|
||||
Add an "LVM2_" prefix plus the field name to the output. Useful
|
||||
with --noheadings to produce a list of field=value pairs that can
|
||||
be used to set environment variables (for example, in udev rules).
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--noheadings\fP
|
||||
.br
|
||||
Suppress the headings line that is normally the first line of output.
|
||||
Useful if grepping the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--nosuffix\fP
|
||||
.br
|
||||
Suppress the suffix on output sizes. Use with --units
|
||||
(except h and H) if processing the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-o\fP|\fB--options\fP \fIString\fP
|
||||
.br
|
||||
Comma-separated, ordered list of fields to display in columns.
|
||||
String arg syntax is: [+|-|#]Field1[,Field2 ...]
|
||||
The prefix \fB+\fP will append the specified fields to the default fields,
|
||||
\fB-\fP will remove the specified fields from the default fields, and
|
||||
\fB#\fP will compact specified fields (removing them when empty for all rows.)
|
||||
Use \fB-o help\fP to view the list of all available fields.
|
||||
The -o option can be repeated, providing several lists.
|
||||
These lists are evaluated from left to right.
|
||||
Use field name \fBlv_all\fP to view all LV fields,
|
||||
\fBvg_all\fP all VG fields,
|
||||
\fBpv_all\fP all PV fields,
|
||||
\fBpvseg_all\fP all PV segment fields,
|
||||
\fBseg_all\fP all LV segment fields, and
|
||||
\fBpvseg_all\fP all PV segment columns.
|
||||
See the lvm.conf report section for more config options.
|
||||
See lvmreport(7) for more information about reporting.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-P\fP|\fB--partial\fP
|
||||
.br
|
||||
When set, the tools will do their best to provide access to VGs
|
||||
that are only partially available (one or more PVs belonging
|
||||
to the VG are missing from the system). Metadata may not be
|
||||
changed with this option.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--profile\fP \fIString\fP
|
||||
.br
|
||||
An alias for --commandprofile or --metadataprofile, depending
|
||||
on the command.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-q\fP|\fB--quiet\fP ...
|
||||
.br
|
||||
Suppress output and log messages. Overrides --debug and --verbose.
|
||||
Repeat once to also suppress any prompts with answer no.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--readonly\fP
|
||||
.br
|
||||
Run the command in a special read-only mode which will read on-disk
|
||||
metadata without needing to take any locks. This can be used to peek
|
||||
inside metadata used by a virtual machine image while the virtual
|
||||
machine is running.
|
||||
It can also be used to peek inside the metadata of clustered VGs
|
||||
when clustered locking is not configured or running. No attempt
|
||||
will be made to communicate with the device-mapper kernel driver, so
|
||||
this option is unable to report whether or not LVs are
|
||||
actually in use.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
|
||||
.br
|
||||
Overrides current output format for reports which is defined globally by
|
||||
the report/output_format setting in lvm.conf.
|
||||
\fBbasic\fP is the original format with columns and rows.
|
||||
If there is more than one report per command, each report is prefixed
|
||||
with the report name for identification. \fBjson\fP produces report
|
||||
output in JSON format. See \fBlvmreport\fP(7) for more information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--rows\fP
|
||||
.br
|
||||
Output columns as rows.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-S\fP|\fB--select\fP \fIString\fP
|
||||
.br
|
||||
Select objects for processing and reporting based on specified criteria.
|
||||
The criteria syntax is described by \fB--select help\fP and \fBlvmreport\fP(7).
|
||||
For reporting commands, one row is displayed for each object matching the criteria.
|
||||
See \fB--options help\fP for selectable object fields.
|
||||
Rows can be displayed with an additional "selected" field (-o selected)
|
||||
showing 1 if the row matches the selection and 0 otherwise.
|
||||
For non-reporting commands which process LVM entities, the selection is
|
||||
used to choose items to process.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--separator\fP \fIString\fP
|
||||
.br
|
||||
String to use to separate each column. Useful if grepping the output.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--shared\fP
|
||||
.br
|
||||
Report/display shared VGs that would otherwise be skipped when
|
||||
lvmlockd is not being used on the host.
|
||||
See lvmlockd(8) for more information about shared VGs.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-O\fP|\fB--sort\fP \fIString\fP
|
||||
.br
|
||||
Comma-separated ordered list of columns to sort by. Replaces the default
|
||||
selection. Precede any column with \fB-\fP for a reverse sort on that column.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-t\fP|\fB--test\fP
|
||||
.br
|
||||
Run in test mode. Commands will not update metadata.
|
||||
This is implemented by disabling all metadata writing but nevertheless
|
||||
returning success to the calling function. This may lead to unusual
|
||||
error messages in multi-stage operations if a tool relies on reading
|
||||
back metadata it believes has changed but hasn't.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--trustcache\fP
|
||||
.br
|
||||
Avoids certain device scanning during command processing. Do not use.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unbuffered\fP
|
||||
.br
|
||||
Produce output immediately without sorting or aligning the columns properly.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--units\fP \fBr\fP|\fBR\fP|\fBh\fP|\fBH\fP|\fBb\fP|\fBB\fP|\fBs\fP|\fBS\fP|\fBk\fP|\fBK\fP|\fBm\fP|\fBM\fP|\fBg\fP|\fBG\fP|\fBt\fP|\fBT\fP|\fBp\fP|\fBP\fP|\fBe\fP|\fBE\fP
|
||||
.br
|
||||
All sizes are output in these units:
|
||||
human-(r)eadable with '<' rounding indicator,
|
||||
(h)uman-readable, (b)ytes, (s)ectors, (k)ilobytes, (m)egabytes,
|
||||
(g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.
|
||||
Capitalise to use multiples of 1000 (S.I.) instead of 1024.
|
||||
Custom units can be specified, e.g. --units 3M.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--unquoted\fP
|
||||
.br
|
||||
When used with --nameprefixes, output values in the field=value
|
||||
pairs are not quoted.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
of messages sent to stdout and stderr.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB--version\fP
|
||||
.br
|
||||
Display version information.
|
||||
.ad b
|
||||
|
||||
.HP
|
||||
.ad l
|
||||
\fB-y\fP|\fB--yes\fP
|
||||
.br
|
||||
Do not prompt for confirmation interactively but always assume the
|
||||
answer yes. Use with extreme caution.
|
||||
(For automatic no, see -qq.)
|
||||
.ad b
|
||||
.SH VARIABLES
|
||||
.br
|
||||
|
||||
.HP
|
||||
\fIVG\fP
|
||||
.br
|
||||
Volume Group name. See \fBlvm\fP(8) for valid names.
|
||||
|
||||
.HP
|
||||
\fIString\fP
|
||||
.br
|
||||
See the option description for information about the string content.
|
||||
|
||||
.HP
|
||||
\fISize\fP[UNIT]
|
||||
.br
|
||||
Size is an input number that accepts an optional unit.
|
||||
Input units are always treated as base two values, regardless of
|
||||
capitalization, e.g. 'k' and 'K' both refer to 1024.
|
||||
The default input unit is specified by letter, followed by |UNIT.
|
||||
UNIT represents other possible input units: \fBbBsSkKmMgGtTpPeE\fP.
|
||||
b|B is bytes, s|S is sectors of 512 bytes, k|K is kilobytes,
|
||||
m|M is megabytes, g|G is gigabytes, t|T is terabytes,
|
||||
p|P is petabytes, e|E is exabytes.
|
||||
(This should not be confused with the output control --units, where
|
||||
capital letters mean multiple of 1000.)
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.br
|
||||
See \fBlvm\fP(8) for information about environment variables used by lvm.
|
||||
For example, LVM_VG_NAME can generally be substituted for a required VG parameter.
|
||||
.SH SEE ALSO
|
||||
|
||||
.BR lvm (8)
|
||||
.BR lvm.conf (5)
|
||||
.BR lvmconfig (8)
|
||||
|
||||
.BR pvchange (8)
|
||||
.BR pvck (8)
|
||||
.BR pvcreate (8)
|
||||
.BR pvdisplay (8)
|
||||
.BR pvmove (8)
|
||||
.BR pvremove (8)
|
||||
.BR pvresize (8)
|
||||
.BR pvs (8)
|
||||
.BR pvscan (8)
|
||||
|
||||
.BR vgcfgbackup (8)
|
||||
.BR vgcfgrestore (8)
|
||||
.BR vgchange (8)
|
||||
.BR vgck (8)
|
||||
.BR vgcreate (8)
|
||||
.BR vgconvert (8)
|
||||
.BR vgdisplay (8)
|
||||
.BR vgexport (8)
|
||||
.BR vgextend (8)
|
||||
.BR vgimport (8)
|
||||
.BR vgimportclone (8)
|
||||
.BR vgmerge (8)
|
||||
.BR vgmknodes (8)
|
||||
.BR vgreduce (8)
|
||||
.BR vgremove (8)
|
||||
.BR vgrename (8)
|
||||
.BR vgs (8)
|
||||
.BR vgscan (8)
|
||||
.BR vgsplit (8)
|
||||
|
||||
.BR lvcreate (8)
|
||||
.BR lvchange (8)
|
||||
.BR lvconvert (8)
|
||||
.BR lvdisplay (8)
|
||||
.BR lvextend (8)
|
||||
.BR lvreduce (8)
|
||||
.BR lvremove (8)
|
||||
.BR lvrename (8)
|
||||
.BR lvresize (8)
|
||||
.BR lvs (8)
|
||||
.BR lvscan (8)
|
||||
|
||||
.BR lvm2-activation-generator (8)
|
||||
.BR blkdeactivate (8)
|
||||
.BR lvmdump (8)
|
||||
|
||||
.BR dmeventd (8)
|
||||
.BR lvmetad (8)
|
||||
.BR lvmpolld (8)
|
||||
.BR lvmlockd (8)
|
||||
.BR lvmlockctl (8)
|
||||
.BR clvmd (8)
|
||||
.BR cmirrord (8)
|
||||
.BR lvmdbusd (8)
|
||||
|
||||
.BR lvmsystemid (7)
|
||||
.BR lvmreport (7)
|
||||
.BR lvmraid (7)
|
||||
.BR lvmthin (7)
|
||||
.BR lvmcache (7)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user