mirror of
git://sourceware.org/git/lvm2.git
synced 2025-08-20 21:49:28 +03:00
Compare commits
341 Commits
sourceware
...
dev-bmr-dm
Author | SHA1 | Date | |
---|---|---|---|
d60364c634 | |||
b5ac2c458a | |||
181975e635 | |||
820843fcb6 | |||
d487fcfb0e | |||
f1e42e2186 | |||
3c69a7248a | |||
00e716b037 | |||
926ce7e279 | |||
6582cc4ff2 | |||
618f9ab04b | |||
5994ed9df2 | |||
11749e7adb | |||
6740eb1c2b | |||
f86c1f5d0a | |||
bc5d67884f | |||
13426092e9 | |||
f66bc3dab0 | |||
8658bbe3ee | |||
7db51a6bed | |||
70bb726678 | |||
43fdbb8aeb | |||
b5252a51a5 | |||
481a522dd7 | |||
d71071a1af | |||
5dfd35f2f8 | |||
5012be326d | |||
4af09a94bd | |||
6742137964 | |||
162552041f | |||
a41d5b6491 | |||
3aab873199 | |||
0c2f7ed49a | |||
396377bc03 | |||
b9399f2148 | |||
19a72e601f | |||
7f31261844 | |||
88e408b8ed | |||
e3a3cf01eb | |||
78d004efa8 | |||
36cac41115 | |||
6165e09221 | |||
5c199d99f4 | |||
66b2084b96 | |||
d823c65d50 | |||
25c841af00 | |||
4046f9bd95 | |||
e9433a9de9 | |||
9354ce6045 | |||
10e0a5066e | |||
5eec3de41f | |||
93467f0d9f | |||
a29bb6a14b | |||
2eaca7ab63 | |||
fe3b9bb7d4 | |||
6471bb2c41 | |||
0dabe7237c | |||
e8362b4cb7 | |||
b84bf3e8cd | |||
1bf90dac77 | |||
14c4d32247 | |||
3be2e61c9f | |||
7126fb13e7 | |||
1810162b51 | |||
1e4462dbfb | |||
642d682d8d | |||
b3e833c777 | |||
862ca6e8b7 | |||
b65a9230a3 | |||
3ead4fb7ac | |||
7eeb093fdd | |||
2dc71fc291 | |||
17b56a4aed | |||
07040942ed | |||
8d7be8f5df | |||
fec2ea76cf | |||
17a8f3d6f0 | |||
6ebf39da91 | |||
76709aaf39 | |||
07ea9887d3 | |||
4a271e7ee7 | |||
d211c98581 | |||
e0ea569045 | |||
1520fec3e8 | |||
17bee733d1 | |||
5e7bc8d854 | |||
270ed9bc90 | |||
0c74afa1c6 | |||
2d00767394 | |||
ad4158bac7 | |||
4a3e30d102 | |||
b917b12e2c | |||
b0336e8b3c | |||
76b843a4bf | |||
a37bb7b2a5 | |||
73d028023a | |||
c8719d4e94 | |||
506d88a2ec | |||
e5b6f2685a | |||
a87715b6fd | |||
19b65a3d76 | |||
7067514c9b | |||
5ba82a16db | |||
cf0bf4b314 | |||
a4a6a7a526 | |||
2fd5c8e908 | |||
affe055462 | |||
51b9de7249 | |||
7fa08ae4e8 | |||
e9b5a455e1 | |||
8ef93c756e | |||
b0430b975b | |||
1cdaa8144d | |||
4f86519845 | |||
9729fc4f8c | |||
6d6ab310e5 | |||
07ded8059c | |||
4a727a3ccd | |||
e3a51537c5 | |||
42b970d4f3 | |||
2a139993b4 | |||
0dcb928d1e | |||
115fd205de | |||
849ab38e3c | |||
7b6ee130cc | |||
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
|
||||
|
@ -1 +1 @@
|
||||
1.02.138-git (2016-11-30)
|
||||
1.02.139-git (2017-03-28)
|
||||
|
34
WHATS_NEW
34
WHATS_NEW
@ -1,8 +1,30 @@
|
||||
Version 2.02.169 -
|
||||
=====================================
|
||||
Version 2.02.170 -
|
||||
==================================
|
||||
|
||||
Version 2.02.169 - 28th March 2017
|
||||
==================================
|
||||
Automatically decide whether '-' in a man page is a hyphen or a minus sign.
|
||||
Add build-time configuration command line to 'lvm version' output.
|
||||
Handle known table line parameter order change in specific raid target vsns.
|
||||
Conditionally reject raid convert to striped/raid0* after reshape.
|
||||
Ensure raid6 upconversion restrictions.
|
||||
Adjust mirror & raid dmeventd plugins for new lvconvert --repair behaviour.
|
||||
Disable lvmetad when lvconvert --repair is run.
|
||||
Remove obsolete lvmchange binary - convert to built-in command.
|
||||
Show more information for cached volumes in lvdisplay [-m].
|
||||
Add option for lvcreate/lvconvert --cachemetadataformat auto|1|2.
|
||||
Support cache segment with configurable metadata format.
|
||||
Add allocation/cache_metadata_format profilable settings.
|
||||
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).
|
||||
Fix regression of accepting both --type and -m with lvresize. (2.02.158)
|
||||
Add lvconvert --swapmetadata, new specific way to swap pool metadata LVs.
|
||||
Add lvconvert --startpoll, new specific way to start polling conversions.
|
||||
Add lvconvert --mergethin, new specific way to merge thin snapshots.
|
||||
@ -15,9 +37,9 @@ Version 2.02.169 -
|
||||
Match every command run to one command definition.
|
||||
Specify every allowed command definition/syntax in command-lines.in.
|
||||
Add extra memory page when limiting pthread stack size in clvmd.
|
||||
Support striped/raid0* <-> raid10_near conversions
|
||||
Support shrinking of RaidLvs
|
||||
Support region size changes on existing RaidLVs
|
||||
Support striped/raid0* <-> raid10_near conversions.
|
||||
Support shrinking of RaidLVs.
|
||||
Support region size changes on existing RaidLVs.
|
||||
Avoid parallel usage of cpg_mcast_joined() in clvmd with corosync.
|
||||
Support raid6_{ls,rs,la,ra}_6 segment types and conversions from/to it.
|
||||
Support raid6_n_6 segment type and conversions from/to it.
|
||||
|
24
WHATS_NEW_DM
24
WHATS_NEW_DM
@ -1,19 +1,27 @@
|
||||
Version 1.02.138 -
|
||||
=====================================
|
||||
Version 1.02.139 -
|
||||
==================================
|
||||
|
||||
Version 1.02.138 - 28th March 2017
|
||||
==================================
|
||||
Support additional raid5/6 configurations.
|
||||
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.
|
||||
Do not suppress kernel key description in dmsetup table output for dm-crypt.
|
||||
Support configurable command executed from dmeventd thin plugin.
|
||||
Support new R|r human readable units output format.
|
||||
Thin dmeventd plugin reacts faster on lvextend failure path with umount.
|
||||
Add dm_stats_bind_from_fd() to bind a stats handle from a file descriptor.
|
||||
Do not try call callback when reverting activation on error path.
|
||||
Fix file mapping for extents with physically adjacent extents.
|
||||
Fix file mapping for extents with physically adjacent extents in dmstats.
|
||||
Validation vsnprintf result in runtime translate of dm_log (1.02.136).
|
||||
Separate filemap extent allocation from region table.
|
||||
Fix segmentation fault when filemap region creation fails.
|
||||
Fix performance of region cleanup for failed filemap creation.
|
||||
Fix very slow region deletion with many regions.
|
||||
Separate filemap extent allocation from region table in dmstats.
|
||||
Fix segmentation fault when filemap region creation fails in dmstats.
|
||||
Fix performance of region cleanup for failed filemap creation in dmstats.
|
||||
Fix very slow region deletion with many regions in dmstats.
|
||||
|
||||
Version 1.02.137 - 30th November 2016
|
||||
=====================================
|
||||
|
@ -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.
|
||||
|
81
configure
vendored
81
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
|
||||
@ -3011,6 +3015,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
CONFIGURE_LINE="$0 $@"
|
||||
|
||||
ac_config_headers="$ac_config_headers include/configure.h"
|
||||
|
||||
@ -6074,7 +6079,7 @@ fi
|
||||
done
|
||||
|
||||
|
||||
for ac_header in termios.h sys/statvfs.h sys/timerfd.h linux/magic.h linux/fiemap.h
|
||||
for ac_header in termios.h sys/statvfs.h sys/timerfd.h sys/vfs.h linux/magic.h linux/fiemap.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
@ -6267,6 +6272,26 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default"
|
||||
if test "x$ac_cv_member_struct_stat_st_blocks" = xyes; then :
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_STRUCT_STAT_ST_BLOCKS 1
|
||||
_ACEOF
|
||||
|
||||
|
||||
$as_echo "#define HAVE_ST_BLOCKS 1" >>confdefs.h
|
||||
|
||||
else
|
||||
case " $LIBOBJS " in
|
||||
*" fileblocks.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS fileblocks.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
|
||||
$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
|
||||
if ${ac_cv_struct_tm+:} false; then :
|
||||
@ -12074,6 +12099,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 +15174,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.
|
||||
@ -15426,6 +15494,12 @@ LVM_MINOR=`echo "$VER" | $AWK -F '.' '{print $2}'`
|
||||
LVM_PATCHLEVEL=`echo "$VER" | $AWK -F '[(.]' '{print $3}'`
|
||||
LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define LVM_CONFIGURE_LINE "$CONFIGURE_LINE"
|
||||
_ACEOF
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
@ -15582,11 +15656,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 +16370,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" ;;
|
||||
|
28
configure.in
28
configure.in
@ -15,6 +15,7 @@ AC_PREREQ(2.69)
|
||||
################################################################################
|
||||
dnl -- Process this file with autoconf to produce a configure script.
|
||||
AC_INIT
|
||||
CONFIGURE_LINE="$0 $@"
|
||||
AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
|
||||
AC_CONFIG_HEADERS([include/configure.h])
|
||||
|
||||
@ -105,7 +106,7 @@ AC_CHECK_HEADERS([assert.h ctype.h dirent.h errno.h fcntl.h float.h \
|
||||
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
|
||||
unistd.h], , [AC_MSG_ERROR(bailing out)])
|
||||
|
||||
AC_CHECK_HEADERS(termios.h sys/statvfs.h sys/timerfd.h linux/magic.h linux/fiemap.h)
|
||||
AC_CHECK_HEADERS(termios.h sys/statvfs.h sys/timerfd.h sys/vfs.h linux/magic.h linux/fiemap.h)
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
@ -120,6 +121,7 @@ AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||
AC_CHECK_TYPES([ptrdiff_t])
|
||||
AC_STRUCT_ST_BLOCKS
|
||||
AC_STRUCT_TM
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_PID_T
|
||||
@ -1271,6 +1273,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 +1872,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)
|
||||
|
||||
@ -1982,6 +2003,8 @@ LVM_MINOR=`echo "$VER" | $AWK -F '.' '{print $2}'`
|
||||
LVM_PATCHLEVEL=`echo "$VER" | $AWK -F '[[(.]]' '{print $3}'`
|
||||
LVM_LIBAPI=`echo "$VER" | $AWK -F '[[()]]' '{print $2}'`
|
||||
|
||||
AC_DEFINE_UNQUOTED(LVM_CONFIGURE_LINE, "$CONFIGURE_LINE", [configure command line used])
|
||||
|
||||
################################################################################
|
||||
AC_SUBST(APPLIB)
|
||||
AC_SUBST(AWK)
|
||||
@ -1994,6 +2017,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 +2067,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 +2183,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
|
||||
|
@ -71,6 +71,17 @@ void model_FD_ZERO(void *fdset)
|
||||
((long*)fdset)[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Resent Coverity reports quite weird errors... */
|
||||
int *__errno_location(void)
|
||||
{
|
||||
}
|
||||
const unsigned short **__ctype_b_loc (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Added extra pointer check to not need these models,
|
||||
* for now just keep then in file
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2005-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
struct dso_state {
|
||||
struct dm_pool *mem;
|
||||
char cmd_lvscan[512];
|
||||
char cmd_lvconvert[512];
|
||||
};
|
||||
|
||||
@ -99,12 +98,8 @@ static int _get_mirror_event(struct dso_state *state, char *params)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconvert,
|
||||
const char *device)
|
||||
static int _remove_failed_devices(const char *cmd_lvconvert, const char *device)
|
||||
{
|
||||
if (!dmeventd_lvm2_run_with_lock(cmd_lvscan))
|
||||
log_warn("WARNING: Re-scan of mirrored device %s failed.", device);
|
||||
|
||||
/* if repair goes OK, report success even if lvscan has failed */
|
||||
if (!dmeventd_lvm2_run_with_lock(cmd_lvconvert)) {
|
||||
log_error("Repair of mirrored device %s failed.", device);
|
||||
@ -151,9 +146,7 @@ void process_event(struct dm_task *dmt,
|
||||
break;
|
||||
case ME_FAILURE:
|
||||
log_error("Device failure in %s.", device);
|
||||
if (!_remove_failed_devices(state->cmd_lvscan,
|
||||
state->cmd_lvconvert,
|
||||
device))
|
||||
if (!_remove_failed_devices(state->cmd_lvconvert, device))
|
||||
/* FIXME Why are all the error return codes unused? Get rid of them? */
|
||||
log_error("Failed to remove faulty devices in %s.",
|
||||
device);
|
||||
@ -183,10 +176,7 @@ int register_device(const char *device,
|
||||
if (!dmeventd_lvm2_init_with_pool("mirror_state", state))
|
||||
goto_bad;
|
||||
|
||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan),
|
||||
"lvscan --cache", device))
|
||||
goto_bad;
|
||||
|
||||
/* CANNOT use --config as this disables cached content */
|
||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
|
||||
"lvconvert --repair --use-policies", device))
|
||||
goto_bad;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2005-2017 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -22,7 +22,6 @@
|
||||
|
||||
struct dso_state {
|
||||
struct dm_pool *mem;
|
||||
char cmd_lvscan[512];
|
||||
char cmd_lvconvert[512];
|
||||
uint64_t raid_devs[RAID_DEVS_ELEMS];
|
||||
int failed;
|
||||
@ -74,8 +73,6 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
goto out; /* already reported */
|
||||
|
||||
state->failed = 1;
|
||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan))
|
||||
log_warn("WARNING: Re-scan of RAID device %s failed.", device);
|
||||
|
||||
/* if repair goes OK, report success even if lvscan has failed */
|
||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
|
||||
@ -136,9 +133,7 @@ int register_device(const char *device,
|
||||
if (!dmeventd_lvm2_init_with_pool("raid_state", state))
|
||||
goto_bad;
|
||||
|
||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan),
|
||||
"lvscan --cache", device) ||
|
||||
!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
|
||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
|
||||
"lvconvert --config devices{ignore_suspended_devices=1} "
|
||||
"--repair --use-policies", device))
|
||||
goto_bad;
|
||||
|
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_DMFILEMAPD_TARGETS)
|
||||
|
||||
install: install_dmfilemapd
|
||||
|
||||
install_device-mapper: install_dmfilemapd
|
||||
|
816
daemons/dmfilemapd/dmfilemapd.c
Normal file
816
daemons/dmfilemapd/dmfilemapd.c
Normal file
@ -0,0 +1,816 @@
|
||||
/*
|
||||
* 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 */
|
||||
uint64_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.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid_d = opendir(path_buf);
|
||||
if (!pid_d) {
|
||||
log_error("Could not open proc path: %s.", path_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)) {
|
||||
if (closedir(pid_d))
|
||||
log_sys_error("closedir", path_buf);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bad:
|
||||
if (closedir(pid_d))
|
||||
log_sys_error("closedir", path_buf);
|
||||
|
||||
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 = (pid_t) strtol(proc_dp->d_name, NULL, 10);
|
||||
if (!pid)
|
||||
continue;
|
||||
if (_is_open_in_pid(pid, path)) {
|
||||
if (closedir(proc_d))
|
||||
log_sys_error("closedir", DEFAULT_PROC_DIR);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (closedir(proc_d))
|
||||
log_sys_error("closedir", DEFAULT_PROC_DIR);
|
||||
|
||||
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 = (int) 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 = (int) strtol(argv[0], &endptr, 10);
|
||||
if (*endptr) {
|
||||
_early_log("Could not parse debug argument: %s.",
|
||||
argv[0]);
|
||||
return 0;
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
if (argc) {
|
||||
_verbose = (int) 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) {
|
||||
log_sys_error("inotify_init1", "IN_NONBLOCK");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((watch_fd = inotify_add_watch(inotify_fd, fm->path,
|
||||
IN_MODIFY | IN_DELETE_SELF)) < 0) {
|
||||
log_sys_error("inotify_add_watch", fm->path);
|
||||
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;
|
||||
ssize_t len;
|
||||
|
||||
fm->deleted = 0;
|
||||
|
||||
if ((fd = open(fm->path, O_RDONLY)) < 0)
|
||||
goto check_unlinked;
|
||||
|
||||
same = _filemap_monitor_check_same_file(fm->fd, fd);
|
||||
|
||||
if (close(fd))
|
||||
log_error("Error closing fd %d", fd);
|
||||
|
||||
if (same < 0)
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
link_buf[len] = '\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;
|
||||
else
|
||||
same = _filemap_monitor_check_same_file(fm->fd, fd);
|
||||
|
||||
if ((fd >= 0) && close(fd))
|
||||
log_error("Error closing fd %d", fd);
|
||||
|
||||
if (same < 0)
|
||||
return 0;
|
||||
|
||||
/* 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 = (int) 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];
|
||||
}
|
||||
dm_free(regions);
|
||||
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):
|
||||
|
@ -11,7 +11,8 @@ import subprocess
|
||||
from . import cfg
|
||||
from .cmdhandler import options_to_cli_args
|
||||
import dbus
|
||||
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug
|
||||
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug,\
|
||||
add_no_notify
|
||||
import os
|
||||
import threading
|
||||
|
||||
@ -42,6 +43,10 @@ def _move_merge(interface_name, command, job_state):
|
||||
# the command always as we will be getting periodic output from them on
|
||||
# the status of the long running operation.
|
||||
command.insert(0, cfg.LVM_CMD)
|
||||
|
||||
# Instruct lvm to not register an event with us
|
||||
command = add_no_notify(command)
|
||||
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE,
|
||||
env=os.environ,
|
||||
stderr=subprocess.PIPE, close_fds=True)
|
||||
@ -59,6 +64,10 @@ def _move_merge(interface_name, command, job_state):
|
||||
(device, ignore, percentage) = line_str.split(':')
|
||||
job_state.Percent = round(
|
||||
float(percentage.strip()[:-1]), 1)
|
||||
|
||||
# While the move is in progress we need to periodically update
|
||||
# the state to reflect where everything is at.
|
||||
cfg.load()
|
||||
except ValueError:
|
||||
log_error("Trying to parse percentage which failed for %s" %
|
||||
line_str)
|
||||
|
@ -26,7 +26,7 @@ bus = None
|
||||
args = None
|
||||
|
||||
# Set to true if we are depending on external events for updates
|
||||
ee = False
|
||||
got_external_event = False
|
||||
|
||||
# Shared state variable across all processes
|
||||
run = multiprocessing.Value('i', 1)
|
||||
@ -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,25 +184,33 @@ 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():
|
||||
utils.log_debug("ExternalEvent received, disabling "
|
||||
"udev monitoring")
|
||||
# We are dependent on external events now to stay current!
|
||||
cfg.ee = True
|
||||
utils.log_debug("ExternalEvent %s" % command)
|
||||
cfg.event()
|
||||
cfg.got_external_event = True
|
||||
|
||||
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,10 +10,41 @@
|
||||
import pyudev
|
||||
import threading
|
||||
from . import cfg
|
||||
from .request import RequestEntry
|
||||
from . import utils
|
||||
|
||||
observer = None
|
||||
observer_lock = threading.RLock()
|
||||
|
||||
_udev_lock = threading.RLock()
|
||||
_udev_count = 0
|
||||
|
||||
|
||||
def udev_add():
|
||||
global _udev_count
|
||||
with _udev_lock:
|
||||
if _udev_count == 0:
|
||||
_udev_count += 1
|
||||
|
||||
# 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 udev_complete():
|
||||
global _udev_count
|
||||
with _udev_lock:
|
||||
if _udev_count > 0:
|
||||
_udev_count -= 1
|
||||
|
||||
|
||||
def _udev_event():
|
||||
utils.log_debug("Processing udev event")
|
||||
udev_complete()
|
||||
cfg.load()
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
def filter_event(action, device):
|
||||
@ -37,7 +68,7 @@ def filter_event(action, device):
|
||||
refresh = True
|
||||
|
||||
if refresh:
|
||||
cfg.event()
|
||||
udev_add()
|
||||
|
||||
|
||||
def add():
|
||||
|
@ -499,6 +499,33 @@ 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
|
||||
"""
|
||||
|
||||
# Only after we have seen an external event will be disable lvm from sending
|
||||
# us one when we call lvm
|
||||
if cfg.got_external_event:
|
||||
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
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define LVMETAD_DISABLE_REASON_LVM1 "LVM1"
|
||||
#define LVMETAD_DISABLE_REASON_DUPLICATES "DUPLICATES"
|
||||
#define LVMETAD_DISABLE_REASON_VGRESTORE "VGRESTORE"
|
||||
#define LVMETAD_DISABLE_REASON_REPAIR "REPAIR"
|
||||
|
||||
struct volume_group;
|
||||
|
||||
|
@ -203,8 +203,9 @@ struct vg_info {
|
||||
#define GLFL_DISABLE_REASON_LVM1 0x00000008
|
||||
#define GLFL_DISABLE_REASON_DUPLICATES 0x00000010
|
||||
#define GLFL_DISABLE_REASON_VGRESTORE 0x00000020
|
||||
#define GLFL_DISABLE_REASON_REPAIR 0x00000040
|
||||
|
||||
#define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_LVM1 | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE)
|
||||
#define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_REPAIR | GLFL_DISABLE_REASON_LVM1 | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE)
|
||||
|
||||
#define VGFL_INVALID 0x00000001
|
||||
|
||||
@ -2355,6 +2356,8 @@ static response set_global_info(lvmetad_state *s, request r)
|
||||
if ((reason = daemon_request_str(r, "disable_reason", NULL))) {
|
||||
if (strstr(reason, LVMETAD_DISABLE_REASON_DIRECT))
|
||||
reason_flags |= GLFL_DISABLE_REASON_DIRECT;
|
||||
if (strstr(reason, LVMETAD_DISABLE_REASON_REPAIR))
|
||||
reason_flags |= GLFL_DISABLE_REASON_REPAIR;
|
||||
if (strstr(reason, LVMETAD_DISABLE_REASON_LVM1))
|
||||
reason_flags |= GLFL_DISABLE_REASON_LVM1;
|
||||
if (strstr(reason, LVMETAD_DISABLE_REASON_DUPLICATES))
|
||||
@ -2418,8 +2421,9 @@ static response get_global_info(lvmetad_state *s, request r)
|
||||
pid = (int)daemon_request_int(r, "pid", 0);
|
||||
|
||||
if (s->flags & GLFL_DISABLE) {
|
||||
snprintf(reason, REASON_BUF_SIZE - 1, "%s%s%s%s",
|
||||
snprintf(reason, REASON_BUF_SIZE - 1, "%s%s%s%s%s",
|
||||
(s->flags & GLFL_DISABLE_REASON_DIRECT) ? LVMETAD_DISABLE_REASON_DIRECT "," : "",
|
||||
(s->flags & GLFL_DISABLE_REASON_REPAIR) ? LVMETAD_DISABLE_REASON_REPAIR "," : "",
|
||||
(s->flags & GLFL_DISABLE_REASON_LVM1) ? LVMETAD_DISABLE_REASON_LVM1 "," : "",
|
||||
(s->flags & GLFL_DISABLE_REASON_DUPLICATES) ? LVMETAD_DISABLE_REASON_DUPLICATES "," : "",
|
||||
(s->flags & GLFL_DISABLE_REASON_VGRESTORE) ? LVMETAD_DISABLE_REASON_VGRESTORE "," : "");
|
||||
|
@ -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
|
||||
|
||||
@ -488,6 +491,9 @@
|
||||
/* Define to 1 if you have the <sys/file.h> header file. */
|
||||
#undef HAVE_SYS_FILE_H
|
||||
|
||||
/* Define to 1 if you have the <sys/inotify.h> header file. */
|
||||
#undef HAVE_SYS_INOTIFY_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
@ -623,6 +629,9 @@
|
||||
/* Define to 1 to include code that uses lvmpolld. */
|
||||
#undef LVMPOLLD_SUPPORT
|
||||
|
||||
/* configure command line used */
|
||||
#undef LVM_CONFIGURE_LINE
|
||||
|
||||
/* Path to lvm binary. */
|
||||
#undef LVM_PATH
|
||||
|
||||
|
@ -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:
|
||||
|
7
lib/cache/lvmetad.c
vendored
7
lib/cache/lvmetad.c
vendored
@ -66,7 +66,7 @@ static int _log_debug_inequality(const char *name, struct dm_config_node *a, str
|
||||
log_debug_lvmetad("VG %s metadata inequality at %s / %s: %s / %s",
|
||||
name, a->key, b->key, av->v.str, bv->v.str);
|
||||
else if (a->v->type == DM_CFG_INT && b->v->type == DM_CFG_INT)
|
||||
log_debug_lvmetad("VG %s metadata inequality at %s / %s: " FMTi64 " / " FMTi64,
|
||||
log_debug_lvmetad("VG %s metadata inequality at %s / %s: " FMTd64 " / " FMTd64,
|
||||
name, a->key, b->key, av->v.i, bv->v.i);
|
||||
else
|
||||
log_debug_lvmetad("VG %s metadata inequality at %s / %s: type %d / type %d",
|
||||
@ -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)) {
|
||||
@ -2874,6 +2874,9 @@ int lvmetad_is_disabled(struct cmd_context *cmd, const char **reason)
|
||||
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_DIRECT)) {
|
||||
*reason = "the disable flag was set directly";
|
||||
|
||||
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_REPAIR)) {
|
||||
*reason = "a repair command was run";
|
||||
|
||||
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_LVM1)) {
|
||||
*reason = "LVM1 metadata was found";
|
||||
|
||||
|
@ -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));
|
||||
|
@ -128,8 +128,8 @@ int import_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
int generate_lvm1_system_id(struct cmd_context *cmd, char *s, const char *prefix)
|
||||
{
|
||||
|
||||
if (dm_snprintf(s, NAME_LEN, "%s%s%lu",
|
||||
prefix, cmd->hostname, time(NULL)) < 0) {
|
||||
if (dm_snprintf(s, NAME_LEN, "%s%s" FMTu64,
|
||||
prefix, cmd->hostname, (uint64_t)time(NULL)) < 0) {
|
||||
log_error("Generated LVM1 format system_id too long");
|
||||
return 0;
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
@ -350,7 +350,7 @@ static int _print_header(struct cmd_context *cmd, struct formatter *f,
|
||||
_utsname.version, _utsname.machine);
|
||||
if (cmd->system_id && *cmd->system_id)
|
||||
outf(f, "creation_host_system_id = \"%s\"", cmd->system_id);
|
||||
outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
|
||||
outf(f, "creation_time = " FMTu64 "\t# %s", (uint64_t)t, ctime(&t));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -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.
|
||||
*
|
||||
@ -220,19 +220,35 @@ char *lvseg_segtype_dup(struct dm_pool *mem, const struct lv_segment *seg)
|
||||
|
||||
char *lvseg_discards_dup(struct dm_pool *mem, const struct lv_segment *seg)
|
||||
{
|
||||
return dm_pool_strdup(mem, get_pool_discards_name(seg->discards));
|
||||
if (lv_is_thin_pool(seg->lv))
|
||||
return dm_pool_strdup(mem, get_pool_discards_name(seg->discards));
|
||||
|
||||
log_error("Cannot query non thin-pool segment of LV %s for discards property.",
|
||||
display_lvname(seg->lv));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *lvseg_kernel_discards_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm)
|
||||
{
|
||||
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 +1120,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 +1284,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 +1298,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 +1307,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;
|
||||
|
||||
/*
|
||||
@ -4749,6 +4773,19 @@ static int _lvresize_check(struct logical_volume *lv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lv_is_raid(lv) &&
|
||||
lp->resize == LV_REDUCE) {
|
||||
unsigned attrs;
|
||||
const struct segment_type *segtype = first_seg(lv)->segtype;
|
||||
|
||||
if (!segtype->ops->target_present ||
|
||||
!segtype->ops->target_present(lv->vg->cmd, NULL, &attrs) ||
|
||||
!(attrs & RAID_FEATURE_SHRINK)) {
|
||||
log_error("RAID module does not support shrinking.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (lp->use_policies && !lv_is_cow(lv) && !lv_is_thin_pool(lv)) {
|
||||
log_error("Policy-based resize is supported only for snapshot and thin pool volumes.");
|
||||
return 0;
|
||||
@ -5391,6 +5428,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 +5950,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 +6057,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 +6365,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 +6831,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 +6888,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 +7415,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 +7438,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 +7676,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 +7689,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 +7885,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;
|
||||
|
||||
|
@ -28,50 +28,50 @@ struct dm_config_node;
|
||||
struct dev_manager;
|
||||
|
||||
/* Feature flags */
|
||||
#define SEG_CAN_SPLIT 0x0000000000000001ULL
|
||||
#define SEG_AREAS_STRIPED 0x0000000000000002ULL
|
||||
#define SEG_AREAS_MIRRORED 0x0000000000000004ULL
|
||||
#define SEG_SNAPSHOT 0x0000000000000008ULL
|
||||
#define SEG_FORMAT1_SUPPORT 0x0000000000000010ULL
|
||||
#define SEG_VIRTUAL 0x0000000000000020ULL
|
||||
#define SEG_CANNOT_BE_ZEROED 0x0000000000000040ULL
|
||||
#define SEG_MONITORED 0x0000000000000080ULL
|
||||
#define SEG_REPLICATOR 0x0000000000000100ULL
|
||||
#define SEG_REPLICATOR_DEV 0x0000000000000200ULL
|
||||
#define SEG_RAID 0x0000000000000400ULL
|
||||
#define SEG_THIN_POOL 0x0000000000000800ULL
|
||||
#define SEG_THIN_VOLUME 0x0000000000001000ULL
|
||||
#define SEG_CACHE 0x0000000000002000ULL
|
||||
#define SEG_CACHE_POOL 0x0000000000004000ULL
|
||||
#define SEG_MIRROR 0x0000000000008000ULL
|
||||
#define SEG_ONLY_EXCLUSIVE 0x0000000000010000ULL /* In cluster only exlusive activation */
|
||||
#define SEG_CAN_ERROR_WHEN_FULL 0x0000000000020000ULL
|
||||
#define SEG_CAN_SPLIT (1ULL << 0)
|
||||
#define SEG_AREAS_STRIPED (1ULL << 1)
|
||||
#define SEG_AREAS_MIRRORED (1ULL << 2)
|
||||
#define SEG_SNAPSHOT (1ULL << 3)
|
||||
#define SEG_FORMAT1_SUPPORT (1ULL << 4)
|
||||
#define SEG_VIRTUAL (1ULL << 5)
|
||||
#define SEG_CANNOT_BE_ZEROED (1ULL << 6)
|
||||
#define SEG_MONITORED (1ULL << 7)
|
||||
#define SEG_REPLICATOR (1ULL << 8)
|
||||
#define SEG_REPLICATOR_DEV (1ULL << 9)
|
||||
#define SEG_RAID (1ULL << 10)
|
||||
#define SEG_THIN_POOL (1ULL << 11)
|
||||
#define SEG_THIN_VOLUME (1ULL << 12)
|
||||
#define SEG_CACHE (1ULL << 13)
|
||||
#define SEG_CACHE_POOL (1ULL << 14)
|
||||
#define SEG_MIRROR (1ULL << 15)
|
||||
#define SEG_ONLY_EXCLUSIVE (1ULL << 16) /* In cluster only exlusive activation */
|
||||
#define SEG_CAN_ERROR_WHEN_FULL (1ULL << 17)
|
||||
|
||||
#define SEG_RAID0 0x0000000000040000ULL
|
||||
#define SEG_RAID0_META 0x0000000000080000ULL
|
||||
#define SEG_RAID1 0x0000000000100000ULL
|
||||
#define SEG_RAID10_NEAR 0x0000000000200000ULL
|
||||
#define SEG_RAID0 (1ULL << 18)
|
||||
#define SEG_RAID0_META (1ULL << 19)
|
||||
#define SEG_RAID1 (1ULL << 20)
|
||||
#define SEG_RAID10_NEAR (1ULL << 21)
|
||||
#define SEG_RAID10 SEG_RAID10_NEAR
|
||||
#define SEG_RAID4 0x0000000000400000ULL
|
||||
#define SEG_RAID5_N 0x0000000000800000ULL
|
||||
#define SEG_RAID5_LA 0x0000000001000000ULL
|
||||
#define SEG_RAID5_LS 0x0000000002000000ULL
|
||||
#define SEG_RAID5_RA 0x0000000004000000ULL
|
||||
#define SEG_RAID5_RS 0x0000000008000000ULL
|
||||
#define SEG_RAID4 (1ULL << 22)
|
||||
#define SEG_RAID5_N (1ULL << 23)
|
||||
#define SEG_RAID5_LA (1ULL << 24)
|
||||
#define SEG_RAID5_LS (1ULL << 25)
|
||||
#define SEG_RAID5_RA (1ULL << 26)
|
||||
#define SEG_RAID5_RS (1ULL << 27)
|
||||
#define SEG_RAID5 SEG_RAID5_LS
|
||||
#define SEG_RAID6_NC 0x0000000010000000ULL
|
||||
#define SEG_RAID6_NR 0x0000000020000000ULL
|
||||
#define SEG_RAID6_ZR 0x0000000040000000ULL
|
||||
#define SEG_RAID6_LA_6 0x0000000080000000ULL
|
||||
#define SEG_RAID6_LS_6 0x0000000100000000ULL
|
||||
#define SEG_RAID6_RA_6 0x0000000200000000ULL
|
||||
#define SEG_RAID6_RS_6 0x0000000400000000ULL
|
||||
#define SEG_RAID6_N_6 0x0000000800000000ULL
|
||||
#define SEG_RAID6_NC (1ULL << 28)
|
||||
#define SEG_RAID6_NR (1ULL << 29)
|
||||
#define SEG_RAID6_ZR (1ULL << 30)
|
||||
#define SEG_RAID6_LA_6 (1ULL << 31)
|
||||
#define SEG_RAID6_LS_6 (1ULL << 32)
|
||||
#define SEG_RAID6_RA_6 (1ULL << 33)
|
||||
#define SEG_RAID6_RS_6 (1ULL << 34)
|
||||
#define SEG_RAID6_N_6 (1ULL << 35)
|
||||
#define SEG_RAID6 SEG_RAID6_ZR
|
||||
|
||||
#define SEG_STRIPED_TARGET 0x0000008000000000ULL
|
||||
#define SEG_STRIPED_TARGET (1ULL << 39)
|
||||
|
||||
#define SEG_UNKNOWN 0x8000000000000000ULL
|
||||
#define SEG_UNKNOWN (1ULL << 63)
|
||||
|
||||
#define SEG_TYPE_NAME_LINEAR "linear"
|
||||
#define SEG_TYPE_NAME_STRIPED "striped"
|
||||
@ -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 /* FIXME ((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,8 @@ 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_SHRINK (1U << 4) /* version 1.9.0 */
|
||||
#define RAID_FEATURE_RESHAPE (1U << 5) /* version 1.10.1 */
|
||||
|
||||
#ifdef RAID_INTERNAL
|
||||
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
|
||||
@ -308,6 +316,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 },
|
||||
|
@ -100,9 +100,10 @@ int attach_thin_external_origin(struct lv_segment *seg,
|
||||
external_lv->status &= ~LVM_WRITE;
|
||||
}
|
||||
|
||||
// TODO: should we mark even origin read-only ?
|
||||
//if (lv_is_cache(external_lv)) /* read-only corigin of cache LV */
|
||||
// seg_lv(first_seg(external_lv), 0)->status &= ~LVM_WRITE;
|
||||
/* FIXME Mark origin read-only?
|
||||
if (lv_is_cache(external_lv)) // read-only corigin of cache LV
|
||||
seg_lv(first_seg(external_lv), 0)->status &= ~LVM_WRITE;
|
||||
*/
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -547,19 +548,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 +584,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 +650,21 @@ 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 == 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;
|
||||
}
|
||||
|
166
lib/raid/raid.c
166
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,33 @@ 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, 9, 0, RAID_FEATURE_SHRINK, "shrinking" },
|
||||
{ 1, 10, 1, RAID_FEATURE_RESHAPE, "reshaping" },
|
||||
};
|
||||
|
||||
static int _raid_checked = 0;
|
||||
@ -438,13 +496,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";
|
||||
@ -1007,7 +1008,7 @@ static int _translate_time_items(struct dm_report *rh, struct time_info *info,
|
||||
dm_pool_free(info->mem, info->ti_list);
|
||||
info->ti_list = NULL;
|
||||
|
||||
if (dm_snprintf(buf, sizeof(buf), "@%ld:@%ld", t1, t2) == -1) {
|
||||
if (dm_snprintf(buf, sizeof(buf), "@" FMTd64 ":@" FMTd64, (int64_t)t1, (int64_t)t2) == -1) {
|
||||
log_error("_translate_time_items: dm_snprintf failed");
|
||||
return 0;
|
||||
}
|
||||
@ -1062,10 +1063,10 @@ static void *_lv_time_handler_get_dynamic_value(struct dm_report *rh,
|
||||
struct dm_pool *mem,
|
||||
const char *data_in)
|
||||
{
|
||||
time_t t1, t2;
|
||||
int64_t t1, t2;
|
||||
time_t *result;
|
||||
|
||||
if (sscanf(data_in, "@%ld:@%ld", &t1, &t2) != 2) {
|
||||
if (sscanf(data_in, "@" FMTd64 ":@" FMTd64, &t1, &t2) != 2) {
|
||||
log_error("Failed to get value for parsed time specification.");
|
||||
return NULL;
|
||||
}
|
||||
@ -1075,8 +1076,8 @@ static void *_lv_time_handler_get_dynamic_value(struct dm_report *rh,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result[0] = t1;
|
||||
result[1] = t2;
|
||||
result[0] = (time_t) t1; /* Validate range for 32b arch ? */
|
||||
result[1] = (time_t) t2;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -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 : (uint64_t) 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 */
|
||||
@ -1731,9 +1734,11 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
|
||||
!child->callback(child, DM_NODE_CALLBACK_DEACTIVATED,
|
||||
child->callback_data))
|
||||
stack;
|
||||
// FIXME: We need to let lvremove pass,
|
||||
// so for now deactivation ignores check result
|
||||
//r = 0; // FIXME: _node_clear_table() without callback ?
|
||||
/* FIXME Deactivation must currently ignore failure
|
||||
* here so that lvremove can continue: we need an
|
||||
* alternative way to handle this state without
|
||||
* setting r=0. Or better, skip calling thin_check
|
||||
* entirely if the device is about to be removed. */
|
||||
|
||||
if (dm_tree_node_num_children(child, 0) &&
|
||||
!_dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, level + 1))
|
||||
@ -2353,16 +2358,66 @@ 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get target version (major, minor and patchlevel) for @target_name
|
||||
*
|
||||
* FIXME: this function is derived from liblvm.
|
||||
* Integrate with move of liblvm functions
|
||||
* to libdm in future library layer purge
|
||||
* (e.g. expose as API dm_target_version()?)
|
||||
*/
|
||||
static int _target_version(const char *target_name, uint32_t *maj,
|
||||
uint32_t *min, uint32_t *patchlevel)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
struct dm_versions *target, *last_target = NULL;
|
||||
|
||||
log_very_verbose("Getting target version for %s", target_name);
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_debug_activation("Failed to get %s target versions", target_name);
|
||||
/* Assume this was because LIST_VERSIONS isn't supported */
|
||||
maj = min = patchlevel = 0;
|
||||
r = 1;
|
||||
|
||||
} else
|
||||
for (target = dm_task_get_versions(dmt);
|
||||
target != last_target;
|
||||
last_target = target, target = (struct dm_versions *)((char *) target + target->next))
|
||||
if (!strcmp(target_name, target->name)) {
|
||||
*maj = target->version[0];
|
||||
*min = target->version[1];
|
||||
*patchlevel = target->version[2];
|
||||
log_very_verbose("Found %s target "
|
||||
"v%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".",
|
||||
target_name, *maj, *min, *patchlevel);
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -2373,61 +2428,129 @@ 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;
|
||||
uint32_t maj, min, patchlevel;
|
||||
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;
|
||||
|
||||
EMIT_PARAMS(pos, "%s %d %u", _dm_segtypes[type].target,
|
||||
EMIT_PARAMS(pos, "%s %d %u",
|
||||
type == SEG_RAID10 ? "raid10" : _dm_segtypes[type].target,
|
||||
param_count, seg->stripe_size);
|
||||
|
||||
if (seg->flags & DM_NOSYNC)
|
||||
EMIT_PARAMS(pos, " nosync");
|
||||
else if (seg->flags & DM_FORCESYNC)
|
||||
EMIT_PARAMS(pos, " sync");
|
||||
if (!_target_version("raid", &maj, &min, &patchlevel))
|
||||
return_0;
|
||||
|
||||
if (seg->region_size)
|
||||
EMIT_PARAMS(pos, " region_size %u", seg->region_size);
|
||||
/*
|
||||
* Target version prior to 1.9.0 and >= 1.11.0 emit
|
||||
* order of parameters as of kernel target documentation
|
||||
*/
|
||||
if (maj > 1 || (maj == 1 && (min < 9 || min >= 11))) {
|
||||
if (seg->flags & DM_NOSYNC)
|
||||
EMIT_PARAMS(pos, " nosync");
|
||||
else if (seg->flags & DM_FORCESYNC)
|
||||
EMIT_PARAMS(pos, " sync");
|
||||
|
||||
for (i = 0; i < (seg->area_count / 2); i++)
|
||||
if (seg->rebuilds & (1ULL << i))
|
||||
EMIT_PARAMS(pos, " rebuild %u", i);
|
||||
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->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);
|
||||
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))
|
||||
EMIT_PARAMS(pos, " write_mostly %u", 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);
|
||||
if (seg->writebehind)
|
||||
EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
|
||||
|
||||
if (seg->region_size)
|
||||
EMIT_PARAMS(pos, " region_size %u", seg->region_size);
|
||||
|
||||
if (seg->data_copies > 1 && type == SEG_RAID10)
|
||||
EMIT_PARAMS(pos, " raid10_copies %u", seg->data_copies);
|
||||
|
||||
if (seg->delta_disks)
|
||||
EMIT_PARAMS(pos, " delta_disks %d", seg->delta_disks);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Target version >= 1.9.0 && < 1.11.0 had a table line parameter ordering flaw */
|
||||
} else {
|
||||
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)
|
||||
EMIT_PARAMS(pos, " sync");
|
||||
|
||||
if (seg->region_size)
|
||||
EMIT_PARAMS(pos, " region_size %u", seg->region_size);
|
||||
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
|
||||
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 +2590,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";
|
||||
@ -2690,7 +2818,7 @@ static int _emit_segment(struct dm_task *dmt, uint32_t major, uint32_t minor,
|
||||
struct load_segment *seg, uint64_t *seg_start)
|
||||
{
|
||||
char *params;
|
||||
size_t paramsize = 4096;
|
||||
size_t paramsize = 4096; /* FIXME: too small for long RAID lines when > 64 devices supported */
|
||||
int ret;
|
||||
|
||||
do {
|
||||
@ -3267,8 +3395,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 +3426,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 +3479,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 +3551,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 +4110,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 +4126,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;
|
||||
|
||||
@ -675,10 +678,10 @@ static void _check_group_regions_present(struct dm_stats *dms,
|
||||
|
||||
group_id = i = dm_bit_get_first(regions);
|
||||
|
||||
for (; i > 0; dm_bit_get_next(regions, i))
|
||||
for (; i > 0; i = dm_bit_get_next(regions, i))
|
||||
if (!_stats_region_present(&dms->regions[i])) {
|
||||
log_warn("Group descriptor " FMTi64 " contains "
|
||||
"non-existent region_id " FMTi64 ".",
|
||||
log_warn("Group descriptor " FMTd64 " contains "
|
||||
"non-existent region_id " FMTd64 ".",
|
||||
group_id, i);
|
||||
dm_bit_clear(regions, i);
|
||||
}
|
||||
@ -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) {
|
||||
@ -4175,21 +4181,23 @@ int dm_stats_get_group_descriptor(const struct dm_stats *dms,
|
||||
* Resize the group bitmap corresponding to group_id so that it can
|
||||
* contain at least num_regions members.
|
||||
*/
|
||||
static int _stats_resize_group(struct dm_stats_group *group, int num_regions)
|
||||
static int _stats_resize_group(struct dm_stats_group *group,
|
||||
uint64_t num_regions)
|
||||
{
|
||||
int last_bit = dm_bit_get_last(group->regions);
|
||||
uint64_t last_bit = dm_bit_get_last(group->regions);
|
||||
dm_bitset_t new, old;
|
||||
|
||||
if (last_bit >= num_regions) {
|
||||
log_error("Cannot resize group bitmap to %d with bit %d set.",
|
||||
num_regions, last_bit);
|
||||
log_error("Cannot resize group bitmap to " FMTu64
|
||||
" with bit " FMTu64 " set.", num_regions, last_bit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Resizing group bitmap from %d to %d (last_bit: %d).",
|
||||
log_very_verbose("Resizing group bitmap from " FMTu64
|
||||
" to " FMTu64 " (last_bit: " FMTu64 ").",
|
||||
group->regions[0], num_regions, last_bit);
|
||||
|
||||
new = dm_bitset_create(NULL, num_regions);
|
||||
new = dm_bitset_create(NULL, (unsigned) num_regions);
|
||||
if (!new) {
|
||||
log_error("Could not allocate memory for new group bitmap.");
|
||||
return 0;
|
||||
@ -4211,7 +4219,7 @@ static int _stats_group_file_regions(struct dm_stats *dms, uint64_t *region_ids,
|
||||
dm_bitset_t regions = dm_bitset_create(NULL, dms->nr_regions);
|
||||
uint64_t i, group_id = DM_STATS_GROUP_NOT_PRESENT;
|
||||
char *members = NULL;
|
||||
int buflen;
|
||||
size_t buflen;
|
||||
|
||||
if (!regions) {
|
||||
log_error("Cannot map file: failed to allocate group bitmap.");
|
||||
@ -4395,10 +4403,14 @@ static struct _extent *_stats_get_extents_for_file(struct dm_pool *mem, int fd,
|
||||
unsigned long flags = 0;
|
||||
uint64_t *buf;
|
||||
|
||||
/* grow temporary extent table in the pool */
|
||||
if (!dm_pool_begin_object(mem, sizeof(*extents)))
|
||||
return NULL;
|
||||
|
||||
buf = dm_zalloc(STATS_FIE_BUF_LEN);
|
||||
if (!buf) {
|
||||
log_error("Could not allocate memory for FIEMAP buffer.");
|
||||
return NULL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* initialise pointers into the ioctl buffer. */
|
||||
@ -4409,10 +4421,6 @@ static struct _extent *_stats_get_extents_for_file(struct dm_pool *mem, int fd,
|
||||
*count = (STATS_FIE_BUF_LEN - sizeof(*fiemap))
|
||||
/ sizeof(struct fiemap_extent);
|
||||
|
||||
/* grow temporary extent table in the pool */
|
||||
if (!dm_pool_begin_object(mem, sizeof(*extents)))
|
||||
return NULL;
|
||||
|
||||
flags = FIEMAP_FLAG_SYNC;
|
||||
|
||||
do {
|
||||
@ -4466,7 +4474,7 @@ bad:
|
||||
#define MATCH_EXTENT(e, s, l) \
|
||||
(((e).start == (s)) && ((e).len == (l)))
|
||||
|
||||
static struct _extent *_find_extent(size_t nr_extents, struct _extent *extents,
|
||||
static struct _extent *_find_extent(uint64_t nr_extents, struct _extent *extents,
|
||||
uint64_t start, uint64_t len)
|
||||
{
|
||||
size_t i;
|
||||
@ -4503,8 +4511,9 @@ static int _stats_unmap_regions(struct dm_stats *dms, uint64_t group_id,
|
||||
{
|
||||
struct dm_stats_region *region = NULL;
|
||||
struct dm_stats_group *group = NULL;
|
||||
int64_t nr_kept, nr_old, i;
|
||||
uint64_t nr_kept, nr_old;
|
||||
struct _extent ext;
|
||||
int64_t i;
|
||||
|
||||
group = &dms->groups[group_id];
|
||||
|
||||
@ -4534,8 +4543,9 @@ static int _stats_unmap_regions(struct dm_stats *dms, uint64_t group_id,
|
||||
ext.id = i;
|
||||
nr_kept++;
|
||||
|
||||
dm_pool_grow_object(mem, &ext,
|
||||
sizeof(ext));
|
||||
if (!dm_pool_grow_object(mem, &ext, sizeof(ext)))
|
||||
goto out;
|
||||
|
||||
log_very_verbose("Kept region " FMTu64, i);
|
||||
} else {
|
||||
|
||||
@ -4557,12 +4567,12 @@ static int _stats_unmap_regions(struct dm_stats *dms, uint64_t group_id,
|
||||
log_error("Could not finalize region extent table.");
|
||||
goto out;
|
||||
}
|
||||
log_very_verbose("Kept " FMTi64 " of " FMTi64 " old extents",
|
||||
log_very_verbose("Kept " FMTd64 " of " FMTd64 " old extents",
|
||||
nr_kept, nr_old);
|
||||
log_very_verbose("Found " FMTu64 " new extents",
|
||||
*count - nr_kept);
|
||||
|
||||
return nr_kept;
|
||||
return (int) nr_kept;
|
||||
out:
|
||||
dm_pool_abandon_object(mem);
|
||||
return -1;
|
||||
@ -4585,15 +4595,15 @@ static uint64_t *_stats_map_file_regions(struct dm_stats *dms, int fd,
|
||||
uint64_t *count, int *regroup)
|
||||
{
|
||||
struct _extent *extents = NULL, *old_extents = NULL;
|
||||
uint64_t *regions = NULL, fail_region;
|
||||
uint64_t *regions = NULL, fail_region, i, num_bits;
|
||||
struct dm_stats_group *group = NULL;
|
||||
struct dm_pool *extent_mem = NULL;
|
||||
struct _extent *old_ext;
|
||||
char *hist_arg = NULL;
|
||||
int update, num_bits;
|
||||
struct statfs fsbuf;
|
||||
int64_t nr_kept = 0, i;
|
||||
int64_t nr_kept = 0;
|
||||
struct stat buf;
|
||||
int update;
|
||||
|
||||
update = _stats_group_id_present(dms, group_id);
|
||||
|
||||
@ -4678,9 +4688,10 @@ static uint64_t *_stats_map_file_regions(struct dm_stats *dms, int fd,
|
||||
*/
|
||||
for (i = 0; i < *count; i++) {
|
||||
if (update) {
|
||||
if ((old_ext = _find_extent(nr_kept, old_extents,
|
||||
extents[i].start,
|
||||
extents[i].len))) {
|
||||
if ((old_ext = _find_extent((uint64_t) nr_kept,
|
||||
old_extents,
|
||||
extents[i].start,
|
||||
extents[i].len))) {
|
||||
regions[i] = old_ext->id;
|
||||
continue;
|
||||
}
|
||||
@ -4736,7 +4747,8 @@ out_remove:
|
||||
* single list operation and call _stats_delete_region() directly
|
||||
* to avoid a @stats_list ioctl and list parsing for each region.
|
||||
*/
|
||||
dm_stats_list(dms, NULL);
|
||||
if (!dm_stats_list(dms, NULL))
|
||||
goto out;
|
||||
|
||||
fail_region = i;
|
||||
_stats_cleanup_region_ids(dms, regions, fail_region);
|
||||
@ -4769,7 +4781,8 @@ uint64_t *dm_stats_create_regions_from_fd(struct dm_stats *dms, int fd,
|
||||
}
|
||||
|
||||
if (!(regions = _stats_map_file_regions(dms, fd, bounds, precise,
|
||||
-1, &count, ®roup)))
|
||||
DM_STATS_GROUP_NOT_PRESENT,
|
||||
&count, ®roup)))
|
||||
return NULL;
|
||||
|
||||
if (!group)
|
||||
@ -4874,9 +4887,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 +4905,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);
|
||||
|
||||
|
@ -566,7 +566,21 @@ static lv_create_params_t _lvm_lv_params_create_thin_pool(vg_t vg,
|
||||
|
||||
if (lvcp) {
|
||||
lvcp->vg = vg;
|
||||
lvcp->lvp.discards = (thin_discards_t) discard;
|
||||
switch (discard) {
|
||||
case LVM_THIN_DISCARDS_IGNORE:
|
||||
lvcp->lvp.discards = THIN_DISCARDS_IGNORE;
|
||||
break;
|
||||
case LVM_THIN_DISCARDS_NO_PASSDOWN:
|
||||
lvcp->lvp.discards = THIN_DISCARDS_NO_PASSDOWN;
|
||||
break;
|
||||
case LVM_THIN_DISCARDS_PASSDOWN:
|
||||
lvcp->lvp.discards = THIN_DISCARDS_PASSDOWN;
|
||||
break;
|
||||
default:
|
||||
log_error("Invalid discard argument %d for thin pool creation.", discard);
|
||||
return NULL;
|
||||
}
|
||||
lvcp->lvp.zero_new_blocks = THIN_ZERO_YES;
|
||||
|
||||
if (chunk_size)
|
||||
lvcp->lvp.chunk_size = chunk_size;
|
||||
|
11
make.tmpl.in
11
make.tmpl.in
@ -13,7 +13,7 @@
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
SHELL = /bin/sh
|
||||
SHELL = @SHELL@
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
@ -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,8 +413,10 @@ 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 $@
|
||||
$(CC) -c $(INCLUDES) $(DEFS) $(DEFS_$@) $(WFLAGS) $(WCFLAGS) $(CFLAGS) $(CFLAGS_$@) $< -o $@
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) -c $(INCLUDES) $(DEFS) $(WFLAGS) $(CXXFLAGS) $(CXXFLAGS_$@) $< -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
|
168
man/Makefile.in
168
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.
|
||||
#
|
||||
@ -19,6 +19,7 @@ top_builddir = @top_builddir@
|
||||
FSADMMAN = fsadm.8
|
||||
BLKDEACTIVATEMAN = blkdeactivate.8
|
||||
DMEVENTDMAN = dmeventd.8
|
||||
DMFILEMAPDMAN = dmfilemapd.8
|
||||
LVMETADMAN = lvmetad.8
|
||||
LVMPOLLDMAN = lvmpolld.8
|
||||
LVMLOCKDMAN = lvmlockd.8 lvmlockctl.8
|
||||
@ -31,20 +32,20 @@ LVMRAIDMAN = lvmraid.7
|
||||
|
||||
MAN5=lvm.conf.5
|
||||
MAN7=lvmsystemid.7 lvmreport.7
|
||||
MAN8=lvm.8 lvmconf.8 lvmdump.8
|
||||
MAN8=lvm.8 lvmconf.8 lvmdump.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
|
||||
MAN8SO=lvm-config.8 lvm-dumpconfig.8
|
||||
MAN8DM=dmsetup.8 dmstats.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"
|
||||
@ -56,7 +57,7 @@ endif
|
||||
|
||||
ifeq ($(MAN_ALL),"yes")
|
||||
MAN8+=$(FSADMMAN) $(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN)
|
||||
MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN)
|
||||
MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN) $(DMFILEMAPDMAN)
|
||||
MAN8CLUSTER+=$(CLVMDMAN) $(CMIRRORDMAN)
|
||||
MAN7+=$(LVMCACHEMAN) $(LVMTHINMAN) $(LVMRAIDMAN)
|
||||
else
|
||||
@ -88,6 +89,10 @@ else
|
||||
MAN8DM+=$(DMEVENTDMAN)
|
||||
endif
|
||||
|
||||
ifeq ("@DMFILEMAPD@", "yes")
|
||||
MAN8DM+=$(DMFILEMAPDMAN)
|
||||
endif
|
||||
|
||||
ifneq ("@CLVMD@", "none")
|
||||
MAN8CLUSTER+=$(CLVMDMAN)
|
||||
endif
|
||||
@ -113,46 +118,123 @@ MAN5DIR=$(mandir)/man5
|
||||
MAN7DIR=$(mandir)/man7
|
||||
MAN8DIR=$(mandir)/man8
|
||||
|
||||
MANGENERATOR=$(top_builddir)/tools/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) $(MAN8SO) $(MAN8:%.8=%.8_gen) $(MAN8CLUSTER) \
|
||||
$(MAN8SYSTEMD_GENERATORS) $(MAN8DM) $(TESTMAN)
|
||||
DISTCLEAN_TARGETS+=$(FSADMMAN) $(BLKDEACTIVATEMAN) $(DMEVENTDMAN) \
|
||||
$(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(CLVMDMAN) $(CMIRRORDMAN) \
|
||||
$(LVMCACHEMAN) $(LVMTHINMAN) $(LVMDBUSDMAN) $(LVMRAIDMAN)
|
||||
$(LVMCACHEMAN) $(LVMTHINMAN) $(LVMDBUSDMAN) $(LVMRAIDMAN) \
|
||||
$(DMFILEMAPDMAN)
|
||||
|
||||
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) $(MAN8SO) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS)
|
||||
|
||||
all_man: man
|
||||
|
||||
$(MAN5) $(MAN7) $(MAN8) $(MAN8GEN) $(MAN8DM) $(MAN8CLUSTER): Makefile
|
||||
$(MAN5) $(MAN7) $(MAN8) $(MAN8SO) $(MAN8DM) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS): Makefile
|
||||
|
||||
Makefile: Makefile.in
|
||||
@:
|
||||
# Test whether or not the man page generator works
|
||||
$(TESTMAN): $(MANGENERATOR) Makefile
|
||||
- $(MANGENERATOR) --primary lvmconfig > $@
|
||||
|
||||
%: %.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
|
||||
SEE_ALSO=$(srcdir)/see_also.end
|
||||
|
||||
man-generator:
|
||||
$(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;
|
||||
.PRECIOUS: %.8_gen
|
||||
|
||||
$(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 > $@
|
||||
%.8_gen: $(srcdir)/%.8_des $(srcdir)/%.8_end $(MANGENERATOR) $(TESTMAN)
|
||||
( \
|
||||
if [ ! -s $(TESTMAN) ] ; then \
|
||||
echo "Copying pre-generated template $@" ; \
|
||||
else \
|
||||
echo "Generating template $@" ; \
|
||||
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)+" \
|
||||
-e "s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+" \
|
||||
-e "s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+" \
|
||||
-e "s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+" \
|
||||
-e "s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+" \
|
||||
-e "s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+" \
|
||||
-e "s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+" \
|
||||
-e "s+#CLVMD_PATH#+/data/lvmtest/usr/sbin/clvmd+" \
|
||||
-e "s+#LVM_PATH#+/data/lvmtest/sbin/lvm+" \
|
||||
-e "s+#DEFAULT_RUN_DIR#+/var/run/lvm+" \
|
||||
-e "s+#DEFAULT_PID_DIR#+/var/run+" \
|
||||
-e "s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+" \
|
||||
-e "s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+" $< > $@
|
||||
endef
|
||||
|
||||
# Escape any '-':
|
||||
#
|
||||
# - multiple (>= 2)
|
||||
# - in ' -'
|
||||
# - in (cache|thin)-*
|
||||
# - in ranges
|
||||
# - in "$vg-$lv"
|
||||
# - in middle of options (e.g. '--use-policies')
|
||||
# - in symbolic use (e.g. '->')
|
||||
# - in single one in '\\f.-'
|
||||
define ESCAPEHYPHENS
|
||||
$(SED) -i -e "s+\([^\\]\)-\{7\}+\1\\\-\\\-\\\-\\\-\\\-\\\-\\\-+g" \
|
||||
-e "s+\([^\\]\)-\{6\}+\1\\\-\\\-\\\-\\\-\\\-\\\-+g" \
|
||||
-e "s+\([^\\]\)-\{5\}+\1\\\-\\\-\\\-\\\-\\\-+g" \
|
||||
-e "s+\([^\\]\)-\{4\}+\1\\\-\\\-\\\-\\\-+g" \
|
||||
-e "s+\([^\\]\)-\{3\}+\1\\\-\\\-\\\-+g" \
|
||||
-e "s+\([^\\]\)-\{2\}+\1\\\-\\\-+g" \
|
||||
-e "s+^-\{2\}+\\\-\\\-+g" \
|
||||
-e "s+ -\([[:alnum:]]\)+ \\\-\1+g" \
|
||||
-e "s+\(cache\)-\([[:alpha:]]\{1,\}\)+\1\\\-\2+g" \
|
||||
-e "s+\(thin\)-\([[:alpha:]]\{1,\}\)+\1\\\-\2+g" \
|
||||
-e "s+\([ :\[][[:alnum:]]\{1,\}\)-\([[:alnum:]]\{1,\}[[ ]\)+\1\\\-\2+g" \
|
||||
-e "s+\([[:alnum:]]\{2,\}\)-\([[:alnum:]]\{2,\}\)-\([[:alnum:]]\{2,\}\)+\1\\\-\2\\\-\3+g" \
|
||||
-e "s+\([[:alnum:]]\{2,\}\)-\([[:alnum:]]\{2,\}\)+\1\\\-\2+g" \
|
||||
-e "s+\(<\)-+\1\\\-+g" \
|
||||
-e "s+[^\\]-\(>\)+\\\-\1+g" \
|
||||
-e "s+\(\\\f.\)-\([^-]\)+\1\\\-\2+g" \
|
||||
-e "s+\([[:digit:]]\{4\}\).*-\([[:digit:]]\{2\}\).*-\([[:digit:]]\{2\}\)+\1-\2-\3+g" $@
|
||||
endef
|
||||
|
||||
%.5: $(srcdir)/%.5_main
|
||||
$(SUBSTVARS)
|
||||
$(ESCAPEHYPHENS)
|
||||
|
||||
%.7: $(srcdir)/%.7_main
|
||||
$(SUBSTVARS)
|
||||
$(ESCAPEHYPHENS)
|
||||
|
||||
%.8: $(srcdir)/%.8_main
|
||||
$(SUBSTVARS)
|
||||
$(ESCAPEHYPHENS)
|
||||
|
||||
%.8: %.8_gen
|
||||
$(SUBSTVARS)
|
||||
$(ESCAPEHYPHENS)
|
||||
|
||||
lvm-config.8 lvm-dumpconfig.8: lvmconfig.8
|
||||
echo ".so $<" > $@
|
||||
|
||||
install_man5: $(MAN5)
|
||||
$(INSTALL) -d $(MAN5DIR)
|
||||
@ -162,10 +244,9 @@ install_man7: $(MAN7)
|
||||
$(INSTALL) -d $(MAN7DIR)
|
||||
$(INSTALL_DATA) $(MAN7) $(MAN7DIR)/
|
||||
|
||||
install_man8: $(MAN8) $(MAN8GEN)
|
||||
install_man8: $(MAN8) $(MAN8SO)
|
||||
$(INSTALL) -d $(MAN8DIR)
|
||||
$(INSTALL_DATA) $(MAN8) $(MAN8DIR)/
|
||||
$(INSTALL_DATA) $(MAN8GEN) $(MAN8DIR)/
|
||||
$(INSTALL_DATA) $(MAN8) $(MAN8SO) $(MAN8DIR)/
|
||||
|
||||
install_lvm2: install_man5 install_man7 install_man8
|
||||
|
||||
@ -179,10 +260,19 @@ install_device-mapper: $(MAN8DM)
|
||||
$(INSTALL) -d $(MAN8DIR)
|
||||
$(INSTALL_DATA) $(MAN8DM) $(MAN8DIR)/
|
||||
|
||||
install_systemd_generators: $(MAN8SYSTEMD_GENERATORS)
|
||||
install_systemdgenerators: $(MAN8SYSTEMD_GENERATORS)
|
||||
$(INSTALL) -d $(MAN8DIR)
|
||||
$(INSTALL_DATA) $(MAN8SYSTEMD_GENERATORS) $(MAN8DIR)/
|
||||
|
||||
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_gen > $(srcdir)/$$CMD.8_pregen ; \
|
||||
done
|
||||
|
||||
generate: pregenerated_man
|
||||
|
@ -1,105 +0,0 @@
|
||||
.TH "BLKDEACTIVATE" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
|
||||
.SH "NAME"
|
||||
blkdeactivate \(em utility to deactivate block devices
|
||||
.SH SYNOPSIS
|
||||
.B blkdeactivate
|
||||
.RB [ \-d \ \fIdm_options\fP ]
|
||||
.RB [ \-e ]
|
||||
.RB [ \-h ]
|
||||
.RB [ \-l \ \fIlvm_options\fP ]
|
||||
.RB [ \-m \ \fImpath_options\fP ]
|
||||
.RB [ \-u ]
|
||||
.RB [ \-v ]
|
||||
.RI [ device ]
|
||||
.SH DESCRIPTION
|
||||
blkdeactivate utility deactivates block devices. If a device
|
||||
is mounted, the utility can 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
|
||||
using the \fBlvm\fP(8) command, the rest of device-mapper
|
||||
based devices are handled using the \fBdmsetup\fP(8) command.
|
||||
MD devices are handled using the \fBmdadm\fP(8) command.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-d ", " \-\-dmoption \ \fIdm_options\fP
|
||||
Comma separated list of device-mapper specific options.
|
||||
Accepted \fBdmsetup\fP(8) options are:
|
||||
.RS
|
||||
.IP \fIretry\fP
|
||||
Retry removal several times in case of failure.
|
||||
.IP \fIforce\fP
|
||||
Force device removal.
|
||||
.RE
|
||||
.TP
|
||||
.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.
|
||||
.TP
|
||||
.BR \-h ", " \-\-help
|
||||
Display the help text.
|
||||
.TP
|
||||
.BR \-l ", " \-\-lvmoption \ \fIlvm_options\fP
|
||||
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.
|
||||
.RE
|
||||
.TP
|
||||
.BR \-m ", " \-\-mpathoption \ \fImpath_options\fP
|
||||
Comma separated list of device-mapper multipath specific options:
|
||||
.RS
|
||||
.IP \fIdisablequeueing\fP
|
||||
Disable queueing on all multipath devices first before deactivation.
|
||||
This avoids a situation where blkdeactivate may end up waiting if
|
||||
all paths are unavailable for any underlying device-mapper multipath
|
||||
device.
|
||||
.RE
|
||||
.TP
|
||||
.BR \-u ", " \-\-umount
|
||||
Unmount a mounted device before trying to deactivate it.
|
||||
Without this option used, a device that is mounted is not deactivated.
|
||||
.TP
|
||||
.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
|
||||
.B blkdeactivate
|
||||
|
||||
Deactivate all supported block devices found in the system. If a device
|
||||
is mounted, unmount it first if possible.
|
||||
.sp
|
||||
.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
|
||||
.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
|
||||
Volume Group at once when processing an LVM Logical Volume.
|
||||
.sp
|
||||
.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
|
||||
.B blkdeactivate \-d force,retry
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR dmsetup (8),
|
||||
.BR lsblk (8),
|
||||
.BR lvm (8),
|
||||
.BR mdadm (8),
|
||||
.BR multipathd (8),
|
||||
.BR umount (8)
|
114
man/blkdeactivate.8_main
Normal file
114
man/blkdeactivate.8_main
Normal file
@ -0,0 +1,114 @@
|
||||
.TH "BLKDEACTIVATE" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
|
||||
.SH "NAME"
|
||||
blkdeactivate \(em utility to deactivate block devices
|
||||
.SH SYNOPSIS
|
||||
.B blkdeactivate
|
||||
.RB [ -d \ \fIdm_options\fP ]
|
||||
.RB [ -e ]
|
||||
.RB [ -h ]
|
||||
.RB [ -l \ \fIlvm_options\fP ]
|
||||
.RB [ -m \ \fImpath_options\fP ]
|
||||
.RB [ -u ]
|
||||
.RB [ -v ]
|
||||
.RI [ device ]
|
||||
.SH DESCRIPTION
|
||||
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
|
||||
using the \fBlvm\fP(8) command, the rest of device-mapper
|
||||
based devices are handled using the \fBdmsetup\fP(8) command.
|
||||
MD devices are handled using the \fBmdadm\fP(8) command.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR -d ", " --dmoption \ \fIdm_options\fP
|
||||
Comma separated list of device-mapper specific options.
|
||||
Accepted \fBdmsetup\fP(8) options are:
|
||||
.RS
|
||||
.IP \fIretry\fP
|
||||
Retry removal several times in case of failure.
|
||||
.IP \fIforce\fP
|
||||
Force device removal.
|
||||
.RE
|
||||
.TP
|
||||
.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 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:
|
||||
.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 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:
|
||||
.RS
|
||||
.IP \fIdisablequeueing\fP
|
||||
Disable queueing on all multipath devices before deactivation.
|
||||
This avoids a situation where blkdeactivate may end up waiting if
|
||||
all the paths are unavailable for any underlying device-mapper multipath
|
||||
device.
|
||||
.RE
|
||||
.TP
|
||||
.BR -u ", " --umount
|
||||
Unmount a mounted device before trying to deactivate it.
|
||||
Without this option used, a device that is mounted is not deactivated.
|
||||
.TP
|
||||
.BR -v ", " --verbose
|
||||
Run in verbose mode. Use --vv for even more verbose mode.
|
||||
.SH EXAMPLES
|
||||
.
|
||||
Deactivate all supported block devices found in the system, skipping mounted
|
||||
devices.
|
||||
.BR
|
||||
#
|
||||
.B blkdeactivate
|
||||
.BR
|
||||
.P
|
||||
Deactivate all supported block devices found in the system, unmounting any
|
||||
mounted devices first, if possible.
|
||||
.BR
|
||||
#
|
||||
.B blkdeactivate -u
|
||||
.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
|
||||
.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.
|
||||
.BR
|
||||
#
|
||||
.B blkdeactivate -u -d retry -l wholevg
|
||||
.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),
|
||||
.BR lvm (8),
|
||||
.BR mdadm (8),
|
||||
.BR multipathd (8),
|
||||
.BR umount (8)
|
@ -8,22 +8,22 @@ clvmd \(em cluster LVM daemon
|
||||
.
|
||||
.ad l
|
||||
.B clvmd
|
||||
.RB [ \-C ]
|
||||
.RB [ \-d
|
||||
.RB [ -C ]
|
||||
.RB [ -d
|
||||
.RI [ value ]]
|
||||
.RB [ \-E
|
||||
.RB [ -E
|
||||
.IR lock_uuid ]
|
||||
.RB [ \-f ]
|
||||
.RB [ \-h ]
|
||||
.RB [ \-I
|
||||
.RB [ -f ]
|
||||
.RB [ -h ]
|
||||
.RB [ -I
|
||||
.IR cluster_manager ]
|
||||
.RB [ \-R ]
|
||||
.RB [ \-S ]
|
||||
.RB [ \-t
|
||||
.RB [ -R ]
|
||||
.RB [ -S ]
|
||||
.RB [ -t
|
||||
.IR timeout ]
|
||||
.RB [ \-T
|
||||
.RB [ -T
|
||||
.IR start_timeout ]
|
||||
.RB [ \-V ]
|
||||
.RB [ -V ]
|
||||
.ad b
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
@ -35,12 +35,12 @@ if a node in the cluster does not have this daemon running.
|
||||
.SH OPTIONS
|
||||
.
|
||||
.HP
|
||||
.BR \-C
|
||||
.BR -C
|
||||
.br
|
||||
Only valid if \fB\-d\fP is also specified.
|
||||
Only valid if \fB-d\fP is also specified.
|
||||
Tells all clvmds in a cluster to enable/disable debug logging.
|
||||
Without this switch, only the local clvmd will change its debug level to that
|
||||
given with \fB\-d\fP.
|
||||
given with \fB-d\fP.
|
||||
.br
|
||||
This does not work correctly if specified on the command-line that starts clvmd.
|
||||
If you want to start clvmd \fBand\fP
|
||||
@ -48,14 +48,14 @@ enable cluster-wide logging then the command needs to be issued twice, eg:
|
||||
.br
|
||||
.BR clvmd
|
||||
.br
|
||||
.BR clvmd\ \-d2
|
||||
.BR clvmd\ -d2
|
||||
.
|
||||
.HP
|
||||
.BR \-d
|
||||
.BR -d
|
||||
.RI [ value ]
|
||||
.br
|
||||
Set debug logging level.
|
||||
If \fB\-d\fP is specified without a \fIvalue\fP
|
||||
If \fB-d\fP is specified without a \fIvalue\fP
|
||||
then 1 is assumed. \fIValue\fP can be:
|
||||
.PD 0
|
||||
.IP
|
||||
@ -63,30 +63,30 @@ then 1 is assumed. \fIValue\fP can be:
|
||||
\(em Disabled
|
||||
.IP
|
||||
.BR 1
|
||||
\(em Sends debug logs to stderr (implies \fB\-f\fP)
|
||||
\(em Sends debug logs to stderr (implies \fB-f\fP)
|
||||
.IP
|
||||
.BR 2
|
||||
\(em Sends debug logs to \fBsyslog\fP(3)
|
||||
.PD
|
||||
.
|
||||
.HP
|
||||
.BR \-E
|
||||
.BR -E
|
||||
.IR lock_uuid
|
||||
.br
|
||||
Pass lock uuid to be reacquired exclusively when clvmd is restarted.
|
||||
.
|
||||
.HP
|
||||
.BR \-f
|
||||
.BR -f
|
||||
.br
|
||||
Don't fork, run in the foreground.
|
||||
.
|
||||
.HP
|
||||
.BR \-h
|
||||
.BR -h
|
||||
.br
|
||||
Show help information.
|
||||
.
|
||||
.HP
|
||||
.BR \-I
|
||||
.BR -I
|
||||
.IR cluster_manager
|
||||
.br
|
||||
Selects the cluster manager to use for locking and internal
|
||||
@ -94,24 +94,24 @@ communications. As it is quite possible to have multiple managers available on
|
||||
the same system you might have to manually specify this option to override the
|
||||
search.
|
||||
|
||||
By default, omit \fB-I\fP is equivalent to \fB\-Iauto\fP.
|
||||
By default, omit \fB-I\fP is equivalent to \fB-Iauto\fP.
|
||||
Clvmd will use the first cluster manager that succeeds,
|
||||
and it checks them in a predefined order
|
||||
.BR cman ,
|
||||
.BR corosync ,
|
||||
.BR openais .
|
||||
The available managers will be listed by order as part of the
|
||||
\fBclvmd \-h\fP output.
|
||||
\fBclvmd -h\fP output.
|
||||
.
|
||||
.HP
|
||||
.BR \-R
|
||||
.BR -R
|
||||
.br
|
||||
Tells all the running instance of \fBclvmd\fP in the cluster to reload their device cache and
|
||||
re-read the lvm configuration file \fBlvm.conf\fP(5). This command should be run whenever the
|
||||
devices on a cluster system are changed.
|
||||
.
|
||||
.HP
|
||||
.BR \-S
|
||||
.BR -S
|
||||
.br
|
||||
Tells the running \fBclvmd\fP to exit and reexecute itself, for example at the
|
||||
end of a package upgrade. The new instance is instructed to reacquire
|
||||
@ -120,7 +120,7 @@ methods of restarting the daemon have the side effect of changing
|
||||
exclusive LV locks into shared locks.)
|
||||
.
|
||||
.HP
|
||||
.BR \-t
|
||||
.BR -t
|
||||
.IR timeout
|
||||
.br
|
||||
Specifies the \fItimeout\fP for commands to run around the cluster. This should not
|
||||
@ -129,7 +129,7 @@ may need to increase this on systems with very large disk farms.
|
||||
The default is 60 seconds.
|
||||
.
|
||||
.HP
|
||||
.BR \-T
|
||||
.BR -T
|
||||
.IR start_timeout
|
||||
.br
|
||||
Specifies the start timeout for \fBclvmd\fP daemon startup. If the
|
||||
@ -147,10 +147,10 @@ The default is \fB0\fP (no timeout) and the value is in seconds. Don't set this
|
||||
small or you will experience spurious errors. 10 or 20 seconds might be
|
||||
sensible.
|
||||
|
||||
This timeout will be ignored if you start \fBclvmd\fP with the \fB\-d\fP.
|
||||
This timeout will be ignored if you start \fBclvmd\fP with the \fB-d\fP.
|
||||
.
|
||||
.HP
|
||||
.BR \-V
|
||||
.BR -V
|
||||
.br
|
||||
Display the version of the cluster LVM daemon.
|
||||
.
|
||||
@ -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
|
@ -3,7 +3,7 @@
|
||||
cmirrord \(em cluster mirror log daemon
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBcmirrord\fR [\fB\-f\fR] [\fB\-h\fR]
|
||||
\fBcmirrord\fR [\fB-f\fR] [\fB-h\fR]
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBcmirrord\fP is the daemon that tracks mirror log information in a cluster.
|
||||
@ -26,9 +26,9 @@ ignored. Active cluster mirrors should be shutdown before stopping the cluster
|
||||
mirror log daemon.
|
||||
|
||||
.SH OPTIONS
|
||||
.IP "\fB\-f\fR, \fB\-\-foreground\fR" 4
|
||||
.IP "\fB-f\fR, \fB--foreground\fR" 4
|
||||
Do not fork and log to the terminal.
|
||||
.IP "\fB\-h\fR, \fB\-\-help\fR" 4
|
||||
.IP "\fB-h\fR, \fB--help\fR" 4
|
||||
Print usage.
|
||||
|
||||
.SH SEE ALSO
|
@ -7,15 +7,15 @@ dmeventd \(em Device-mapper event daemon
|
||||
.SH SYNOPSIS
|
||||
.
|
||||
.B dmeventd
|
||||
.RB [ \-d
|
||||
.RB [ \-d
|
||||
.RB [ \-d ]]]
|
||||
.RB [ \-f ]
|
||||
.RB [ \-h ]
|
||||
.RB [ \-l ]
|
||||
.RB [ \-R ]
|
||||
.RB [ \-V ]
|
||||
.RB [ \-? ]
|
||||
.RB [ -d
|
||||
.RB [ -d
|
||||
.RB [ -d ]]]
|
||||
.RB [ -f ]
|
||||
.RB [ -h ]
|
||||
.RB [ -l ]
|
||||
.RB [ -R ]
|
||||
.RB [ -V ]
|
||||
.RB [ -? ]
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
.
|
||||
@ -27,46 +27,46 @@ particular events occur.
|
||||
.SH OPTIONS
|
||||
.
|
||||
.HP
|
||||
.BR \-d
|
||||
.BR -d
|
||||
.br
|
||||
Repeat from 1 to 3 times (
|
||||
.BR \-d ,
|
||||
.BR \-dd ,
|
||||
.BR \-ddd
|
||||
.BR -d ,
|
||||
.BR -dd ,
|
||||
.BR -ddd
|
||||
) to increase the detail of
|
||||
debug messages sent to syslog.
|
||||
Each extra d adds more debugging information.
|
||||
.
|
||||
.HP
|
||||
.BR \-f
|
||||
.BR -f
|
||||
.br
|
||||
Don't fork, run in the foreground.
|
||||
.
|
||||
.HP
|
||||
.BR \-h
|
||||
.BR -h
|
||||
.br
|
||||
Show help information.
|
||||
.
|
||||
.HP
|
||||
.BR \-l
|
||||
.BR -l
|
||||
.br
|
||||
Log through stdout and stderr instead of syslog.
|
||||
This option works only with option \-f, otherwise it is ignored.
|
||||
This option works only with option -f, otherwise it is ignored.
|
||||
.
|
||||
.HP
|
||||
.BR \-?
|
||||
.BR -?
|
||||
.br
|
||||
Show help information on stderr.
|
||||
.
|
||||
.HP
|
||||
.BR \-R
|
||||
.BR -R
|
||||
.br
|
||||
Replace a running dmeventd instance. The running dmeventd must be version
|
||||
2.02.77 or newer. The new dmeventd instance will obtain a list of devices and
|
||||
events to monitor from the currently running daemon.
|
||||
.
|
||||
.HP
|
||||
.BR \-V
|
||||
.BR -V
|
||||
.br
|
||||
Show version of dmeventd.
|
||||
.
|
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
|
@ -23,12 +23,12 @@ dmsetup \(em low level logical volume management
|
||||
. ad l
|
||||
. BR create
|
||||
. IR device_name
|
||||
. RB [ -u | \-\-uuid
|
||||
. RB [ -u | --uuid
|
||||
. IR uuid ]
|
||||
. RB \%[ \-\-addnodeoncreate | \-\-addnodeonresume ]
|
||||
. RB \%[ \-n | \-\-notable | \-\-table
|
||||
. RB \%[ --addnodeoncreate | --addnodeonresume ]
|
||||
. RB \%[ -n | --notable | --table
|
||||
. IR \%table | table_file ]
|
||||
. RB [ \-\-readahead
|
||||
. RB [ --readahead
|
||||
. RB \%[ + ] \fIsectors | auto | none ]
|
||||
. ad b
|
||||
..
|
||||
@ -39,7 +39,7 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_DEPS
|
||||
. ad l
|
||||
. BR deps
|
||||
. RB [ \-o
|
||||
. RB [ -o
|
||||
. IR options ]
|
||||
. RI [ device_name ...]
|
||||
. ad b
|
||||
@ -50,7 +50,7 @@ dmsetup \(em low level logical volume management
|
||||
.B dmsetup
|
||||
.de CMD_HELP
|
||||
. BR help
|
||||
. RB [ \-c | \-C | \-\-columns ]
|
||||
. RB [ -c | -C | --columns ]
|
||||
..
|
||||
.CMD_HELP
|
||||
.
|
||||
@ -67,18 +67,18 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_INFOLONG
|
||||
. ad l
|
||||
. BR info
|
||||
. BR \-c | \-C | \-\-columns
|
||||
. RB [ \-\-count
|
||||
. BR -c | -C | --columns
|
||||
. RB [ --count
|
||||
. IR count ]
|
||||
. RB [ \-\-interval
|
||||
. RB [ --interval
|
||||
. IR seconds ]
|
||||
. RB \%[ \-\-nameprefixes ]
|
||||
. RB \%[ \-\-noheadings ]
|
||||
. RB [ \-o
|
||||
. RB \%[ --nameprefixes ]
|
||||
. RB \%[ --noheadings ]
|
||||
. RB [ -o
|
||||
. IR fields ]
|
||||
. RB [ \-O | \-\-sort
|
||||
. RB [ -O | --sort
|
||||
. IR sort_fields ]
|
||||
. RB [ \-\-separator
|
||||
. RB [ --separator
|
||||
. IR separator ]
|
||||
. RI [ device_name ]
|
||||
. ad b
|
||||
@ -91,7 +91,7 @@ dmsetup \(em low level logical volume management
|
||||
. ad l
|
||||
. BR load
|
||||
. IR device_name
|
||||
. RB [ \-\-table
|
||||
. RB [ --table
|
||||
. IR table | table_file ]
|
||||
. ad b
|
||||
..
|
||||
@ -102,12 +102,12 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_LS
|
||||
. ad l
|
||||
. BR ls
|
||||
. RB [ \-\-target
|
||||
. RB [ --target
|
||||
. IR target_type ]
|
||||
. RB [ \-\-exec
|
||||
. RB [ --exec
|
||||
. IR command ]
|
||||
. RB [ \-\-tree ]
|
||||
. RB [ \-o
|
||||
. RB [ --tree ]
|
||||
. RB [ -o
|
||||
. IR options ]
|
||||
. ad b
|
||||
..
|
||||
@ -145,7 +145,7 @@ dmsetup \(em low level logical volume management
|
||||
. ad l
|
||||
. BR reload
|
||||
. IR device_name
|
||||
. RB [ \-\-table
|
||||
. RB [ --table
|
||||
. IR table | table_file ]
|
||||
. ad b
|
||||
..
|
||||
@ -156,9 +156,9 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_REMOVE
|
||||
. ad l
|
||||
. BR remove
|
||||
. RB [ \-f | \-\-force ]
|
||||
. RB [ \-\-retry ]
|
||||
. RB [ \-\-deferred ]
|
||||
. RB [ -f | --force ]
|
||||
. RB [ --retry ]
|
||||
. RB [ --deferred ]
|
||||
. IR device_name ...
|
||||
. ad b
|
||||
..
|
||||
@ -168,8 +168,8 @@ dmsetup \(em low level logical volume management
|
||||
.B dmsetup
|
||||
.de CMD_REMOVE_ALL
|
||||
. BR remove_all
|
||||
. RB [ \-f | \-\-force ]
|
||||
. RB [ \-\-deferred ]
|
||||
. RB [ -f | --force ]
|
||||
. RB [ --deferred ]
|
||||
..
|
||||
.CMD_REMOVE_ALL
|
||||
.
|
||||
@ -187,7 +187,7 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_RENAME_UUID
|
||||
. BR rename
|
||||
. IR device_name
|
||||
. BR \-\-setuuid
|
||||
. BR --setuuid
|
||||
. IR uuid
|
||||
..
|
||||
.CMD_RENAME_UUID
|
||||
@ -198,10 +198,10 @@ dmsetup \(em low level logical volume management
|
||||
. ad l
|
||||
. BR resume
|
||||
. IR device_name ...
|
||||
. RB [ \-\-addnodeoncreate | \-\-addnodeonresume ]
|
||||
. RB [ \-\-noflush ]
|
||||
. RB [ \-\-nolockfs ]
|
||||
. RB \%[ \-\-readahead
|
||||
. RB [ --addnodeoncreate | --addnodeonresume ]
|
||||
. RB [ --noflush ]
|
||||
. RB [ --nolockfs ]
|
||||
. RB \%[ --readahead
|
||||
. RB \%[ + ] \fIsectors | auto | none ]
|
||||
. ad b
|
||||
..
|
||||
@ -244,9 +244,9 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_STATUS
|
||||
. ad l
|
||||
. BR status
|
||||
. RB [ \-\-target
|
||||
. RB [ --target
|
||||
. IR target_type ]
|
||||
. RB [ \-\-noflush ]
|
||||
. RB [ --noflush ]
|
||||
. RI [ device_name ...]
|
||||
. ad b
|
||||
..
|
||||
@ -257,8 +257,8 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_SUSPEND
|
||||
. ad l
|
||||
. BR suspend
|
||||
. RB [ \-\-nolockfs ]
|
||||
. RB [ \-\-noflush ]
|
||||
. RB [ --nolockfs ]
|
||||
. RB [ --noflush ]
|
||||
. IR device_name ...
|
||||
. ad b
|
||||
..
|
||||
@ -269,9 +269,9 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_TABLE
|
||||
. ad l
|
||||
. BR table
|
||||
. RB [ \-\-target
|
||||
. RB [ --target
|
||||
. IR target_type ]
|
||||
. RB [ \-\-showkeys ]
|
||||
. RB [ --showkeys ]
|
||||
. RI [ device_name ...]
|
||||
. ad b
|
||||
..
|
||||
@ -342,7 +342,7 @@ dmsetup \(em low level logical volume management
|
||||
.de CMD_WAIT
|
||||
. ad l
|
||||
. BR wait
|
||||
. RB [ \-\-noflush ]
|
||||
. RB [ --noflush ]
|
||||
. IR device_name
|
||||
. RI [ event_nr ]
|
||||
. ad b
|
||||
@ -355,9 +355,9 @@ dmsetup \(em low level logical volume management
|
||||
. ad l
|
||||
. BR wipe_table
|
||||
. IR device_name ...
|
||||
. RB [ \-f | \-\-force ]
|
||||
. RB [ \-\-noflush ]
|
||||
. RB [ \-\-nolockfs ]
|
||||
. RB [ -f | --force ]
|
||||
. RB [ --noflush ]
|
||||
. RB [ --nolockfs ]
|
||||
. ad b
|
||||
..
|
||||
.CMD_WIPE_TABLE
|
||||
@ -383,70 +383,70 @@ The second argument is the logical device name or uuid.
|
||||
Invoking the dmsetup tool as \fBdevmap_name\fP
|
||||
(which is not normally distributed and is supported
|
||||
only for historical reasons) is equivalent to
|
||||
.BI \%dmsetup\ info\ \-c\ \-\-noheadings\ \-j \ major\ \-m \ minor \c
|
||||
.BI \%dmsetup\ info\ -c\ --noheadings\ -j \ major\ -m \ minor \c
|
||||
\fR.
|
||||
.\" dot above here fixes -Thtml rendering for next HP option
|
||||
.
|
||||
.SH OPTIONS
|
||||
.
|
||||
.HP
|
||||
.BR \-\-addnodeoncreate
|
||||
.BR --addnodeoncreate
|
||||
.br
|
||||
Ensure \fI/dev/mapper\fP node exists after \fBdmsetup create\fP.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-addnodeonresume
|
||||
.BR --addnodeonresume
|
||||
.br
|
||||
Ensure \fI/dev/mapper\fP node exists after \fBdmsetup resume\fP (default with udev).
|
||||
.
|
||||
.HP
|
||||
.BR \-\-checks
|
||||
.BR --checks
|
||||
.br
|
||||
Perform additional checks on the operations requested and report
|
||||
potential problems. Useful when debugging scripts.
|
||||
In some cases these checks may slow down operations noticeably.
|
||||
.
|
||||
.HP
|
||||
.BR \-c | \-C | \-\-columns
|
||||
.BR -c | -C | --columns
|
||||
.br
|
||||
Display output in columns rather than as Field: Value lines.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-count
|
||||
.BR --count
|
||||
.IR count
|
||||
.br
|
||||
Specify the number of times to repeat a report. Set this to zero
|
||||
continue until interrupted. The default interval is one second.
|
||||
.
|
||||
.HP
|
||||
.BR \-f | \-\-force
|
||||
.BR -f | --force
|
||||
.br
|
||||
Try harder to complete operation.
|
||||
.
|
||||
.HP
|
||||
.BR \-h | \-\-help
|
||||
.BR -h | --help
|
||||
.br
|
||||
Outputs a summary of the commands available, optionally including
|
||||
the list of report fields (synonym with \fBhelp\fP command).
|
||||
.
|
||||
.HP
|
||||
.BR \-\-inactive
|
||||
.BR --inactive
|
||||
.br
|
||||
When returning any table information from the kernel report on the
|
||||
inactive table instead of the live table.
|
||||
Requires kernel driver version 4.16.0 or above.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-interval
|
||||
.BR --interval
|
||||
.IR seconds
|
||||
.br
|
||||
Specify the interval in seconds between successive iterations for
|
||||
repeating reports. If \fB\-\-interval\fP is specified but \fB\-\-count\fP
|
||||
repeating reports. If \fB--interval\fP is specified but \fB--count\fP
|
||||
is not, reports will continue to repeat until interrupted.
|
||||
The default interval is one second.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-manglename
|
||||
.BR --manglename
|
||||
.BR auto | hex | none
|
||||
.br
|
||||
Mangle any character not on a whitelist using mangling_mode when
|
||||
@ -466,69 +466,69 @@ Mangling mode could be also set through
|
||||
environment variable.
|
||||
.
|
||||
.HP
|
||||
.BR \-j | \-\-major
|
||||
.BR -j | --major
|
||||
.IR major
|
||||
.br
|
||||
Specify the major number.
|
||||
.
|
||||
.HP
|
||||
.BR \-m | \-\-minor
|
||||
.BR -m | --minor
|
||||
.IR minor
|
||||
.br
|
||||
Specify the minor number.
|
||||
.
|
||||
.HP
|
||||
.BR \-n | \-\-notable
|
||||
.BR -n | --notable
|
||||
.br
|
||||
When creating a device, don't load any table.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-nameprefixes
|
||||
.BR --nameprefixes
|
||||
.br
|
||||
Add a "DM_" prefix plus the field name to the output. Useful with
|
||||
\fB\-\-noheadings\fP to produce a list of
|
||||
\fB--noheadings\fP to produce a list of
|
||||
field=value pairs that can be used to set environment variables
|
||||
(for example, in
|
||||
.BR udev (7)
|
||||
rules).
|
||||
.
|
||||
.HP
|
||||
.BR \-\-noheadings
|
||||
.BR --noheadings
|
||||
Suppress the headings line when using columnar output.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-noflush
|
||||
.BR --noflush
|
||||
Do not flush outstading I/O when suspending a device, or do not
|
||||
commit thin-pool metadata when obtaining thin-pool status.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-nolockfs
|
||||
.BR --nolockfs
|
||||
.br
|
||||
Do not attempt to synchronize filesystem eg, when suspending a device.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-noopencount
|
||||
.BR --noopencount
|
||||
.br
|
||||
Tell the kernel not to supply the open reference count for the device.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-noudevrules
|
||||
.BR --noudevrules
|
||||
.br
|
||||
Do not allow udev to manage nodes for devices in device-mapper directory.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-noudevsync
|
||||
.BR --noudevsync
|
||||
.br
|
||||
Do not synchronise with udev when creating, renaming or removing devices.
|
||||
.
|
||||
.HP
|
||||
.BR \-o | \-\-options
|
||||
.BR -o | --options
|
||||
.IR options
|
||||
.br
|
||||
Specify which fields to display.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-readahead
|
||||
.BR --readahead
|
||||
.RB [ + ] \fIsectors | auto | none
|
||||
.br
|
||||
Specify read ahead size in units of sectors.
|
||||
@ -539,12 +539,12 @@ smaller than the value chosen by the kernel.
|
||||
The value \fBnone\fP is equivalent to specifying zero.
|
||||
.
|
||||
.HP
|
||||
.BR \-r | \-\-readonly
|
||||
.BR -r | --readonly
|
||||
.br
|
||||
Set the table being loaded read-only.
|
||||
.
|
||||
.HP
|
||||
.BR \-S | \-\-select
|
||||
.BR -S | --select
|
||||
.IR selection
|
||||
.br
|
||||
Display only rows that match \fIselection\fP criteria. All rows are displayed
|
||||
@ -557,14 +557,14 @@ selection operators, check the output of \fBdmsetup\ info\ -c\ -S\ help\fP
|
||||
command.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-table
|
||||
.BR --table
|
||||
.IR table
|
||||
.br
|
||||
Specify a one-line table directly on the command line.
|
||||
See below for more information on the table format.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-udevcookie
|
||||
.BR --udevcookie
|
||||
.IR cookie
|
||||
.br
|
||||
Use cookie for udev synchronisation.
|
||||
@ -573,29 +573,29 @@ multiple different devices. It's not adviced to combine different
|
||||
operations on the single device.
|
||||
.
|
||||
.HP
|
||||
.BR \-u | \-\-uuid
|
||||
.BR -u | --uuid
|
||||
.br
|
||||
Specify the \fIuuid\fP.
|
||||
.
|
||||
.HP
|
||||
.BR \-y | \-\-yes
|
||||
.BR -y | --yes
|
||||
.br
|
||||
Answer yes to all prompts automatically.
|
||||
.
|
||||
.HP
|
||||
.BR \-v | \-\-verbose
|
||||
.RB [ \-v | \-\-verbose ]
|
||||
.BR -v | --verbose
|
||||
.RB [ -v | --verbose ]
|
||||
.br
|
||||
Produce additional output.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-verifyudev
|
||||
.BR --verifyudev
|
||||
.br
|
||||
If udev synchronisation is enabled, verify that udev operations get performed
|
||||
correctly and try to fix up the device nodes afterwards if not.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-version
|
||||
.BR --version
|
||||
.br
|
||||
Display the library and kernel driver version.
|
||||
.br
|
||||
@ -612,7 +612,7 @@ Destroys the table in the inactive table slot for device_name.
|
||||
.br
|
||||
Creates a device with the given name.
|
||||
If \fItable\fP or \fItable_file\fP is supplied, the table is loaded and made live.
|
||||
Otherwise a table is read from standard input unless \fB\-\-notable\fP is used.
|
||||
Otherwise a table is read from standard input unless \fB--notable\fP is used.
|
||||
The optional \fIuuid\fP can be used in place of
|
||||
device_name in subsequent dmsetup commands.
|
||||
If successful the device will appear in table and for live
|
||||
@ -682,7 +682,7 @@ Device names on output can be customised by following options:
|
||||
\fBdevno\fP (major and minor pair, used by default),
|
||||
\fBblkdevname\fP (block device name),
|
||||
\fBdevname\fP (map name for device-mapper devices, equal to blkdevname otherwise).
|
||||
\fB\-\-tree\fP displays dependencies between devices as a tree.
|
||||
\fB--tree\fP displays dependencies between devices as a tree.
|
||||
It accepts a comma-separate list of \fIoptions\fP.
|
||||
Some specify the information displayed against each node:
|
||||
.BR device / nodevice ;
|
||||
@ -705,11 +705,11 @@ If neither is supplied, reads a table from standard input.
|
||||
Ensure existing device-mapper \fIdevice_name\fP and UUID is in the correct mangled
|
||||
form containing only whitelisted characters (supported by udev) and do
|
||||
a rename if necessary. Any character not on the whitelist will be mangled
|
||||
based on the \fB\-\-manglename\fP setting. Automatic rename works only for device
|
||||
based on the \fB--manglename\fP setting. Automatic rename works only for device
|
||||
names and not for device UUIDs because the kernel does not allow changing
|
||||
the UUID of active devices. Any incorrect UUIDs are reported only and they
|
||||
must be manually corrected by deactivating the device first and then
|
||||
reactivating it with proper mangling mode used (see also \fB\-\-manglename\fP).
|
||||
reactivating it with proper mangling mode used (see also \fB--manglename\fP).
|
||||
.
|
||||
.HP
|
||||
.CMD_MESSAGE
|
||||
@ -728,16 +728,16 @@ driver, adding, changing or removing nodes as necessary.
|
||||
.CMD_REMOVE
|
||||
.br
|
||||
Removes a device. It will no longer be visible to dmsetup. Open devices
|
||||
cannot be removed, but adding \fB\-\-force\fP will replace the table with one
|
||||
that fails all I/O. \fB\-\-deferred\fP will enable deferred removal of open
|
||||
cannot be removed, but adding \fB--force\fP will replace the table with one
|
||||
that fails all I/O. \fB--deferred\fP will enable deferred removal of open
|
||||
devices - the device will be removed when the last user closes it. The deferred
|
||||
removal feature is supported since version 4.27.0 of the device-mapper
|
||||
driver available in upstream kernel version 3.13. (Use \fBdmsetup version\fP
|
||||
to check this.) If an attempt to remove a device fails, perhaps because a process run
|
||||
from a quick udev rule temporarily opened the device, the \fB\-\-retry\fP
|
||||
from a quick udev rule temporarily opened the device, the \fB--retry\fP
|
||||
option will cause the operation to be retried for a few seconds before failing.
|
||||
Do NOT combine
|
||||
\fB\-\-force\fP and \fB\-\-udevcookie\fP, as udev may start to process udev
|
||||
\fB--force\fP and \fB--udevcookie\fP, as udev may start to process udev
|
||||
rules in the middle of error target replacement and result in nondeterministic
|
||||
result.
|
||||
.
|
||||
@ -746,8 +746,8 @@ result.
|
||||
.br
|
||||
Attempts to remove all device definitions i.e. reset the driver. This also runs
|
||||
\fBmknodes\fP afterwards. Use with care! Open devices cannot be removed, but
|
||||
adding \fB\-\-force\fP will replace the table with one that fails all I/O.
|
||||
\fB\-\-deferred\fP will enable deferred removal of open devices - the device
|
||||
adding \fB--force\fP will replace the table with one that fails all I/O.
|
||||
\fB--deferred\fP will enable deferred removal of open devices - the device
|
||||
will be removed when the last user closes it. The deferred removal feature is
|
||||
supported since version 4.27.0 of the device-mapper driver available in
|
||||
upstream kernel version 3.13.
|
||||
@ -797,8 +797,8 @@ for more details.
|
||||
.CMD_STATUS
|
||||
.br
|
||||
Outputs status information for each of the device's targets.
|
||||
With \fB\-\-target\fP, only information relating to the specified target type
|
||||
any is displayed. With \fB\-\-noflush\fP, the thin target (from version 1.3.0)
|
||||
With \fB--target\fP, only information relating to the specified target type
|
||||
any is displayed. With \fB--noflush\fP, the thin target (from version 1.3.0)
|
||||
doesn't commit any outstanding changes to disk before reporting its statistics.
|
||||
|
||||
.HP
|
||||
@ -808,9 +808,9 @@ Suspends a device. Any I/O that has already been mapped by the device
|
||||
but has not yet completed will be flushed. Any further I/O to that
|
||||
device will be postponed for as long as the device is suspended.
|
||||
If there's a filesystem on the device which supports the operation,
|
||||
an attempt will be made to sync it first unless \fB\-\-nolockfs\fP is specified.
|
||||
an attempt will be made to sync it first unless \fB--nolockfs\fP is specified.
|
||||
Some targets such as recent (October 2006) versions of multipath may support
|
||||
the \fB\-\-noflush\fP option. This lets outstanding I/O that has not yet reached the
|
||||
the \fB--noflush\fP option. This lets outstanding I/O that has not yet reached the
|
||||
device to remain unflushed.
|
||||
.
|
||||
.HP
|
||||
@ -818,10 +818,10 @@ device to remain unflushed.
|
||||
.br
|
||||
Outputs the current table for the device in a format that can be fed
|
||||
back in using the create or load commands.
|
||||
With \fB\-\-target\fP, only information relating to the specified target type
|
||||
With \fB--target\fP, only information relating to the specified target type
|
||||
is displayed.
|
||||
Real encryption keys are suppressed in the table output for the crypt
|
||||
target unless the \fB\-\-showkeys\fP parameter is supplied. Kernel key
|
||||
target unless the \fB--showkeys\fP parameter is supplied. Kernel key
|
||||
references prefixed with \fB:\fP are not affected by the parameter and get
|
||||
displayed always.
|
||||
.
|
||||
@ -855,7 +855,7 @@ The output is a cookie value. Normally we don't need to create cookies since
|
||||
dmsetup creates and destroys them for each action automatically. However, we can
|
||||
generate one explicitly to group several actions together and use only one
|
||||
cookie instead. We can define a cookie to use for each relevant command by using
|
||||
\fB\-\-udevcookie\fP option. Alternatively, we can export this value into the environment
|
||||
\fB--udevcookie\fP option. Alternatively, we can export this value into the environment
|
||||
of the dmsetup process as \fBDM_UDEV_COOKIE\fP variable and it will be used automatically
|
||||
with all subsequent commands until it is unset.
|
||||
Invoking this command will create system-wide semaphore that needs to be cleaned
|
||||
@ -888,10 +888,10 @@ Outputs version information.
|
||||
.CMD_WAIT
|
||||
.br
|
||||
Sleeps until the event counter for device_name exceeds event_nr.
|
||||
Use \fB\-v\fP to see the event number returned.
|
||||
Use \fB-v\fP to see the event number returned.
|
||||
To wait until the next event is triggered, use \fBinfo\fP to find
|
||||
the last event number.
|
||||
With \fB\-\-noflush\fP, the thin target (from version 1.3.0) doesn't commit
|
||||
With \fB--noflush\fP, the thin target (from version 1.3.0) doesn't commit
|
||||
any outstanding changes to disk before reporting its statistics.
|
||||
.
|
||||
.HP
|
||||
@ -1005,11 +1005,11 @@ Defaults to "\fI/dev\fP" and must be an absolute path.
|
||||
.TP
|
||||
.B DM_UDEV_COOKIE
|
||||
A cookie to use for all relevant commands to synchronize with udev processing.
|
||||
It is an alternative to using \fB\-\-udevcookie\fP option.
|
||||
It is an alternative to using \fB--udevcookie\fP option.
|
||||
.TP
|
||||
.B DM_DEFAULT_NAME_MANGLING_MODE
|
||||
A default mangling mode. Defaults to "\fB#DEFAULT_MANGLING#\fP"
|
||||
and it is an alternative to using \fB\-\-manglename\fP option.
|
||||
and it is an alternative to using \fB--manglename\fP option.
|
||||
.
|
||||
.SH AUTHORS
|
||||
.
|
@ -1,18 +1,21 @@
|
||||
.TH DMSTATS 8 "Jun 23 2016" "Linux" "MAINTENANCE COMMANDS"
|
||||
|
||||
.de OPT_PROGRAMS
|
||||
. RB \%[ \-\-allprograms | \-\-programid
|
||||
. RB \%[ --allprograms | --programid
|
||||
. IR id ]
|
||||
..
|
||||
.
|
||||
.de OPT_REGIONS
|
||||
. RB \%[ \-\-allregions | \-\-regionid
|
||||
. RB \%[ --allregions | --regionid
|
||||
. IR id ]
|
||||
..
|
||||
.de OPT_OBJECTS
|
||||
. RB [ \-\-area ]
|
||||
. RB [ \-\-region ]
|
||||
. RB [ \-\-group ]
|
||||
. RB [ --area ]
|
||||
. RB [ --region ]
|
||||
. RB [ --group ]
|
||||
..
|
||||
.de OPT_FOREGROUND
|
||||
. RB [ --foreground ]
|
||||
..
|
||||
.
|
||||
.\" Print units suffix, use with arg to print human
|
||||
@ -54,13 +57,13 @@ dmstats \(em device-mapper statistics management
|
||||
. ad l
|
||||
. IR command
|
||||
. IR device_name " |"
|
||||
. BR \-\-major
|
||||
. BR --major
|
||||
. IR major
|
||||
. BR \-\-minor
|
||||
. BR --minor
|
||||
. IR minor " |"
|
||||
. BR \-u | \-\-uuid
|
||||
. BR -u | --uuid
|
||||
. IR uuid
|
||||
. RB \%[ \-v | \-\-verbose]
|
||||
. RB \%[ -v | --verbose]
|
||||
. ad b
|
||||
..
|
||||
.CMD_COMMAND
|
||||
@ -82,22 +85,26 @@ dmstats \(em device-mapper statistics management
|
||||
.de CMD_CREATE
|
||||
. ad l
|
||||
. BR create
|
||||
. IR device_name... | file_path... | \fB\-\-alldevices
|
||||
. RB [ \-\-areas
|
||||
. IR nr_areas | \fB\-\-areasize
|
||||
. IR device_name... | file_path... | \fB--alldevices
|
||||
. RB [ --areas
|
||||
. IR nr_areas | \fB--areasize
|
||||
. IR area_size ]
|
||||
. RB [ \-\-bounds
|
||||
. RB [ --bounds
|
||||
. IR \%histogram_boundaries ]
|
||||
. RB [ \-\-filemap ]
|
||||
. RB [ \-\-nogroup ]
|
||||
. RB [ \-\-precise ]
|
||||
. RB [ \-\-start
|
||||
. RB [ --filemap ]
|
||||
. RB [ --follow
|
||||
. IR follow_mode ]
|
||||
. OPT_FOREGROUND
|
||||
. RB [ --nomonitor ]
|
||||
. RB [ --nogroup ]
|
||||
. RB [ --precise ]
|
||||
. RB [ --start
|
||||
. IR start_sector
|
||||
. BR \-\-length
|
||||
. IR length | \fB\-\-segments ]
|
||||
. RB \%[ \-\-userdata
|
||||
. BR --length
|
||||
. IR length | \fB--segments ]
|
||||
. RB \%[ --userdata
|
||||
. IR user_data ]
|
||||
. RB [ \-\-programid
|
||||
. RB [ --programid
|
||||
. IR id ]
|
||||
. ad b
|
||||
..
|
||||
@ -108,7 +115,7 @@ dmstats \(em device-mapper statistics management
|
||||
.de CMD_DELETE
|
||||
. ad l
|
||||
. BR delete
|
||||
. IR device_name | \fB\-\-alldevices
|
||||
. IR device_name | \fB--alldevices
|
||||
. OPT_PROGRAMS
|
||||
. OPT_REGIONS
|
||||
. ad b
|
||||
@ -120,10 +127,10 @@ dmstats \(em device-mapper statistics management
|
||||
.de CMD_GROUP
|
||||
. ad l
|
||||
. BR group
|
||||
. RI [ device_name | \fB\-\-alldevices ]
|
||||
. RB [ \-\-alias
|
||||
. RI [ device_name | \fB--alldevices ]
|
||||
. RB [ --alias
|
||||
. IR name ]
|
||||
. RB [ \-\-regions
|
||||
. RB [ --regions
|
||||
. IR regions ]
|
||||
. ad b
|
||||
..
|
||||
@ -133,7 +140,7 @@ dmstats \(em device-mapper statistics management
|
||||
.de CMD_HELP
|
||||
. ad l
|
||||
. BR help
|
||||
. RB [ \-c | \-C | \-\-columns ]
|
||||
. RB [ -c | -C | --columns ]
|
||||
. ad b
|
||||
..
|
||||
.CMD_HELP
|
||||
@ -144,14 +151,14 @@ dmstats \(em device-mapper statistics management
|
||||
. ad l
|
||||
. BR list
|
||||
. RI [ device_name ]
|
||||
. RB [ \-\-histogram ]
|
||||
. RB [ --histogram ]
|
||||
. OPT_PROGRAMS
|
||||
. RB [ \-\-units
|
||||
. RB [ --units
|
||||
. IR units ]
|
||||
. OPT_OBJECTS
|
||||
. RB \%[ \-\-nosuffix ]
|
||||
. RB [ \-\-notimesuffix ]
|
||||
. RB \%[ \-v | \-\-verbose]
|
||||
. RB \%[ --nosuffix ]
|
||||
. RB [ --notimesuffix ]
|
||||
. RB \%[ -v | --verbose]
|
||||
. ad b
|
||||
..
|
||||
.CMD_LIST
|
||||
@ -162,7 +169,7 @@ dmstats \(em device-mapper statistics management
|
||||
. ad l
|
||||
. BR print
|
||||
. RI [ device_name ]
|
||||
. RB [ \-\-clear ]
|
||||
. RB [ --clear ]
|
||||
. OPT_PROGRAMS
|
||||
. OPT_REGIONS
|
||||
. ad b
|
||||
@ -175,24 +182,24 @@ dmstats \(em device-mapper statistics management
|
||||
. ad l
|
||||
. BR report
|
||||
. RI [ device_name ]
|
||||
. RB [ \-\-interval
|
||||
. RB [ --interval
|
||||
. IR seconds ]
|
||||
. RB [ \-\-count
|
||||
. RB [ --count
|
||||
. IR count ]
|
||||
. RB [ \-\-units
|
||||
. RB [ --units
|
||||
. IR units ]
|
||||
. RB [ \-\-histogram ]
|
||||
. RB [ --histogram ]
|
||||
. OPT_PROGRAMS
|
||||
. OPT_REGIONS
|
||||
. OPT_OBJECTS
|
||||
. RB [ \-O | \-\-sort
|
||||
. RB [ -O | --sort
|
||||
. IR sort_fields ]
|
||||
. RB [ \-S | \-\-select
|
||||
. RB [ -S | --select
|
||||
. IR selection ]
|
||||
. RB [ \-\-units
|
||||
. RB [ --units
|
||||
. IR units ]
|
||||
. RB [ \-\-nosuffix ]
|
||||
. RB \%[ \-\-notimesuffix ]
|
||||
. RB [ --nosuffix ]
|
||||
. RB \%[ --notimesuffix ]
|
||||
. ad b
|
||||
..
|
||||
.CMD_REPORT
|
||||
@ -201,8 +208,8 @@ dmstats \(em device-mapper statistics management
|
||||
.de CMD_UNGROUP
|
||||
. ad l
|
||||
. BR ungroup
|
||||
. RI [ device_name | \fB\-\-alldevices ]
|
||||
. RB [ \-\-groupid
|
||||
. RI [ device_name | \fB--alldevices ]
|
||||
. RB [ --groupid
|
||||
. IR id ]
|
||||
. ad b
|
||||
..
|
||||
@ -213,8 +220,11 @@ dmstats \(em device-mapper statistics management
|
||||
. ad l
|
||||
. BR update_filemap
|
||||
. IR file_path
|
||||
. RB [ \-\-groupid
|
||||
. RB [ --groupid
|
||||
. IR id ]
|
||||
. RB [ --follow
|
||||
. IR follow_mode ]
|
||||
. OPT_FOREGROUND
|
||||
. ad b
|
||||
..
|
||||
.CMD_UPDATE_FILEMAP
|
||||
@ -238,47 +248,47 @@ control, and reporting behaviour.
|
||||
|
||||
When no device argument is given dmstats will by default operate on all
|
||||
device-mapper devices present. The \fBcreate\fP and \fBdelete\fP
|
||||
commands require the use of \fB\-\-alldevices\fP when used in this way.
|
||||
commands require the use of \fB--alldevices\fP when used in this way.
|
||||
.
|
||||
.SH OPTIONS
|
||||
.
|
||||
.HP
|
||||
.BR \-\-alias
|
||||
.BR --alias
|
||||
.IR name
|
||||
.br
|
||||
Specify an alias name for a group.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-alldevices
|
||||
.BR --alldevices
|
||||
.br
|
||||
If no device arguments are given allow operation on all devices when
|
||||
creating or deleting regions.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-allprograms
|
||||
.BR --allprograms
|
||||
.br
|
||||
Include regions from all program IDs for list and report operations.
|
||||
.br
|
||||
.HP
|
||||
.BR \-\-allregions
|
||||
.BR --allregions
|
||||
.br
|
||||
Include all present regions for commands that normally accept a single
|
||||
region identifier.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-area
|
||||
.BR --area
|
||||
.br
|
||||
When peforming a list or report, include objects of type area in the
|
||||
results.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-areas
|
||||
.BR --areas
|
||||
.IR nr_areas
|
||||
.br
|
||||
Specify the number of statistics areas to create within a new region.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-areasize
|
||||
.BR --areasize
|
||||
.IR area_size \c
|
||||
.RB [ \c
|
||||
.UNITS
|
||||
@ -288,25 +298,25 @@ optional suffix selects units of:
|
||||
.HELP_UNITS
|
||||
.
|
||||
.HP
|
||||
.BR \-\-clear
|
||||
.BR --clear
|
||||
.br
|
||||
When printing statistics counters, also atomically reset them to zero.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-count
|
||||
.BR --count
|
||||
.IR count
|
||||
.br
|
||||
Specify the iteration count for repeating reports. If the count
|
||||
argument is zero reports will continue to repeat until interrupted.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-group
|
||||
.BR --group
|
||||
.br
|
||||
When peforming a list or report, include objects of type group in the
|
||||
results.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-filemap
|
||||
.BR --filemap
|
||||
.br
|
||||
Instead of creating regions on a device as specified by command line
|
||||
options, open the file found at each \fBfile_path\fP argument, and
|
||||
@ -314,13 +324,67 @@ create regions corresponding to the locations of the on-disk extents
|
||||
allocated to the file(s).
|
||||
.
|
||||
.HP
|
||||
.BR \-\-groupid
|
||||
.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
|
||||
Specify the group to operate on.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-bounds
|
||||
.BR --bounds
|
||||
.IR histogram_boundaries \c
|
||||
.RB [ ns | us | ms | s ]
|
||||
.br
|
||||
@ -334,22 +398,22 @@ or \fBs\fP may be given after each value to specify units of
|
||||
nanoseconds, microseconds, miliseconds or seconds respectively.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-histogram
|
||||
.BR --histogram
|
||||
.br
|
||||
When used with the \fBreport\fP and \fBlist\fP commands select default
|
||||
fields that emphasize latency histogram data.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-interval
|
||||
.BR --interval
|
||||
.IR seconds
|
||||
.br
|
||||
Specify the interval in seconds between successive iterations for
|
||||
repeating reports. If \fB\-\-interval\fP is specified but
|
||||
\fB\-\-count\fP is not,
|
||||
repeating reports. If \fB--interval\fP is specified but
|
||||
\fB--count\fP is not,
|
||||
reports will continue to repeat until interrupted.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-length
|
||||
.BR --length
|
||||
.IR length \c
|
||||
.RB [ \c
|
||||
.UNITS
|
||||
@ -359,55 +423,55 @@ suffix selects units of:
|
||||
.HELP_UNITS
|
||||
.
|
||||
.HP
|
||||
.BR \-j | \-\-major
|
||||
.BR -j | --major
|
||||
.IR major
|
||||
.br
|
||||
Specify the major number.
|
||||
.
|
||||
.HP
|
||||
.BR \-m | \-\-minor
|
||||
.BR -m | --minor
|
||||
.IR minor
|
||||
.br
|
||||
Specify the minor number.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-nogroup
|
||||
.BR --nogroup
|
||||
.br
|
||||
When creating regions mapping the extents of a file in the file
|
||||
system, do not create a group or set an alias.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-nosuffix
|
||||
.BR --nosuffix
|
||||
.br
|
||||
Suppress the suffix on output sizes. Use with \fB\-\-units\fP
|
||||
Suppress the suffix on output sizes. Use with \fB--units\fP
|
||||
(except h and H) if processing the output.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-notimesuffix
|
||||
.BR --notimesuffix
|
||||
.br
|
||||
Suppress the suffix on output time values. Histogram boundary values
|
||||
will be reported in units of nanoseconds.
|
||||
.
|
||||
.HP
|
||||
.BR \-o | \-\-options
|
||||
.BR -o | --options
|
||||
.br
|
||||
Specify which report fields to display.
|
||||
.
|
||||
.HP
|
||||
.BR \-O | \-\-sort
|
||||
.BR -O | --sort
|
||||
.IR sort_fields
|
||||
.br
|
||||
Sort output according to the list of fields given. Precede any
|
||||
sort field with '\fB-\fP' for a reverse sort on that column.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-precise
|
||||
.BR --precise
|
||||
.br
|
||||
Attempt to use nanosecond precision counters when creating new
|
||||
statistics regions.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-programid
|
||||
.BR --programid
|
||||
.IR id
|
||||
.br
|
||||
Specify a program ID string. When creating new statistics regions this
|
||||
@ -416,19 +480,19 @@ program ID in order to select only regions with a matching value. The
|
||||
default program ID for dmstats-managed regions is "dmstats".
|
||||
.
|
||||
.HP
|
||||
.BR \-\-region
|
||||
.BR --region
|
||||
.br
|
||||
When peforming a list or report, include objects of type region in the
|
||||
results.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-regionid
|
||||
.BR --regionid
|
||||
.IR id
|
||||
.br
|
||||
Specify the region to operate on.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-regions
|
||||
.BR --regions
|
||||
.IR region_list
|
||||
.br
|
||||
Specify a list of regions to group. The group list is a comma-separated
|
||||
@ -436,23 +500,23 @@ list of region identifiers. Continuous sequences of identifiers may be
|
||||
expressed as a hyphen separated range, for example: '1-10'.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-relative
|
||||
.BR --relative
|
||||
.br
|
||||
If displaying the histogram report show relative (percentage) values
|
||||
instead of absolute counts.
|
||||
.
|
||||
.HP
|
||||
.BR \-S | \-\-select
|
||||
.BR -S | --select
|
||||
.IR selection
|
||||
.br
|
||||
Display only rows that match \fIselection\fP criteria. All rows with the
|
||||
additional "selected" column (\fB\-o selected\fP) showing 1 if the row matches
|
||||
additional "selected" column (\fB-o selected\fP) showing 1 if the row matches
|
||||
the \fIselection\fP and 0 otherwise. The selection criteria are defined by
|
||||
specifying column names and their valid values while making use of
|
||||
supported comparison operators.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-start
|
||||
.BR --start
|
||||
.IR start \c
|
||||
.RB [ \c
|
||||
.UNITS
|
||||
@ -462,18 +526,18 @@ optional suffix selects units of:
|
||||
.HELP_UNITS
|
||||
.
|
||||
.HP
|
||||
.BR \-\-segments
|
||||
.BR --segments
|
||||
.br
|
||||
When used with \fBcreate\fP, create a new statistics region for each
|
||||
target contained in the given device(s). This causes a separate region
|
||||
to be allocated for each segment of the device.
|
||||
|
||||
The newly created regions are automatically placed into a group unless
|
||||
the \fB\-\-nogroup\fP option is given. When grouping is enabled a group
|
||||
alias may be specified using the \fB\-\-alias\fP option.
|
||||
the \fB--nogroup\fP option is given. When grouping is enabled a group
|
||||
alias may be specified using the \fB--alias\fP option.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-units
|
||||
.BR --units
|
||||
.RI [ units ] \c
|
||||
.RB [ h | H | \c
|
||||
.UNITS
|
||||
@ -482,10 +546,10 @@ Set the display units for report output.
|
||||
All sizes are output in these units:
|
||||
.RB ( h )uman-readable,
|
||||
.HELP_UNITS
|
||||
Can also specify custom units e.g. \fB\-\-units\ 3M\fP.
|
||||
Can also specify custom units e.g. \fB--units\ 3M\fP.
|
||||
.
|
||||
.HP
|
||||
.BR \-\-userdata
|
||||
.BR --userdata
|
||||
.IR user_data
|
||||
.br
|
||||
Specify user data (a word) to be stored with a new region. The value
|
||||
@ -494,12 +558,12 @@ information), and stored with the region in the aux_data field provided
|
||||
by the kernel. Whitespace is not permitted.
|
||||
.
|
||||
.HP
|
||||
.BR \-u | \-\-uuid
|
||||
.BR -u | --uuid
|
||||
.br
|
||||
Specify the uuid.
|
||||
.
|
||||
.HP
|
||||
.BR \-v | \-\-verbose " [" \-v | \-\-verbose ]
|
||||
.BR -v | --verbose " [" -v | --verbose ]
|
||||
.br
|
||||
Produce additional output.
|
||||
.
|
||||
@ -516,17 +580,17 @@ regions (with the exception of in-flight IO counters).
|
||||
.br
|
||||
Creates one or more new statistics regions on the specified device(s).
|
||||
|
||||
The region will span the entire device unless \fB\-\-start\fP and
|
||||
\fB\-\-length\fP or \fB\-\-segments\fP are given. The \fB\-\-start\fP an
|
||||
\fB\-\-length\fP options allow a region of arbitrary length to be placed
|
||||
at an arbitrary offset into the device. The \fB\-\-segments\fP option
|
||||
The region will span the entire device unless \fB--start\fP and
|
||||
\fB--length\fP or \fB--segments\fP are given. The \fB--start\fP an
|
||||
\fB--length\fP options allow a region of arbitrary length to be placed
|
||||
at an arbitrary offset into the device. The \fB--segments\fP option
|
||||
causes a new region to be created for each target in the corresponding
|
||||
device-mapper device's table.
|
||||
|
||||
If the \fB\-\-precise\fP option is used the command will attempt to
|
||||
If the \fB--precise\fP option is used the command will attempt to
|
||||
create a region using nanosecond precision counters.
|
||||
|
||||
If \fB\-\-bounds\fP is given a latency histogram will be tracked for
|
||||
If \fB--bounds\fP is given a latency histogram will be tracked for
|
||||
the new region. The boundaries of the histogram bins are given as a
|
||||
comma separated list of latency values. There is an implicit lower bound
|
||||
of zero on the first bin and an implicit upper bound of infinity (or the
|
||||
@ -537,7 +601,7 @@ ms, or s may be given after each value to specify units of nanoseconds,
|
||||
microseconds, miliseconds or seconds respectively, so for example, 10ms
|
||||
is equivalent to 10000000. Latency values with a precision of less than
|
||||
one milisecond can only be used when precise timestamps are enabled: if
|
||||
\fB\-\-precise\fP is not given and values less than one milisecond are
|
||||
\fB--precise\fP is not given and values less than one milisecond are
|
||||
used it will be enabled automatically.
|
||||
|
||||
An optional \fBprogram_id\fP or \fBuser_data\fP string may be associated
|
||||
@ -552,7 +616,7 @@ By default dmstats creates regions with a \fBprogram_id\fP of
|
||||
On success the \fBregion_id\fP of the newly created region is printed
|
||||
to stdout.
|
||||
|
||||
If the \fB\-\-filemap\fP option is given with a regular file, or list
|
||||
If the \fB--filemap\fP option is given with a regular file, or list
|
||||
of files, as the \fBfile_path\fP argument, instead of creating regions
|
||||
with parameters specified on the command line, \fBdmstats\fP will open
|
||||
the files located at \fBfile_path\fP and create regions corresponding to
|
||||
@ -560,15 +624,20 @@ the physical extents allocated to the file. This can be used to monitor
|
||||
statistics for individual files in the file system, for example, virtual
|
||||
machine images, swap areas, or large database files.
|
||||
|
||||
To work with the \fB\-\-filemap\fP option, files must be located on a
|
||||
To work with the \fB--filemap\fP option, files must be located on a
|
||||
local file system, backed by a device-mapper device, that supports
|
||||
physical extent data using the FIEMAP ioctl (Ext4 and XFS for e.g.).
|
||||
|
||||
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.
|
||||
overridden with the \fB--alias\fP and \fB--nogroup\fP options.
|
||||
|
||||
Use the \fB\-\-group\fP option to only display information for groups
|
||||
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.
|
||||
.
|
||||
.HP
|
||||
@ -579,12 +648,12 @@ by the region are released and the region will not appear in the output
|
||||
of subsequent list, print, or report operations.
|
||||
|
||||
All regions registered on a device may be removed using
|
||||
\fB\-\-allregions\fP.
|
||||
\fB--allregions\fP.
|
||||
|
||||
To remove all regions on all devices both \fB\-\-allregions\fP and
|
||||
\fB\-\-alldevices\fP must be used.
|
||||
To remove all regions on all devices both \fB--allregions\fP and
|
||||
\fB--alldevices\fP must be used.
|
||||
|
||||
If a \fB\-\-groupid\fP is given instead of a \fB\-\-regionid\fP the
|
||||
If a \fB--groupid\fP is given instead of a \fB--regionid\fP the
|
||||
command will attempt to delete the group and all regions that it
|
||||
contains.
|
||||
|
||||
@ -597,8 +666,8 @@ will also be removed.
|
||||
Combine one or more statistics regions on the specified device into a
|
||||
group.
|
||||
|
||||
The list of regions to be grouped is specified with \fB\-\-regions\fP
|
||||
and an optional alias may be assigned with \fB\-\-alias\fP. The set of
|
||||
The list of regions to be grouped is specified with \fB--regions\fP
|
||||
and an optional alias may be assigned with \fB--alias\fP. The set of
|
||||
regions is given as a comma-separated list of region identifiers. A
|
||||
continuous range of identifers spanning from \fBR1\fP to \fBR2\fP may
|
||||
be expressed as '\fBR1\fP-\fBR2\fP'.
|
||||
@ -624,21 +693,21 @@ the list of report fields.
|
||||
.CMD_LIST
|
||||
.br
|
||||
List the statistics regions, areas, or groups registered on the device.
|
||||
If the \fB\-\-allprograms\fP switch is given all regions will be listed
|
||||
If the \fB--allprograms\fP switch is given all regions will be listed
|
||||
regardless of region program ID values.
|
||||
|
||||
By default only regions and groups are included in list output. If
|
||||
\fB\-v\fP or \fB\-\-verbose\fP is given the report will also include a
|
||||
\fB-v\fP or \fB--verbose\fP is given the report will also include a
|
||||
row of information for each configured group and for each area contained
|
||||
in each region displayed.
|
||||
|
||||
Regions that contain a single area are by default omitted from the
|
||||
verbose list since their properties are identical to the area that they
|
||||
contain - to view all regions regardless of the number of areas present
|
||||
use \fB\-\-region\fP). To also view the areas contained within regions
|
||||
use \fB\-\-area\fP.
|
||||
use \fB--region\fP). To also view the areas contained within regions
|
||||
use \fB--area\fP.
|
||||
|
||||
If \fB\-\-histogram\fP is given the report will include the bin count
|
||||
If \fB--histogram\fP is given the report will include the bin count
|
||||
and latency boundary values for any configured histograms.
|
||||
.HP
|
||||
.CMD_PRINT
|
||||
@ -651,20 +720,20 @@ present regions.
|
||||
.br
|
||||
Start a report for the specified object or for all present objects. If
|
||||
the count argument is specified, the report will repeat at a fixed
|
||||
interval set by the \fB\-\-interval\fP option. The default interval is
|
||||
interval set by the \fB--interval\fP option. The default interval is
|
||||
one second.
|
||||
|
||||
If the \fB\-\-allprograms\fP switch is given, all regions will be
|
||||
If the \fB--allprograms\fP switch is given, all regions will be
|
||||
listed, regardless of region program ID values.
|
||||
|
||||
If the \fB\-\-histogram\fP is given the report will include the histogram
|
||||
If the \fB--histogram\fP is given the report will include the histogram
|
||||
values and latency boundaries.
|
||||
|
||||
If the \fB\-\-relative\fP is used the default histogram field displays
|
||||
If the \fB--relative\fP is used the default histogram field displays
|
||||
bin values as a percentage of the total number of I/Os.
|
||||
|
||||
Object types (areas, regions and groups) to include in the report are
|
||||
selected using the \fB\-\-area\fP, \fB\-\-region\fP, and \fB\-\-group\fP
|
||||
selected using the \fB--area\fP, \fB--region\fP, and \fB--group\fP
|
||||
options.
|
||||
.
|
||||
.HP
|
||||
@ -673,22 +742,28 @@ options.
|
||||
Remove an existing group and return all the group's regions to their
|
||||
original state.
|
||||
|
||||
The group to be removed is specified using \fB\-\-groupid\fP.
|
||||
The group to be removed is specified using \fB--groupid\fP.
|
||||
.HP
|
||||
.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
|
||||
.
|
||||
@ -711,8 +786,8 @@ The group metadata is stored with the first (lowest numbered)
|
||||
the group and other group members will be returned to their prior
|
||||
state.
|
||||
|
||||
By default new regions span the entire device. The \fB\-\-start\fP and
|
||||
\fB\-\-length\fP options allows a region of any size to be placed at any
|
||||
By default new regions span the entire device. The \fB--start\fP and
|
||||
\fB--length\fP options allows a region of any size to be placed at any
|
||||
location on the device.
|
||||
|
||||
Using offsets it is possible to create regions that map individual
|
||||
@ -723,7 +798,7 @@ and data aggregation.
|
||||
|
||||
A region may be either divided into the specified number of equal-sized
|
||||
areas, or into areas of the given size by specifying one of
|
||||
\fB\-\-areas\fP or \fB\-\-areasize\fP when creating a region with the
|
||||
\fB--areas\fP or \fB--areasize\fP when creating a region with the
|
||||
\fBcreate\fP command. Depending on the size of the areas and the device
|
||||
region the final area within the region may be smaller than requested.
|
||||
.P
|
||||
@ -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
|
||||
@ -822,11 +984,11 @@ when a statistics region is created.
|
||||
.TP
|
||||
.B region_start
|
||||
The region start location. Display units are selected by the
|
||||
\fB\-\-units\fP option.
|
||||
\fB--units\fP option.
|
||||
.TP
|
||||
.B region_len
|
||||
The length of the region. Display units are selected by the
|
||||
\fB\-\-units\fP option.
|
||||
\fB--units\fP option.
|
||||
.TP
|
||||
.B area_id
|
||||
Area identifier. Area identifiers are assigned by the device-mapper
|
||||
@ -839,11 +1001,11 @@ identifiers exist.
|
||||
.TP
|
||||
.B area_start
|
||||
The area start location. Display units are selected by the
|
||||
\fB\-\-units\fP option.
|
||||
\fB--units\fP option.
|
||||
.TP
|
||||
.B area_len
|
||||
The length of the area. Display units are selected by the
|
||||
\fB\-\-units\fP option.
|
||||
\fB--units\fP option.
|
||||
.TP
|
||||
.B area_count
|
||||
The number of areas in this region.
|
||||
@ -995,7 +1157,7 @@ vg00/lvol1: Created new region with 1 area(s) as region ID 0
|
||||
Create a 32M region 1G into device d0
|
||||
.br
|
||||
#
|
||||
.B dmstats create \-\-start 1G \-\-length 32M d0
|
||||
.B dmstats create --start 1G --length 32M d0
|
||||
.br
|
||||
d0: Created new region with 1 area(s) as region ID 0
|
||||
.P
|
||||
@ -1003,7 +1165,7 @@ Create a whole-device region with 8 areas on every device
|
||||
.br
|
||||
.br
|
||||
#
|
||||
.B dmstats create \-\-areas 8
|
||||
.B dmstats create --areas 8
|
||||
.br
|
||||
vg00-lvol1: Created new region with 8 area(s) as region ID 0
|
||||
.br
|
||||
@ -1021,21 +1183,21 @@ Delete all regions on all devices
|
||||
.br
|
||||
.br
|
||||
#
|
||||
.B dmstats delete \-\-alldevices \-\-allregions
|
||||
.B dmstats delete --alldevices --allregions
|
||||
.P
|
||||
Create a whole-device region with areas 10GiB in size on vg00/lvol1
|
||||
using dmsetup
|
||||
.br
|
||||
.br
|
||||
#
|
||||
.B dmsetup stats create \-\-areasize 10G vg00/lvol1
|
||||
.B dmsetup stats create --areasize 10G vg00/lvol1
|
||||
.br
|
||||
vg00-lvol1: Created new region with 5 area(s) as region ID 1
|
||||
.P
|
||||
Create a 1GiB region with 16 areas at the start of vg00/lvol1
|
||||
.br
|
||||
#
|
||||
.B dmstats create \-\-start 0 \-\-len 1G \-\-areas=16 vg00/lvol1
|
||||
.B dmstats create --start 0 --len 1G --areas=16 vg00/lvol1
|
||||
.br
|
||||
vg00-lvol1: Created new region with 16 area(s) as region ID 0
|
||||
.P
|
||||
@ -1056,7 +1218,7 @@ Display five statistics reports for vg00/lvol1 at an interval of one second
|
||||
.br
|
||||
.br
|
||||
#
|
||||
.B dmstats report \-\-interval 1 \-\-count 5 vg00/lvol1
|
||||
.B dmstats report --interval 1 --count 5 vg00/lvol1
|
||||
.br
|
||||
#
|
||||
.B dmstats report
|
||||
@ -1073,7 +1235,7 @@ Create one region for reach target contained in device vg00/lvol1
|
||||
.br
|
||||
.br
|
||||
#
|
||||
.B dmstats create \-\-segments vg00/lvol1
|
||||
.B dmstats create --segments vg00/lvol1
|
||||
.br
|
||||
vg00-lvol1: Created new region with 1 area(s) as region ID 0
|
||||
.br
|
||||
@ -1100,7 +1262,7 @@ images/vm3.img: Created new group with 2 region(s) as group ID 1560.
|
||||
Print raw counters for region 4 on device d0
|
||||
.br
|
||||
#
|
||||
.B dmstats print \-\-regionid 4 d0
|
||||
.B dmstats print --regionid 4 d0
|
||||
.br
|
||||
2097152+65536 0 0 0 0 29 0 264 701 0 41 701 0 41
|
||||
.
|
@ -35,32 +35,32 @@ filesystem.
|
||||
.SH OPTIONS
|
||||
.
|
||||
.HP
|
||||
.BR \-e | \-\-ext\-offline
|
||||
.BR -e | --ext-offline
|
||||
.br
|
||||
Unmount ext2/ext3/ext4 filesystem before doing resize.
|
||||
.
|
||||
.HP
|
||||
.BR \-f | \-\-force
|
||||
.BR -f | --force
|
||||
.br
|
||||
Bypass some sanity checks.
|
||||
.
|
||||
.HP
|
||||
.BR \-h | \-\-help
|
||||
.BR -h | --help
|
||||
.br
|
||||
Display the help text.
|
||||
.
|
||||
.HP
|
||||
.BR \-n | \-\-dry\-run
|
||||
.BR -n | --dry-run
|
||||
.br
|
||||
Print commands without running them.
|
||||
.
|
||||
.HP
|
||||
.BR \-v | \-\-verbose
|
||||
.BR -v | --verbose
|
||||
.br
|
||||
Be more verbose.
|
||||
.
|
||||
.HP
|
||||
.BR \-y | \-\-yes
|
||||
.BR -y | --yes
|
||||
.br
|
||||
Answer "yes" at any prompts.
|
||||
.
|
||||
@ -87,7 +87,7 @@ If \fI/dev/vg/test\fP contains ext2/ext3/ext4
|
||||
filesystem it will be unmounted prior the resize.
|
||||
All [y/n] questions will be answered 'y'.
|
||||
.sp
|
||||
.B fsadm \-e \-y resize /dev/vg/test 1000M
|
||||
.B fsadm -e -y resize /dev/vg/test 1000M
|
||||
.
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.
|
@ -1,6 +1,4 @@
|
||||
.SH EXAMPLES
|
||||
|
||||
Change LV permission to read-only:
|
||||
.sp
|
||||
.B lvchange \-pr vg00/lvol1
|
||||
|
||||
.B lvchange -pr vg00/lvol1
|
1161
man/lvchange.8_pregen
Normal file
1161
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
|
||||
|
64
man/lvconvert.8_des
Normal file
64
man/lvconvert.8_des
Normal file
@ -0,0 +1,64 @@
|
||||
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
|
||||
@ -18,24 +17,22 @@ If LV1 was not a cache pool, the command would convert LV1 to
|
||||
a cache pool, optionally using a specified LV for metadata.
|
||||
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
|
||||
.B lvconvert --type mirror --mirrors 1 vg/lvol1
|
||||
|
||||
Convert a linear LV to a two-way RAID1 LV.
|
||||
.br
|
||||
.B lvconvert \-\-type raid1 \-\-mirrors 1 vg/lvol1
|
||||
.B lvconvert --type raid1 --mirrors 1 vg/lvol1
|
||||
|
||||
Convert a mirror LV to use an in\-memory log.
|
||||
Convert a mirror LV to use an in-memory log.
|
||||
.br
|
||||
.B lvconvert \-\-mirrorlog core vg/lvol1
|
||||
.B lvconvert --mirrorlog core vg/lvol1
|
||||
|
||||
Convert a mirror LV to use a disk log.
|
||||
.br
|
||||
.B lvconvert \-\-mirrorlog disk vg/lvol1
|
||||
.B lvconvert --mirrorlog disk vg/lvol1
|
||||
|
||||
Convert a mirror or raid1 LV to a linear LV.
|
||||
.br
|
||||
@ -43,74 +40,73 @@ Convert a mirror or raid1 LV to a linear LV.
|
||||
|
||||
Convert a mirror LV to a raid1 LV with the same number of images.
|
||||
.br
|
||||
.B lvconvert \-\-type raid1 vg/lvol1
|
||||
.B lvconvert --type raid1 vg/lvol1
|
||||
|
||||
Convert a linear LV to a two-way mirror LV, allocating new extents from specific
|
||||
PV ranges.
|
||||
.br
|
||||
.B lvconvert \-\-mirrors 1 vg/lvol1 /dev/sda:0\-15 /dev/sdb:0\-15
|
||||
.B lvconvert --mirrors 1 vg/lvol1 /dev/sda:0-15 /dev/sdb:0-15
|
||||
|
||||
Convert a mirror LV to a linear LV, freeing physical extents from a specific PV.
|
||||
.br
|
||||
.B lvconvert \-\-type linear vg/lvol1 /dev/sda
|
||||
.B lvconvert --type linear vg/lvol1 /dev/sda
|
||||
|
||||
Split one image from a mirror or raid1 LV, making it a new LV.
|
||||
.br
|
||||
.B lvconvert \-\-splitmirrors 1 \-\-name lv_split vg/lvol1
|
||||
.B lvconvert --splitmirrors 1 --name lv_split vg/lvol1
|
||||
|
||||
Split one image from a raid1 LV, and track changes made to the raid1 LV
|
||||
while the split image remains detached.
|
||||
.br
|
||||
.B lvconvert \-\-splitmirrors 1 \-\-trackchanges vg/lvol1
|
||||
.B lvconvert --splitmirrors 1 --trackchanges vg/lvol1
|
||||
|
||||
Merge an image (that was previously created with \-\-splitmirrors and
|
||||
\-\-trackchanges) back into the original raid1 LV.
|
||||
Merge an image (that was previously created with --splitmirrors and
|
||||
--trackchanges) back into the original raid1 LV.
|
||||
.br
|
||||
.B lvconvert \-\-mergemirrors vg/lvol1_rimage_1
|
||||
.B lvconvert --mergemirrors vg/lvol1_rimage_1
|
||||
|
||||
Replace PV /dev/sdb1 with PV /dev/sdf1 in a raid1/4/5/6/10 LV.
|
||||
.br
|
||||
.B lvconvert \-\-replace /dev/sdb1 vg/lvol1 /dev/sdf1
|
||||
.B lvconvert --replace /dev/sdb1 vg/lvol1 /dev/sdf1
|
||||
|
||||
Replace 3 PVs /dev/sd[b-d]1 with PVs /dev/sd[f-h]1 in a raid1 LV.
|
||||
.br
|
||||
.B lvconvert \-\-replace /dev/sdb1 \-\-replace /dev/sdc1 \-\-replace /dev/sdd1
|
||||
.B lvconvert --replace /dev/sdb1 --replace /dev/sdc1 --replace /dev/sdd1
|
||||
.RS
|
||||
.B vg/lvol1 /dev/sd[fgh]1
|
||||
.RE
|
||||
|
||||
Replace the maximum of 2 PVs /dev/sd[bc]1 with PVs /dev/sd[gh]1 in a raid6 LV.
|
||||
.br
|
||||
.B lvconvert \-\-replace /dev/sdb1 \-\-replace /dev/sdc1 vg/lvol1 /dev/sd[gh]1
|
||||
.B lvconvert --replace /dev/sdb1 --replace /dev/sdc1 vg/lvol1 /dev/sd[gh]1
|
||||
|
||||
Convert an LV into a thin LV in the specified thin pool. The existing LV
|
||||
is used as an external read\-only origin for the new thin LV.
|
||||
is used as an external read-only origin for the new thin LV.
|
||||
.br
|
||||
.B lvconvert \-\-type thin \-\-thinpool vg/tpool1 vg/lvol1
|
||||
.B lvconvert --type thin --thinpool vg/tpool1 vg/lvol1
|
||||
|
||||
Convert an LV into a thin LV in the specified thin pool. The existing LV
|
||||
is used as an external read\-only origin for the new thin LV, and is
|
||||
is used as an external read-only origin for the new thin LV, and is
|
||||
renamed "external".
|
||||
.br
|
||||
.B lvconvert \-\-type thin \-\-thinpool vg/tpool1
|
||||
.B lvconvert --type thin --thinpool vg/tpool1
|
||||
.RS
|
||||
.B \-\-originname external vg/lvol1
|
||||
.B --originname external vg/lvol1
|
||||
.RE
|
||||
|
||||
Convert an LV to a cache pool LV using another specified LV for cache pool
|
||||
metadata.
|
||||
.br
|
||||
.B lvconvert \-\-type cache-pool \-\-poolmetadata vg/poolmeta1 vg/lvol1
|
||||
.B lvconvert --type cache-pool --poolmetadata vg/poolmeta1 vg/lvol1
|
||||
|
||||
Convert an LV to a cache LV using the specified cache pool and chunk size.
|
||||
.br
|
||||
.B lvconvert \-\-type cache \-\-cachepool vg/cpool1 \-c 128 vg/lvol1
|
||||
.B lvconvert --type cache --cachepool vg/cpool1 -c 128 vg/lvol1
|
||||
|
||||
Detach and keep the cache pool from a cache LV.
|
||||
.br
|
||||
.B lvconvert \-\-splitcache vg/lvol1
|
||||
.B lvconvert --splitcache vg/lvol1
|
||||
|
||||
Detach and remove the cache pool from a cache LV.
|
||||
.br
|
||||
.B lvconvert \-\-uncache vg/lvol1
|
||||
|
||||
.B lvconvert --uncache vg/lvol1
|
1877
man/lvconvert.8_pregen
Normal file
1877
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.
|
||||
|
@ -3,56 +3,56 @@
|
||||
Create a striped LV with 3 stripes, a stripe size of 8KiB and a size of 100MiB.
|
||||
The LV name is chosen by lvcreate.
|
||||
.br
|
||||
.B lvcreate \-i 3 \-I 8 \-L 100m vg00
|
||||
.B lvcreate -i 3 -I 8 -L 100m vg00
|
||||
|
||||
Create a raid1 LV with two images, and a useable size of 500 MiB. This
|
||||
operation requires two devices, one for each mirror image. RAID metadata
|
||||
(superblock and bitmap) is also included on the two devices.
|
||||
.br
|
||||
.B lvcreate \-\-type raid1 \-m1 \-L 500m \-n mylv vg00
|
||||
.B lvcreate --type raid1 -m1 -L 500m -n mylv vg00
|
||||
|
||||
Create a mirror LV with two images, and a useable size of 500 MiB.
|
||||
This operation requires three devices: two for mirror images and
|
||||
one for a disk log.
|
||||
.br
|
||||
.B lvcreate \-\-type mirror \-m1 \-L 500m \-n mylv vg00
|
||||
.B lvcreate --type mirror -m1 -L 500m -n mylv vg00
|
||||
|
||||
Create a mirror LV with 2 images, and a useable size of 500 MiB.
|
||||
This operation requires 2 devices because the log is in memory.
|
||||
.br
|
||||
.B lvcreate \-\-type mirror \-m1 \-\-mirrorlog core \-L 500m \-n mylv vg00
|
||||
.B lvcreate --type mirror -m1 --mirrorlog core -L 500m -n mylv vg00
|
||||
|
||||
Create a copy\-on\-write snapshot of an LV:
|
||||
Create a copy-on-write snapshot of an LV:
|
||||
.br
|
||||
.B lvcreate \-\-snapshot \-\-size 100m \-\-name mysnap vg00/mylv
|
||||
.B lvcreate --snapshot --size 100m --name mysnap vg00/mylv
|
||||
|
||||
Create a copy\-on\-write snapshot with a size sufficient
|
||||
Create a copy-on-write snapshot with a size sufficient
|
||||
for overwriting 20% of the size of the original LV.
|
||||
.br
|
||||
.B lvcreate \-s \-l 20%ORIGIN \-n mysnap vg00/mylv
|
||||
.B lvcreate -s -l 20%ORIGIN -n mysnap vg00/mylv
|
||||
|
||||
Create a sparse LV with 1TiB of virtual space, and actual space just under
|
||||
100MiB.
|
||||
.br
|
||||
.B lvcreate \-\-snapshot \-\-virtualsize 1t \-\-size 100m \-\-name mylv vg00
|
||||
.B lvcreate --snapshot --virtualsize 1t --size 100m --name mylv vg00
|
||||
|
||||
Create a linear LV with a usable size of 64MiB on specific physical extents.
|
||||
.br
|
||||
.B lvcreate \-L 64m \-n mylv vg00 /dev/sda:0\-7 /dev/sdb:0\-7
|
||||
.B lvcreate -L 64m -n mylv vg00 /dev/sda:0-7 /dev/sdb:0-7
|
||||
|
||||
Create a RAID5 LV with a usable size of 5GiB, 3 stripes, a stripe size of
|
||||
64KiB, using a total of 4 devices (including one for parity).
|
||||
.br
|
||||
.B lvcreate \-\-type raid5 \-L 5G \-i 3 \-I 64 \-n mylv vg00
|
||||
.B lvcreate --type raid5 -L 5G -i 3 -I 64 -n mylv vg00
|
||||
|
||||
Create a RAID5 LV using all of the free space in the VG and spanning all the
|
||||
PVs in the VG (note that the command will fail if there are more than 8 PVs in
|
||||
the VG, in which case \fB\-i 7\fP must be used to get to the current maximum of
|
||||
the VG, in which case \fB-i 7\fP must be used to get to the current maximum of
|
||||
8 devices including parity for RaidLVs).
|
||||
.br
|
||||
.B lvcreate \-\-config allocation/raid_stripe_all_devices=1
|
||||
.B lvcreate --config allocation/raid_stripe_all_devices=1
|
||||
.RS
|
||||
.B \-\-type raid5 \-l 100%FREE \-n mylv vg00
|
||||
.B --type raid5 -l 100%FREE -n mylv vg00
|
||||
.RE
|
||||
|
||||
Create RAID10 LV with a usable size of 5GiB, using 2 stripes, each on
|
||||
@ -62,37 +62,36 @@ differently:
|
||||
but \fB-m\fP specifies the number of images in addition
|
||||
to the first image).
|
||||
.br
|
||||
.B lvcreate \-\-type raid10 \-L 5G \-i 2 \-m 1 \-n mylv vg00
|
||||
.B lvcreate --type raid10 -L 5G -i 2 -m 1 -n mylv vg00
|
||||
|
||||
Create a 1TiB thin LV, first creating a new thin pool for it, where
|
||||
the thin pool has 100MiB of space, uses 2 stripes, has a 64KiB stripe
|
||||
size, and 256KiB chunk size.
|
||||
.br
|
||||
.B lvcreate \-\-type thin \-\-name mylv \-\-thinpool mypool
|
||||
.B lvcreate --type thin --name mylv --thinpool mypool
|
||||
.RS
|
||||
.B \-V 1t \-L 100m \-i 2 \-I 64 \-c 256 vg00
|
||||
.B -V 1t -L 100m -i 2 -I 64 -c 256 vg00
|
||||
.RE
|
||||
|
||||
Create a thin snapshot of a thin LV (the size option must not be
|
||||
used, otherwise a copy-on-write snapshot would be created).
|
||||
.br
|
||||
.B lvcreate \-\-snapshot \-\-name mysnap vg00/thinvol
|
||||
.B lvcreate --snapshot --name mysnap vg00/thinvol
|
||||
|
||||
Create a thin snapshot of the read-only inactive LV named "origin"
|
||||
which becomes an external origin for the thin snapshot LV.
|
||||
.br
|
||||
.B lvcreate \-\-snapshot \-\-name mysnap \-\-thinpool mypool vg00/origin
|
||||
.B lvcreate --snapshot --name mysnap --thinpool mypool vg00/origin
|
||||
|
||||
Create a cache pool from a fast physical device. The cache pool can
|
||||
then be used to cache an LV.
|
||||
.br
|
||||
.B lvcreate \-\-type cache-pool \-L 1G \-n my_cpool vg00 /dev/fast1
|
||||
.B lvcreate --type cache-pool -L 1G -n my_cpool vg00 /dev/fast1
|
||||
|
||||
Create a cache LV, first creating a new origin LV on a slow physical device,
|
||||
then combining the new origin LV with an existing cache pool.
|
||||
.br
|
||||
.B lvcreate \-\-type cache \-\-cachepool my_cpool
|
||||
.B lvcreate --type cache --cachepool my_cpool
|
||||
.RS
|
||||
.B \-L 100G \-n mylv vg00 /dev/slow1
|
||||
.B -L 100G -n mylv vg00 /dev/slow1
|
||||
.RE
|
||||
|
2738
man/lvcreate.8_pregen
Normal file
2738
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
579
man/lvdisplay.8_pregen
Normal file
579
man/lvdisplay.8_pregen
Normal file
@ -0,0 +1,579 @@
|
||||
.TH LVDISPLAY 8 "LVM TOOLS #VERSION#" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
lvdisplay - Display information about a logical volume
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
\fBlvdisplay\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
[ \fIposition_args\fP ]
|
||||
.br
|
||||
.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.
|
||||
.SH USAGE
|
||||
\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
|
||||
.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.
|
||||
Use separate lists of fields to add, remove or compact by repeating the -o option:
|
||||
-o+field1,field2 -o-field3,field4 -o#field5.
|
||||
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
|
||||
.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
|
||||
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,16 +1,14 @@
|
||||
.SH EXAMPLES
|
||||
|
||||
Extend the size of an LV by 54MiB, using a specific PV.
|
||||
.br
|
||||
.B lvextend \-L +54 vg01/lvol10 /dev/sdk3
|
||||
.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.
|
||||
"-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
|
||||
|
||||
.B lvextend -L+16m vg01/lvol01 /dev/sda:8-9 /dev/sdb:8-9
|
712
man/lvextend.8_pregen
Normal file
712
man/lvextend.8_pregen
Normal file
@ -0,0 +1,712 @@
|
||||
.TH LVEXTEND 8 "LVM TOOLS #VERSION#" "Red Hat, Inc."
|
||||
.SH NAME
|
||||
lvextend - Add space to a logical volume
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
\fBlvextend\fP \fIoption_args\fP \fIposition_args\fP
|
||||
.br
|
||||
[ \fIoption_args\fP ]
|
||||
.br
|
||||
[ \fIposition_args\fP ]
|
||||
.br
|
||||
.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
|
||||
.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.
|
||||
.SH USAGE
|
||||
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
|
||||
-
|
||||
|
||||
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
|
||||
-
|
||||
|
||||
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
|
||||
-
|
||||
|
||||
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
|
||||
-
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
.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: 2, 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
|
||||
.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
|
||||
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)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user