
29 changed files with 9212 additions and 82 deletions
@ -0,0 +1,239 @@
@@ -0,0 +1,239 @@
|
||||
conf/example.conf.in | 20 ++++++++++++++++---- |
||||
man/pvcreate.8_pregen | 7 ++++--- |
||||
man/vgcfgrestore.8_pregen | 9 +++++---- |
||||
man/vgconvert.8_pregen | 14 +++++++++----- |
||||
man/vgcreate.8_pregen | 7 ++++--- |
||||
man/vgextend.8_pregen | 7 ++++--- |
||||
man/vgsplit.8_pregen | 7 ++++--- |
||||
7 files changed, 46 insertions(+), 25 deletions(-) |
||||
|
||||
diff --git a/conf/example.conf.in b/conf/example.conf.in |
||||
index cd58615..742812c 100644 |
||||
--- a/conf/example.conf.in |
||||
+++ b/conf/example.conf.in |
||||
@@ -702,17 +702,29 @@ global { |
||||
activation = 1 |
||||
|
||||
# Configuration option global/fallback_to_lvm1. |
||||
- # This setting is no longer used. |
||||
+ # Try running LVM1 tools if LVM cannot communicate with DM. |
||||
+ # This option only applies to 2.4 kernels and is provided to help |
||||
+ # switch between device-mapper kernels and LVM1 kernels. The LVM1 |
||||
+ # tools need to be installed with .lvm1 suffices, e.g. vgscan.lvm1. |
||||
+ # They will stop working once the lvm2 on-disk metadata format is used. |
||||
# This configuration option has an automatic default value. |
||||
- # fallback_to_lvm1 = 0 |
||||
+ # fallback_to_lvm1 = @DEFAULT_FALLBACK_TO_LVM1@ |
||||
|
||||
# Configuration option global/format. |
||||
- # This setting is no longer used. |
||||
+ # The default metadata format that commands should use. |
||||
+ # The -M 1|2 option overrides this setting. |
||||
+ # |
||||
+ # Accepted values: |
||||
+ # lvm1 |
||||
+ # lvm2 |
||||
+ # |
||||
# This configuration option has an automatic default value. |
||||
# format = "lvm2" |
||||
|
||||
# Configuration option global/format_libraries. |
||||
- # This setting is no longer used. |
||||
+ # Shared libraries that process different metadata formats. |
||||
+ # If support for LVM1 metadata was compiled as a shared library use |
||||
+ # format_libraries = "liblvm2format1.so" |
||||
# This configuration option does not have a default value defined. |
||||
|
||||
# Configuration option global/segment_libraries. |
||||
diff --git a/man/pvcreate.8_pregen b/man/pvcreate.8_pregen |
||||
index c4b03da..abceb82 100644 |
||||
--- a/man/pvcreate.8_pregen |
||||
+++ b/man/pvcreate.8_pregen |
||||
@@ -38,7 +38,7 @@ normally prevent it, e.g. if the PV is already in a VG. |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ] |
||||
+[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ] |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
@@ -266,11 +266,12 @@ The size may be rounded. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP |
||||
+\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP |
||||
.br |
||||
Specifies the type of on-disk metadata to use. |
||||
\fBlvm2\fP (or just \fB2\fP) is the current, standard format. |
||||
-\fBlvm1\fP (or just \fB1\fP) is no longer used. |
||||
+\fBlvm1\fP (or just \fB1\fP) is a historical format that |
||||
+can be used for accessing old data. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
diff --git a/man/vgcfgrestore.8_pregen b/man/vgcfgrestore.8_pregen |
||||
index cffd44b..e028103 100644 |
||||
--- a/man/vgcfgrestore.8_pregen |
||||
+++ b/man/vgcfgrestore.8_pregen |
||||
@@ -51,7 +51,7 @@ vgcfgrestore - Restore volume group configuration |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
- \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP |
||||
+ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
@@ -141,7 +141,7 @@ Common options for command: |
||||
. |
||||
.RS 4 |
||||
.ad l |
||||
-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ] |
||||
+[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ] |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
@@ -280,11 +280,12 @@ Display long help text. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP |
||||
+\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP |
||||
.br |
||||
Specifies the type of on-disk metadata to use. |
||||
\fBlvm2\fP (or just \fB2\fP) is the current, standard format. |
||||
-\fBlvm1\fP (or just \fB1\fP) is no longer used. |
||||
+\fBlvm1\fP (or just \fB1\fP) is a historical format that |
||||
+can be used for accessing old data. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
diff --git a/man/vgconvert.8_pregen b/man/vgconvert.8_pregen |
||||
index 5e7f8a9..6228087 100644 |
||||
--- a/man/vgconvert.8_pregen |
||||
+++ b/man/vgconvert.8_pregen |
||||
@@ -8,9 +8,12 @@ vgconvert - Change volume group metadata format |
||||
[ \fIoption_args\fP ] |
||||
.br |
||||
.SH DESCRIPTION |
||||
-vgconvert converts VG metadata from one format to another. This command |
||||
-is no longer used because this version of lvm no longer supports the LVM1 |
||||
+vgconvert converts VG metadata from one format to another. The new |
||||
+metadata format must be able to fit into the space provided by the old |
||||
format. |
||||
+ |
||||
+Because the LVM1 format should no longer be used, this command is no |
||||
+longer needed in general. |
||||
.SH USAGE |
||||
\fBvgconvert\fP \fIVG\fP ... |
||||
.br |
||||
@@ -20,7 +23,7 @@ format. |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ] |
||||
+[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ] |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
@@ -191,11 +194,12 @@ The size may be rounded. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP |
||||
+\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP |
||||
.br |
||||
Specifies the type of on-disk metadata to use. |
||||
\fBlvm2\fP (or just \fB2\fP) is the current, standard format. |
||||
-\fBlvm1\fP (or just \fB1\fP) is no longer used. |
||||
+\fBlvm1\fP (or just \fB1\fP) is a historical format that |
||||
+can be used for accessing old data. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
diff --git a/man/vgcreate.8_pregen b/man/vgcreate.8_pregen |
||||
index 09bf126..ddad391 100644 |
||||
--- a/man/vgcreate.8_pregen |
||||
+++ b/man/vgcreate.8_pregen |
||||
@@ -33,7 +33,7 @@ devices are also available with vgcreate. |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ] |
||||
+[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ] |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
@@ -324,11 +324,12 @@ The size may be rounded. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP |
||||
+\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP |
||||
.br |
||||
Specifies the type of on-disk metadata to use. |
||||
\fBlvm2\fP (or just \fB2\fP) is the current, standard format. |
||||
-\fBlvm1\fP (or just \fB1\fP) is no longer used. |
||||
+\fBlvm1\fP (or just \fB1\fP) is a historical format that |
||||
+can be used for accessing old data. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
diff --git a/man/vgextend.8_pregen b/man/vgextend.8_pregen |
||||
index a6a30e9..ee805a8 100644 |
||||
--- a/man/vgextend.8_pregen |
||||
+++ b/man/vgextend.8_pregen |
||||
@@ -36,7 +36,7 @@ will initialize them. In this case pvcreate options can be used, e.g. |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ] |
||||
+[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ] |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
@@ -237,11 +237,12 @@ The size may be rounded. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP |
||||
+\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP |
||||
.br |
||||
Specifies the type of on-disk metadata to use. |
||||
\fBlvm2\fP (or just \fB2\fP) is the current, standard format. |
||||
-\fBlvm1\fP (or just \fB1\fP) is no longer used. |
||||
+\fBlvm1\fP (or just \fB1\fP) is a historical format that |
||||
+can be used for accessing old data. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
diff --git a/man/vgsplit.8_pregen b/man/vgsplit.8_pregen |
||||
index 6c3e6ec..210c266 100644 |
||||
--- a/man/vgsplit.8_pregen |
||||
+++ b/man/vgsplit.8_pregen |
||||
@@ -62,7 +62,7 @@ Common options for command: |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
-[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ] |
||||
+[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ] |
||||
.ad b |
||||
.br |
||||
.ad l |
||||
@@ -230,11 +230,12 @@ and --vgmetadatacopies for improving performance. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
-\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP |
||||
+\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP |
||||
.br |
||||
Specifies the type of on-disk metadata to use. |
||||
\fBlvm2\fP (or just \fB2\fP) is the current, standard format. |
||||
-\fBlvm1\fP (or just \fB1\fP) is no longer used. |
||||
+\fBlvm1\fP (or just \fB1\fP) is a historical format that |
||||
+can be used for accessing old data. |
||||
.ad b |
||||
.HP |
||||
.ad l |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
From b6608e0f8426ad334a9eb2f6e1c9a1cfced0536e Mon Sep 17 00:00:00 2001 |
||||
From: Marian Csontos <mcsontos@redhat.com> |
||||
Date: Tue, 31 Jul 2018 17:02:47 +0200 |
||||
Subject: [PATCH 1/2] Update WHATS_NEW |
||||
|
||||
--- |
||||
WHATS_NEW | 7 +++++-- |
||||
1 file changed, 5 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 3b15325..546d3e6 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,7 +1,10 @@ |
||||
Version 2.02.181 - |
||||
================================= |
||||
- lvconvert: reject conversions on raid1 LVs with split tracked SubLVs |
||||
- lvconvert: reject conversions on raid1 split tracked SubLVs |
||||
+ Reject conversions on raid1 LVs with split tracked SubLVs. |
||||
+ Reject conversions on raid1 split tracked SubLVs. |
||||
+ Fix dmstats list failing when no regions exist. |
||||
+ Reject conversions of LVs under snapshot. |
||||
+ Limit suggested options on incorrect option for lvconvert subcommand. |
||||
|
||||
Version 2.02.180 - 19th July 2018 |
||||
================================= |
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
From fc32d2b1b62eb9b75c246efd9c8e514b39f7bd3e Mon Sep 17 00:00:00 2001 |
||||
From: Marian Csontos <mcsontos@redhat.com> |
||||
Date: Tue, 31 Jul 2018 17:36:04 +0200 |
||||
Subject: [PATCH] build: make generate |
||||
|
||||
(cherry picked from commit 12dfd0ed02e003e21072798d17dcec4a80fc466d) |
||||
--- |
||||
man/lvconvert.8_pregen | 14 +++++++++----- |
||||
1 file changed, 9 insertions(+), 5 deletions(-) |
||||
|
||||
diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen |
||||
index 91691a3..a47127b 100644 |
||||
--- a/man/lvconvert.8_pregen |
||||
+++ b/man/lvconvert.8_pregen |
||||
@@ -475,7 +475,7 @@ Split images from a raid1 or mirror LV and use them to create a new LV. |
||||
.RE |
||||
- |
||||
|
||||
-Split images from a raid1 LV and track changes to origin. |
||||
+Split images from a raid1 LV and track changes to origin for later merge. |
||||
.br |
||||
.P |
||||
\fBlvconvert\fP \fB--splitmirrors\fP \fINumber\fP \fB--trackchanges\fP \fILV\fP\fI_cache_raid1\fP |
||||
@@ -1281,6 +1281,8 @@ Before the separation, the cache is flushed. Also see --uncache. |
||||
Splits the specified number of images from a raid1 or mirror LV |
||||
and uses them to create a new LV. If --trackchanges is also specified, |
||||
changes to the raid1 LV are tracked while the split LV remains detached. |
||||
+If --name is specified, then the images are permanently split from the |
||||
+original LV and changes are not tracked. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
@@ -1354,10 +1356,12 @@ The name of a thin pool LV. |
||||
.br |
||||
Can be used with --splitmirrors on a raid1 LV. This causes |
||||
changes to the original raid1 LV to be tracked while the split images |
||||
-remain detached. This allows the read-only detached image(s) to be |
||||
-merged efficiently back into the raid1 LV later. Only the regions with |
||||
-changed data are resynchronized during merge. (This option only applies |
||||
-when using the raid1 LV type.) |
||||
+remain detached. This is a temporary state that allows the read-only |
||||
+detached image to be merged efficiently back into the raid1 LV later. |
||||
+Only the regions with changed data are resynchronized during merge. |
||||
+While a raid1 LV is tracking changes, operations on it are limited to |
||||
+merging the split image (see --mergemirrors) or permanently splitting |
||||
+the image (see --splitmirrors with --name. |
||||
.ad b |
||||
.HP |
||||
.ad l |
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,562 @@
@@ -0,0 +1,562 @@
|
||||
WHATS_NEW_DM | 1 + |
||||
configure | 3 +- |
||||
configure.ac | 1 + |
||||
daemons/dmeventd/libdevmapper-event.c | 1 + |
||||
daemons/dmeventd/plugins/Makefile.in | 9 +- |
||||
daemons/dmeventd/plugins/vdo/.exported_symbols | 3 + |
||||
daemons/dmeventd/plugins/vdo/Makefile.in | 36 +++ |
||||
daemons/dmeventd/plugins/vdo/dmeventd_vdo.c | 406 +++++++++++++++++++++++++ |
||||
8 files changed, 453 insertions(+), 7 deletions(-) |
||||
create mode 100644 daemons/dmeventd/plugins/vdo/.exported_symbols |
||||
create mode 100644 daemons/dmeventd/plugins/vdo/Makefile.in |
||||
create mode 100644 daemons/dmeventd/plugins/vdo/dmeventd_vdo.c |
||||
|
||||
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM |
||||
index e77352a..c42ee17 100644 |
||||
--- a/WHATS_NEW_DM |
||||
+++ b/WHATS_NEW_DM |
||||
@@ -1,5 +1,6 @@ |
||||
Version 1.02.150 - |
||||
================================= |
||||
+ Add vdo plugin for monitoring VDO devices. |
||||
|
||||
Version 1.02.149 - 19th July 2018 |
||||
================================= |
||||
diff --git a/configure b/configure |
||||
index 10b49c6..eb7d70b 100755 |
||||
--- a/configure |
||||
+++ b/configure |
||||
@@ -15648,7 +15648,7 @@ _ACEOF |
||||
|
||||
|
||||
################################################################################ |
||||
-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/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile device_mapper/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 include/lvm-version.h 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/api/python_lvm_unit.py test/unit/Makefile tools/Makefile udev/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/dmeventd/plugins/vdo/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile device_mapper/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 include/lvm-version.h 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/api/python_lvm_unit.py test/unit/Makefile tools/Makefile udev/Makefile" |
||||
|
||||
cat >confcache <<\_ACEOF |
||||
# This file is a shell script that caches the results of configure |
||||
@@ -16356,6 +16356,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/dmeventd/plugins/vdo/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/vdo/Makefile" ;; |
||||
"daemons/dmfilemapd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmfilemapd/Makefile" ;; |
||||
"daemons/lvmdbusd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/Makefile" ;; |
||||
"daemons/lvmdbusd/lvmdbusd") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/lvmdbusd" ;; |
||||
diff --git a/configure.ac b/configure.ac |
||||
index 9fa0c76..24bae39 100644 |
||||
--- a/configure.ac |
||||
+++ b/configure.ac |
||||
@@ -2155,6 +2155,7 @@ daemons/dmeventd/plugins/raid/Makefile |
||||
daemons/dmeventd/plugins/mirror/Makefile |
||||
daemons/dmeventd/plugins/snapshot/Makefile |
||||
daemons/dmeventd/plugins/thin/Makefile |
||||
+daemons/dmeventd/plugins/vdo/Makefile |
||||
daemons/dmfilemapd/Makefile |
||||
daemons/lvmdbusd/Makefile |
||||
daemons/lvmdbusd/lvmdbusd |
||||
diff --git a/daemons/dmeventd/libdevmapper-event.c b/daemons/dmeventd/libdevmapper-event.c |
||||
index 9aeb4c5..f9a8a2b 100644 |
||||
--- a/daemons/dmeventd/libdevmapper-event.c |
||||
+++ b/daemons/dmeventd/libdevmapper-event.c |
||||
@@ -645,6 +645,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh) |
||||
uuid = dm_task_get_uuid(dmt); |
||||
|
||||
if (!strstr(dmevh->dso, "libdevmapper-event-lvm2thin.so") && |
||||
+ !strstr(dmevh->dso, "libdevmapper-event-lvm2vdo.so") && |
||||
!strstr(dmevh->dso, "libdevmapper-event-lvm2snapshot.so") && |
||||
!strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") && |
||||
!strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so")) |
||||
diff --git a/daemons/dmeventd/plugins/Makefile.in b/daemons/dmeventd/plugins/Makefile.in |
||||
index 27edf55..951dd2b 100644 |
||||
--- a/daemons/dmeventd/plugins/Makefile.in |
||||
+++ b/daemons/dmeventd/plugins/Makefile.in |
||||
@@ -1,6 +1,6 @@ |
||||
# |
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
||||
-# Copyright (C) 2004-2005, 2011 Red Hat, Inc. All rights reserved. |
||||
+# Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved. |
||||
# |
||||
# This file is part of LVM2. |
||||
# |
||||
@@ -16,11 +16,7 @@ srcdir = @srcdir@ |
||||
top_srcdir = @top_srcdir@ |
||||
top_builddir = @top_builddir@ |
||||
|
||||
-SUBDIRS += lvm2 snapshot raid thin mirror |
||||
- |
||||
-ifeq ($(MAKECMDGOALS),distclean) |
||||
- SUBDIRS = lvm2 mirror snapshot raid thin |
||||
-endif |
||||
+SUBDIRS += lvm2 snapshot raid thin mirror vdo |
||||
|
||||
include $(top_builddir)/make.tmpl |
||||
|
||||
@@ -28,3 +24,4 @@ snapshot: lvm2 |
||||
mirror: lvm2 |
||||
raid: lvm2 |
||||
thin: lvm2 |
||||
+vdo: lvm2 |
||||
diff --git a/daemons/dmeventd/plugins/vdo/.exported_symbols b/daemons/dmeventd/plugins/vdo/.exported_symbols |
||||
new file mode 100644 |
||||
index 0000000..b88c705 |
||||
--- /dev/null |
||||
+++ b/daemons/dmeventd/plugins/vdo/.exported_symbols |
||||
@@ -0,0 +1,3 @@ |
||||
+process_event |
||||
+register_device |
||||
+unregister_device |
||||
diff --git a/daemons/dmeventd/plugins/vdo/Makefile.in b/daemons/dmeventd/plugins/vdo/Makefile.in |
||||
new file mode 100644 |
||||
index 0000000..bda738a |
||||
--- /dev/null |
||||
+++ b/daemons/dmeventd/plugins/vdo/Makefile.in |
||||
@@ -0,0 +1,36 @@ |
||||
+# |
||||
+# Copyright (C) 2018 Red Hat, Inc. All rights reserved. |
||||
+# |
||||
+# This file is part of LVM2. |
||||
+# |
||||
+# This copyrighted material is made available to anyone wishing to use, |
||||
+# modify, copy, or redistribute it subject to the terms and conditions |
||||
+# of the GNU 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 |
||||
+ |
||||
+srcdir = @srcdir@ |
||||
+top_srcdir = @top_srcdir@ |
||||
+top_builddir = @top_builddir@ |
||||
+ |
||||
+INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2 |
||||
+CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2 |
||||
+ |
||||
+SOURCES = dmeventd_vdo.c |
||||
+ |
||||
+LIB_NAME = libdevmapper-event-lvm2vdo |
||||
+LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) |
||||
+LIB_VERSION = $(LIB_VERSION_LVM) |
||||
+ |
||||
+CFLOW_LIST = $(SOURCES) |
||||
+CFLOW_LIST_TARGET = $(LIB_NAME).cflow |
||||
+ |
||||
+include $(top_builddir)/make.tmpl |
||||
+ |
||||
+LIBS += -ldevmapper-event-lvm2 $(INTERNAL_LIBS) |
||||
+ |
||||
+install_lvm2: install_dm_plugin |
||||
+ |
||||
+install: install_lvm2 |
||||
diff --git a/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c |
||||
new file mode 100644 |
||||
index 0000000..d77ca79 |
||||
--- /dev/null |
||||
+++ b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c |
||||
@@ -0,0 +1,406 @@ |
||||
+/* |
||||
+ * Copyright (C) 2018 Red Hat, Inc. All rights reserved. |
||||
+ * |
||||
+ * This file is part of LVM2. |
||||
+ * |
||||
+ * This copyrighted material is made available to anyone wishing to use, |
||||
+ * modify, copy, or redistribute it subject to the terms and conditions |
||||
+ * of the GNU Lesser General Public License v.2.1. |
||||
+ * |
||||
+ * You should have received a copy of the GNU Lesser General Public License |
||||
+ * along with this program; if not, write to the Free Software Foundation, |
||||
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
+ */ |
||||
+ |
||||
+#include "lib/misc/lib.h" |
||||
+#include "dmeventd_lvm.h" |
||||
+#include "daemons/dmeventd/libdevmapper-event.h" |
||||
+#include "device_mapper/vdo/target.h" |
||||
+ |
||||
+#include <sys/wait.h> |
||||
+#include <stdarg.h> |
||||
+ |
||||
+/* First warning when VDO pool is 80% full. */ |
||||
+#define WARNING_THRESH (DM_PERCENT_1 * 80) |
||||
+/* Run a check every 5%. */ |
||||
+#define CHECK_STEP (DM_PERCENT_1 * 5) |
||||
+/* Do not bother checking VDO pool is less than 50% full. */ |
||||
+#define CHECK_MINIMUM (DM_PERCENT_1 * 50) |
||||
+ |
||||
+#define MAX_FAILS (256) /* ~42 mins between cmd call retry with 10s delay */ |
||||
+ |
||||
+#define VDO_DEBUG 0 |
||||
+ |
||||
+struct dso_state { |
||||
+ struct dm_pool *mem; |
||||
+ int percent_check; |
||||
+ int percent; |
||||
+ uint64_t known_data_size; |
||||
+ unsigned fails; |
||||
+ unsigned max_fails; |
||||
+ int restore_sigset; |
||||
+ sigset_t old_sigset; |
||||
+ pid_t pid; |
||||
+ char *argv[3]; |
||||
+ const char *cmd_str; |
||||
+ const char *name; |
||||
+}; |
||||
+ |
||||
+DM_EVENT_LOG_FN("vdo") |
||||
+ |
||||
+static int _run_command(struct dso_state *state) |
||||
+{ |
||||
+ char val[16]; |
||||
+ int i; |
||||
+ |
||||
+ /* Mark for possible lvm2 command we are running from dmeventd |
||||
+ * lvm2 will not try to talk back to dmeventd while processing it */ |
||||
+ (void) setenv("LVM_RUN_BY_DMEVENTD", "1", 1); |
||||
+ |
||||
+ if (state->percent) { |
||||
+ /* Prepare some known data to env vars for easy use */ |
||||
+ if (dm_snprintf(val, sizeof(val), "%d", |
||||
+ state->percent / DM_PERCENT_1) != -1) |
||||
+ (void) setenv("DMEVENTD_VDO_POOL", val, 1); |
||||
+ } else { |
||||
+ /* For an error event it's for a user to check status and decide */ |
||||
+ log_debug("Error event processing."); |
||||
+ } |
||||
+ |
||||
+ log_verbose("Executing command: %s", state->cmd_str); |
||||
+ |
||||
+ /* TODO: |
||||
+ * Support parallel run of 'task' and it's waitpid maintainence |
||||
+ * ATM we can't handle signaling of SIGALRM |
||||
+ * as signalling is not allowed while 'process_event()' is running |
||||
+ */ |
||||
+ if (!(state->pid = fork())) { |
||||
+ /* child */ |
||||
+ (void) close(0); |
||||
+ for (i = 3; i < 255; ++i) (void) close(i); |
||||
+ execvp(state->argv[0], state->argv); |
||||
+ _exit(errno); |
||||
+ } else if (state->pid == -1) { |
||||
+ log_error("Can't fork command %s.", state->cmd_str); |
||||
+ state->fails = 1; |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
+static int _use_policy(struct dm_task *dmt, struct dso_state *state) |
||||
+{ |
||||
+#if VDO_DEBUG |
||||
+ log_debug("dmeventd executes: %s.", state->cmd_str); |
||||
+#endif |
||||
+ if (state->argv[0]) |
||||
+ return _run_command(state); |
||||
+ |
||||
+ if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) { |
||||
+ log_error("Failed command for %s.", dm_task_get_name(dmt)); |
||||
+ state->fails = 1; |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
+ state->fails = 0; |
||||
+ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
+/* Check if executed command has finished |
||||
+ * Only 1 command may run */ |
||||
+static int _wait_for_pid(struct dso_state *state) |
||||
+{ |
||||
+ int status = 0; |
||||
+ |
||||
+ if (state->pid == -1) |
||||
+ return 1; |
||||
+ |
||||
+ if (!waitpid(state->pid, &status, WNOHANG)) |
||||
+ return 0; |
||||
+ |
||||
+ /* Wait for finish */ |
||||
+ if (WIFEXITED(status)) { |
||||
+ log_verbose("Child %d exited with status %d.", |
||||
+ state->pid, WEXITSTATUS(status)); |
||||
+ state->fails = WEXITSTATUS(status) ? 1 : 0; |
||||
+ } else { |
||||
+ if (WIFSIGNALED(status)) |
||||
+ log_verbose("Child %d was terminated with status %d.", |
||||
+ state->pid, WTERMSIG(status)); |
||||
+ state->fails = 1; |
||||
+ } |
||||
+ |
||||
+ state->pid = -1; |
||||
+ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
+void process_event(struct dm_task *dmt, |
||||
+ enum dm_event_mask event __attribute__((unused)), |
||||
+ void **user) |
||||
+{ |
||||
+ const char *device = dm_task_get_name(dmt); |
||||
+ struct dso_state *state = *user; |
||||
+ void *next = NULL; |
||||
+ uint64_t start, length; |
||||
+ char *target_type = NULL; |
||||
+ char *params; |
||||
+ int needs_policy = 0; |
||||
+ struct dm_task *new_dmt = NULL; |
||||
+ struct dm_vdo_status_parse_result vdop = { .status = NULL }; |
||||
+ |
||||
+#if VDO_DEBUG |
||||
+ log_debug("Watch for VDO %s:%.2f%%.", state->name, |
||||
+ dm_percent_to_round_float(state->percent_check, 2)); |
||||
+#endif |
||||
+ if (!_wait_for_pid(state)) { |
||||
+ log_warn("WARNING: Skipping event, child %d is still running (%s).", |
||||
+ state->pid, state->cmd_str); |
||||
+ return; |
||||
+ } |
||||
+ |
||||
+ if (event & DM_EVENT_DEVICE_ERROR) { |
||||
+#if VDO_DEBUG |
||||
+ log_debug("VDO event error."); |
||||
+#endif |
||||
+ /* Error -> no need to check and do instant resize */ |
||||
+ state->percent = 0; |
||||
+ if (_use_policy(dmt, state)) |
||||
+ goto out; |
||||
+ |
||||
+ stack; |
||||
+ |
||||
+ if (!(new_dmt = dm_task_create(DM_DEVICE_STATUS))) |
||||
+ goto_out; |
||||
+ |
||||
+ if (!dm_task_set_uuid(new_dmt, dm_task_get_uuid(dmt))) |
||||
+ goto_out; |
||||
+ |
||||
+ /* Non-blocking status read */ |
||||
+ if (!dm_task_no_flush(new_dmt)) |
||||
+ log_warn("WARNING: Can't set no_flush for dm status."); |
||||
+ |
||||
+ if (!dm_task_run(new_dmt)) |
||||
+ goto_out; |
||||
+ |
||||
+ dmt = new_dmt; |
||||
+ } |
||||
+ |
||||
+ dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); |
||||
+ |
||||
+ if (!target_type || (strcmp(target_type, "vdo") != 0)) { |
||||
+ log_error("Invalid target type."); |
||||
+ goto out; |
||||
+ } |
||||
+ |
||||
+ if (!dm_vdo_status_parse(state->mem, params, &vdop)) { |
||||
+ log_error("Failed to parse status."); |
||||
+ goto out; |
||||
+ } |
||||
+ |
||||
+ state->percent = dm_make_percent(vdop.status->used_blocks, |
||||
+ vdop.status->total_blocks); |
||||
+ |
||||
+#if VDO_DEBUG |
||||
+ log_debug("VDO %s status %.2f%% " FMTu64 "/" FMTu64 ".", |
||||
+ state->name, dm_percent_to_round_float(state->percent, 2), |
||||
+ vdop.status->used_blocks, vdop.status->total_blocks); |
||||
+#endif |
||||
+ |
||||
+ /* VDO pool size had changed. Clear the threshold. */ |
||||
+ if (state->known_data_size != vdop.status->total_blocks) { |
||||
+ state->percent_check = CHECK_MINIMUM; |
||||
+ state->known_data_size = vdop.status->total_blocks; |
||||
+ state->fails = 0; |
||||
+ } |
||||
+ |
||||
+ /* |
||||
+ * Trigger action when threshold boundary is exceeded. |
||||
+ * Report 80% threshold warning when it's used above 80%. |
||||
+ * Only 100% is exception as it cannot be surpased so policy |
||||
+ * action is called for: >50%, >55% ... >95%, 100% |
||||
+ */ |
||||
+ if ((state->percent > WARNING_THRESH) && |
||||
+ (state->percent > state->percent_check)) |
||||
+ log_warn("WARNING: VDO %s %s is now %.2f%% full.", |
||||
+ state->name, device, |
||||
+ dm_percent_to_round_float(state->percent, 2)); |
||||
+ if (state->percent > CHECK_MINIMUM) { |
||||
+ /* Run action when usage raised more than CHECK_STEP since the last time */ |
||||
+ if (state->percent > state->percent_check) |
||||
+ needs_policy = 1; |
||||
+ state->percent_check = (state->percent / CHECK_STEP + 1) * CHECK_STEP; |
||||
+ if (state->percent_check == DM_PERCENT_100) |
||||
+ state->percent_check--; /* Can't get bigger then 100% */ |
||||
+ } else |
||||
+ state->percent_check = CHECK_MINIMUM; |
||||
+ |
||||
+ /* Reduce number of _use_policy() calls by power-of-2 factor till frequency of MAX_FAILS is reached. |
||||
+ * Avoids too high number of error retries, yet shows some status messages in log regularly. |
||||
+ * i.e. PV could have been pvmoved and VG/LV was locked for a while... |
||||
+ */ |
||||
+ if (state->fails) { |
||||
+ if (state->fails++ <= state->max_fails) { |
||||
+ log_debug("Postponing frequently failing policy (%u <= %u).", |
||||
+ state->fails - 1, state->max_fails); |
||||
+ return; |
||||
+ } |
||||
+ if (state->max_fails < MAX_FAILS) |
||||
+ state->max_fails <<= 1; |
||||
+ state->fails = needs_policy = 1; /* Retry failing command */ |
||||
+ } else |
||||
+ state->max_fails = 1; /* Reset on success */ |
||||
+ |
||||
+ /* FIXME: ATM nothing can be done, drop 0, once it becomes useful */ |
||||
+ if (0 && needs_policy) |
||||
+ _use_policy(dmt, state); |
||||
+out: |
||||
+ if (vdop.status) |
||||
+ dm_pool_free(state->mem, vdop.status); |
||||
+ |
||||
+ if (new_dmt) |
||||
+ dm_task_destroy(new_dmt); |
||||
+} |
||||
+ |
||||
+/* Handle SIGCHLD for a thread */ |
||||
+static void _sig_child(int signum __attribute__((unused))) |
||||
+{ |
||||
+ /* empty SIG_IGN */; |
||||
+} |
||||
+ |
||||
+/* Setup handler for SIGCHLD when executing external command |
||||
+ * to get quick 'waitpid()' reaction |
||||
+ * It will interrupt syscall just like SIGALRM and |
||||
+ * invoke process_event(). |
||||
+ */ |
||||
+static void _init_thread_signals(struct dso_state *state) |
||||
+{ |
||||
+ struct sigaction act = { .sa_handler = _sig_child }; |
||||
+ sigset_t my_sigset; |
||||
+ |
||||
+ sigemptyset(&my_sigset); |
||||
+ |
||||
+ if (sigaction(SIGCHLD, &act, NULL)) |
||||
+ log_warn("WARNING: Failed to set SIGCHLD action."); |
||||
+ else if (sigaddset(&my_sigset, SIGCHLD)) |
||||
+ log_warn("WARNING: Failed to add SIGCHLD to set."); |
||||
+ else if (pthread_sigmask(SIG_UNBLOCK, &my_sigset, &state->old_sigset)) |
||||
+ log_warn("WARNING: Failed to unblock SIGCHLD."); |
||||
+ else |
||||
+ state->restore_sigset = 1; |
||||
+} |
||||
+ |
||||
+static void _restore_thread_signals(struct dso_state *state) |
||||
+{ |
||||
+ if (state->restore_sigset && |
||||
+ pthread_sigmask(SIG_SETMASK, &state->old_sigset, NULL)) |
||||
+ log_warn("WARNING: Failed to block SIGCHLD."); |
||||
+} |
||||
+ |
||||
+int register_device(const char *device, |
||||
+ const char *uuid, |
||||
+ int major __attribute__((unused)), |
||||
+ int minor __attribute__((unused)), |
||||
+ void **user) |
||||
+{ |
||||
+ struct dso_state *state; |
||||
+ const char *cmd; |
||||
+ char *str; |
||||
+ char cmd_str[PATH_MAX + 128 + 2]; /* cmd ' ' vg/lv \0 */ |
||||
+ const char *name = "pool"; |
||||
+ |
||||
+ if (!dmeventd_lvm2_init_with_pool("vdo_pool_state", state)) |
||||
+ goto_bad; |
||||
+ |
||||
+ state->cmd_str = ""; |
||||
+ |
||||
+ /* Search for command for LVM- prefixed devices only */ |
||||
+ cmd = (strncmp(uuid, "LVM-", 4) == 0) ? "_dmeventd_vdo_command" : ""; |
||||
+ |
||||
+ if (!dmeventd_lvm2_command(state->mem, cmd_str, sizeof(cmd_str), cmd, device)) |
||||
+ goto_bad; |
||||
+ |
||||
+ if (strncmp(cmd_str, "lvm ", 4) == 0) { |
||||
+ if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str + 4))) { |
||||
+ log_error("Failed to copy lvm VDO command."); |
||||
+ goto bad; |
||||
+ } |
||||
+ } else if (cmd_str[0] == '/') { |
||||
+ if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str))) { |
||||
+ log_error("Failed to copy VDO command."); |
||||
+ goto bad; |
||||
+ } |
||||
+ |
||||
+ /* Find last space before 'vg/lv' */ |
||||
+ if (!(str = strrchr(state->cmd_str, ' '))) |
||||
+ goto inval; |
||||
+ |
||||
+ if (!(state->argv[0] = dm_pool_strndup(state->mem, state->cmd_str, |
||||
+ str - state->cmd_str))) { |
||||
+ log_error("Failed to copy command."); |
||||
+ goto bad; |
||||
+ } |
||||
+ |
||||
+ state->argv[1] = str + 1; /* 1 argument - vg/lv */ |
||||
+ _init_thread_signals(state); |
||||
+ } else if (cmd[0] == 0) { |
||||
+ state->name = "volume"; /* What to use with 'others?' */ |
||||
+ } else/* Unuspported command format */ |
||||
+ goto inval; |
||||
+ |
||||
+ state->pid = -1; |
||||
+ state->name = name; |
||||
+ *user = state; |
||||
+ |
||||
+ log_info("Monitoring VDO %s %s.", name, device); |
||||
+ |
||||
+ return 1; |
||||
+inval: |
||||
+ log_error("Invalid command for monitoring: %s.", cmd_str); |
||||
+bad: |
||||
+ log_error("Failed to monitor VDO %s %s.", name, device); |
||||
+ |
||||
+ if (state) |
||||
+ dmeventd_lvm2_exit_with_pool(state); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+int unregister_device(const char *device, |
||||
+ const char *uuid __attribute__((unused)), |
||||
+ int major __attribute__((unused)), |
||||
+ int minor __attribute__((unused)), |
||||
+ void **user) |
||||
+{ |
||||
+ struct dso_state *state = *user; |
||||
+ const char *name = state->name; |
||||
+ int i; |
||||
+ |
||||
+ for (i = 0; !_wait_for_pid(state) && (i < 6); ++i) { |
||||
+ if (i == 0) |
||||
+ /* Give it 2 seconds, then try to terminate & kill it */ |
||||
+ log_verbose("Child %d still not finished (%s) waiting.", |
||||
+ state->pid, state->cmd_str); |
||||
+ else if (i == 3) { |
||||
+ log_warn("WARNING: Terminating child %d.", state->pid); |
||||
+ kill(state->pid, SIGINT); |
||||
+ kill(state->pid, SIGTERM); |
||||
+ } else if (i == 5) { |
||||
+ log_warn("WARNING: Killing child %d.", state->pid); |
||||
+ kill(state->pid, SIGKILL); |
||||
+ } |
||||
+ sleep(1); |
||||
+ } |
||||
+ |
||||
+ if (state->pid != -1) |
||||
+ log_warn("WARNING: Cannot kill child %d!", state->pid); |
||||
+ |
||||
+ _restore_thread_signals(state); |
||||
+ |
||||
+ dmeventd_lvm2_exit_with_pool(state); |
||||
+ log_info("No longer monitoring VDO %s %s.", name, device); |
||||
+ |
||||
+ return 1; |
||||
+} |
@ -0,0 +1,94 @@
@@ -0,0 +1,94 @@
|
||||
daemons/dmeventd/plugins/vdo/dmeventd_vdo.c | 39 +++++++++++++++++++---------- |
||||
1 file changed, 26 insertions(+), 13 deletions(-) |
||||
|
||||
diff --git a/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c |
||||
index d77ca79..389632c 100644 |
||||
--- a/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c |
||||
+++ b/daemons/dmeventd/plugins/vdo/dmeventd_vdo.c |
||||
@@ -12,10 +12,9 @@ |
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
-#include "lib/misc/lib.h" |
||||
+#include "lib.h" |
||||
#include "dmeventd_lvm.h" |
||||
-#include "daemons/dmeventd/libdevmapper-event.h" |
||||
-#include "device_mapper/vdo/target.h" |
||||
+#include "libdevmapper-event.h" |
||||
|
||||
#include <sys/wait.h> |
||||
#include <stdarg.h> |
||||
@@ -46,6 +45,23 @@ struct dso_state { |
||||
const char *name; |
||||
}; |
||||
|
||||
+struct vdo_status { |
||||
+ uint64_t used_blocks; |
||||
+ uint64_t total_blocks; |
||||
+}; |
||||
+ |
||||
+static int _vdo_status_parse(const char *params, struct vdo_status *status) |
||||
+{ |
||||
+ if (sscanf(params, "%*s %*s %*s %*s %*s %" PRIu64 " %" PRIu64, |
||||
+ &status->used_blocks, |
||||
+ &status->total_blocks) < 2) { |
||||
+ log_error("Failed to parse vdo params: %s.", params); |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
DM_EVENT_LOG_FN("vdo") |
||||
|
||||
static int _run_command(struct dso_state *state) |
||||
@@ -149,7 +165,7 @@ void process_event(struct dm_task *dmt, |
||||
char *params; |
||||
int needs_policy = 0; |
||||
struct dm_task *new_dmt = NULL; |
||||
- struct dm_vdo_status_parse_result vdop = { .status = NULL }; |
||||
+ struct vdo_status status; |
||||
|
||||
#if VDO_DEBUG |
||||
log_debug("Watch for VDO %s:%.2f%%.", state->name, |
||||
@@ -195,24 +211,24 @@ void process_event(struct dm_task *dmt, |
||||
goto out; |
||||
} |
||||
|
||||
- if (!dm_vdo_status_parse(state->mem, params, &vdop)) { |
||||
+ if (!_vdo_status_parse(params, &status)) { |
||||
log_error("Failed to parse status."); |
||||
goto out; |
||||
} |
||||
|
||||
- state->percent = dm_make_percent(vdop.status->used_blocks, |
||||
- vdop.status->total_blocks); |
||||
+ state->percent = dm_make_percent(status.used_blocks, |
||||
+ status.total_blocks); |
||||
|
||||
#if VDO_DEBUG |
||||
log_debug("VDO %s status %.2f%% " FMTu64 "/" FMTu64 ".", |
||||
state->name, dm_percent_to_round_float(state->percent, 2), |
||||
- vdop.status->used_blocks, vdop.status->total_blocks); |
||||
+ status.used_blocks, status.total_blocks); |
||||
#endif |
||||
|
||||
/* VDO pool size had changed. Clear the threshold. */ |
||||
- if (state->known_data_size != vdop.status->total_blocks) { |
||||
+ if (state->known_data_size != status.total_blocks) { |
||||
state->percent_check = CHECK_MINIMUM; |
||||
- state->known_data_size = vdop.status->total_blocks; |
||||
+ state->known_data_size = status.total_blocks; |
||||
state->fails = 0; |
||||
} |
||||
|
||||
@@ -257,9 +273,6 @@ void process_event(struct dm_task *dmt, |
||||
if (0 && needs_policy) |
||||
_use_policy(dmt, state); |
||||
out: |
||||
- if (vdop.status) |
||||
- dm_pool_free(state->mem, vdop.status); |
||||
- |
||||
if (new_dmt) |
||||
dm_task_destroy(new_dmt); |
||||
} |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
tools/dmsetup.c | 4 +++- |
||||
1 file changed, 3 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/tools/dmsetup.c b/tools/dmsetup.c |
||||
index 95a15dd..3cdf862 100644 |
||||
--- a/tools/dmsetup.c |
||||
+++ b/tools/dmsetup.c |
||||
@@ -939,8 +939,10 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info) |
||||
goto_out; |
||||
|
||||
/* No regions to report is not an error */ |
||||
- if (!dm_stats_get_nr_regions(obj.stats)) |
||||
+ if (!dm_stats_get_nr_regions(obj.stats)) { |
||||
+ r = 1; |
||||
goto out; |
||||
+ } |
||||
} |
||||
|
||||
/* group report with no groups? */ |
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
lib/metadata/raid_manip.c | 4 ++-- |
||||
tools/args.h | 14 +++++++++----- |
||||
tools/command-lines.in | 2 +- |
||||
3 files changed, 12 insertions(+), 8 deletions(-) |
||||
|
||||
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
||||
index 8f78e1a..705a7f9 100644 |
||||
--- a/lib/metadata/raid_manip.c |
||||
+++ b/lib/metadata/raid_manip.c |
||||
@@ -3563,7 +3563,7 @@ int lv_raid_merge(struct logical_volume *image_lv) |
||||
struct volume_group *vg = image_lv->vg; |
||||
|
||||
if (image_lv->status & LVM_WRITE) { |
||||
- log_error("%s is not read-only - refusing to merge.", |
||||
+ log_error("%s cannot be merged because --trackchanges was not used.", |
||||
display_lvname(image_lv)); |
||||
return 0; |
||||
} |
||||
@@ -3572,7 +3572,7 @@ int lv_raid_merge(struct logical_volume *image_lv) |
||||
return_0; |
||||
|
||||
if (!(p = strstr(lv_name, "_rimage_"))) { |
||||
- log_error("Unable to merge non-mirror image %s.", |
||||
+ log_error("Unable to merge non-raid image %s.", |
||||
display_lvname(image_lv)); |
||||
return 0; |
||||
} |
||||
diff --git a/tools/args.h b/tools/args.h |
||||
index b80b8da..abe193c 100644 |
||||
--- a/tools/args.h |
||||
+++ b/tools/args.h |
||||
@@ -611,7 +611,9 @@ arg(splitcache_ARG, '\0', "splitcache", 0, 0, 0, |
||||
arg(splitmirrors_ARG, '\0', "splitmirrors", number_VAL, 0, 0, |
||||
"Splits the specified number of images from a raid1 or mirror LV\n" |
||||
"and uses them to create a new LV. If --trackchanges is also specified,\n" |
||||
- "changes to the raid1 LV are tracked while the split LV remains detached.\n") |
||||
+ "changes to the raid1 LV are tracked while the split LV remains detached.\n" |
||||
+ "If --name is specified, then the images are permanently split from the\n" |
||||
+ "original LV and changes are not tracked.\n") |
||||
|
||||
arg(splitsnapshot_ARG, '\0', "splitsnapshot", 0, 0, 0, |
||||
"Separates a COW snapshot from its origin LV. The LV that is split off\n" |
||||
@@ -691,10 +693,12 @@ arg(thinpool_ARG, '\0', "thinpool", lv_VAL, 0, 0, |
||||
arg(trackchanges_ARG, '\0', "trackchanges", 0, 0, 0, |
||||
"Can be used with --splitmirrors on a raid1 LV. This causes\n" |
||||
"changes to the original raid1 LV to be tracked while the split images\n" |
||||
- "remain detached. This allows the read-only detached image(s) to be\n" |
||||
- "merged efficiently back into the raid1 LV later. Only the regions with\n" |
||||
- "changed data are resynchronized during merge. (This option only applies\n" |
||||
- "when using the raid1 LV type.)\n") |
||||
+ "remain detached. This is a temporary state that allows the read-only\n" |
||||
+ "detached image to be merged efficiently back into the raid1 LV later.\n" |
||||
+ "Only the regions with changed data are resynchronized during merge.\n" |
||||
+ "While a raid1 LV is tracking changes, operations on it are limited to\n" |
||||
+ "merging the split image (see --mergemirrors) or permanently splitting\n" |
||||
+ "the image (see --splitmirrors with --name.\n") |
||||
|
||||
/* TODO: hide this? */ |
||||
arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0, |
||||
diff --git a/tools/command-lines.in b/tools/command-lines.in |
||||
index b7aefa3..a8c06ba 100644 |
||||
--- a/tools/command-lines.in |
||||
+++ b/tools/command-lines.in |
||||
@@ -399,7 +399,7 @@ lvconvert --splitmirrors Number --trackchanges LV_raid1_cache |
||||
OO: OO_LVCONVERT |
||||
OP: PV ... |
||||
ID: lvconvert_split_mirror_images |
||||
-DESC: Split images from a raid1 LV and track changes to origin. |
||||
+DESC: Split images from a raid1 LV and track changes to origin for later merge. |
||||
RULE: all not lv_is_locked lv_is_pvmove |
||||
|
||||
lvconvert --mergemirrors LV_linear_raid|VG|Tag ... |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
tools/lvconvert.c | 6 ++++++ |
||||
1 file changed, 6 insertions(+) |
||||
|
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
||||
index 3ce228f..3fad02c 100644 |
||||
--- a/tools/lvconvert.c |
||||
+++ b/tools/lvconvert.c |
||||
@@ -4256,6 +4256,12 @@ static int _lvconvert_to_pool_or_swap_metadata_single(struct cmd_context *cmd, |
||||
return 0; |
||||
}; |
||||
|
||||
+ if (lv_is_origin(lv)) { |
||||
+ log_error("Cannot convert logical volume %s under snapshot.", |
||||
+ display_lvname(lv)); |
||||
+ return 0; |
||||
+ }; |
||||
+ |
||||
if (cmd->position_argc > 1) { |
||||
/* First pos arg is required LV, remaining are optional PVs. */ |
||||
if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0))) |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
lib/commands/toolcontext.h | 1 + |
||||
tools/command-lines.in | 2 +- |
||||
tools/lvmcmdline.c | 14 ++++++++++++++ |
||||
3 files changed, 16 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h |
||||
index bc05736..da5d582 100644 |
||||
--- a/lib/commands/toolcontext.h |
||||
+++ b/lib/commands/toolcontext.h |
||||
@@ -95,6 +95,7 @@ struct cmd_context { |
||||
char **argv; |
||||
struct arg_values *opt_arg_values; |
||||
struct dm_list arg_value_groups; |
||||
+ int opt_count; /* total number of options (beginning with - or --) */ |
||||
|
||||
/* |
||||
* Position args remaining after command name |
||||
diff --git a/tools/command-lines.in b/tools/command-lines.in |
||||
index 9d407d0..b7aefa3 100644 |
||||
--- a/tools/command-lines.in |
||||
+++ b/tools/command-lines.in |
||||
@@ -700,7 +700,7 @@ RULE: all and lv_is_converting |
||||
# for compat since this was how it used to be done. |
||||
lvconvert LV_mirror_raid |
||||
OO: OO_LVCONVERT |
||||
-ID: lvconvert_start_poll |
||||
+ID: lvconvert_plain |
||||
DESC: Poll LV to continue conversion (also see --startpoll) |
||||
DESC: or waits till conversion/mirror syncing is finished |
||||
FLAGS: SECONDARY_SYNTAX |
||||
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c |
||||
index 0600b1c..c62a66e 100644 |
||||
--- a/tools/lvmcmdline.c |
||||
+++ b/tools/lvmcmdline.c |
||||
@@ -119,6 +119,7 @@ static const struct command_function _command_functions[CMD_COUNT] = { |
||||
|
||||
/* lvconvert utility to trigger polling on an LV. */ |
||||
{ lvconvert_start_poll_CMD, lvconvert_start_poll_cmd }, |
||||
+ { lvconvert_plain_CMD, lvconvert_start_poll_cmd }, |
||||
|
||||
/* lvconvert utilities for creating/maintaining thin and cache objects. */ |
||||
{ lvconvert_to_thinpool_CMD, lvconvert_to_pool_cmd }, |
||||
@@ -1579,6 +1580,17 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path, |
||||
if (arg_is_set(cmd, help_ARG) || arg_is_set(cmd, help2_ARG) || arg_is_set(cmd, longhelp_ARG) || arg_is_set(cmd, version_ARG)) |
||||
return &commands[i]; |
||||
|
||||
+ /* |
||||
+ * The 'lvconvert LV' cmd def matches any lvconvert cmd which throws off |
||||
+ * nearest-command partial-match suggestions. Make it a special case so |
||||
+ * that it won't be used as a close match. If the command has any option |
||||
+ * set (other than -v), don't attempt to match it to 'lvconvert LV'. |
||||
+ */ |
||||
+ if (commands[i].command_enum == lvconvert_plain_CMD) { |
||||
+ if (cmd->opt_count - cmd->opt_arg_values[verbose_ARG].count) |
||||
+ continue; |
||||
+ } |
||||
+ |
||||
match_required = 0; /* required parameters that match */ |
||||
match_ro = 0; /* required opt_args that match */ |
||||
match_rp = 0; /* required pos_args that match */ |
||||
@@ -2097,6 +2109,8 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, char ***arg |
||||
if (goval == '?') |
||||
return 0; |
||||
|
||||
+ cmd->opt_count++; |
||||
+ |
||||
/* |
||||
* translate the option value used by getopt into the enum |
||||
* value (e.g. foo_ARG) from the args array. |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
WHATS_NEW | 3 +++ |
||||
WHATS_NEW_DM | 3 +++ |
||||
2 files changed, 6 insertions(+) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 62a5045..bdd2fa6 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,3 +1,6 @@ |
||||
+Version 2.02.181 - |
||||
+================================= |
||||
+ |
||||
Version 2.02.180 - 19th July 2018 |
||||
================================= |
||||
Never send any discard ioctl with test mode. |
||||
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM |
||||
index 93e4b14..e77352a 100644 |
||||
--- a/WHATS_NEW_DM |
||||
+++ b/WHATS_NEW_DM |
||||
@@ -1,3 +1,6 @@ |
||||
+Version 1.02.150 - |
||||
+================================= |
||||
+ |
||||
Version 1.02.149 - 19th July 2018 |
||||
================================= |
||||
|
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
WHATS_NEW | 1 + |
||||
test/shell/lvconvert-raid1-split-trackchanges.sh | 7 +++++++ |
||||
tools/lvconvert.c | 6 ++++++ |
||||
3 files changed, 14 insertions(+) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 7c74c50..3b15325 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.181 - |
||||
================================= |
||||
+ lvconvert: reject conversions on raid1 LVs with split tracked SubLVs |
||||
lvconvert: reject conversions on raid1 split tracked SubLVs |
||||
|
||||
Version 2.02.180 - 19th July 2018 |
||||
diff --git a/test/shell/lvconvert-raid1-split-trackchanges.sh b/test/shell/lvconvert-raid1-split-trackchanges.sh |
||||
index e25a632..718c254 100644 |
||||
--- a/test/shell/lvconvert-raid1-split-trackchanges.sh |
||||
+++ b/test/shell/lvconvert-raid1-split-trackchanges.sh |
||||
@@ -27,6 +27,13 @@ vgcreate $SHARED -s 512k "$vg" "${DEVICES[@]}" |
||||
lvcreate -y --ty raid1 -m 2 -n $lv1 -l 1 $vg |
||||
lvconvert -y --splitmirrors 1 --trackchanges $vg/$lv1 |
||||
|
||||
+not lvconvert -y --ty linear $vg/$lv1 |
||||
+not lvconvert -y --ty striped -i 3 $vg/$lv1 |
||||
+not lvconvert -y --ty mirror $vg/$lv1 |
||||
+not lvconvert -y --ty raid4 $vg/$lv1 |
||||
+not lvconvert -y --ty raid5 $vg/$lv1 |
||||
+not lvconvert -y --ty raid6 $vg/$lv1 |
||||
+not lvconvert -y --ty raid10 $vg/$lv1 |
||||
not lvconvert -y --ty striped -m 1 $vg/${lv1}_rimage_2 |
||||
not lvconvert -y --ty raid1 -m 1 $vg/${lv1}_rimage_2 |
||||
not lvconvert -y --ty mirror -m 1 $vg/${lv1}_rimage_2 |
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
||||
index 079c3cd..731a210 100644 |
||||
--- a/tools/lvconvert.c |
||||
+++ b/tools/lvconvert.c |
||||
@@ -1170,6 +1170,12 @@ static int _raid_split_image_conversion(struct logical_volume *lv) |
||||
{ |
||||
const char *s; |
||||
|
||||
+ if (lv_is_raid_with_tracking(lv)) { |
||||
+ log_error("Conversion of tracking raid1 LV %s is not supported.", |
||||
+ display_lvname(lv)); |
||||
+ return 1; |
||||
+ } |
||||
+ |
||||
if (lv_is_raid_image(lv) && |
||||
(s = strstr(lv->name, "_rimage_"))) { |
||||
size_t len = s - lv->name; |
@ -0,0 +1,150 @@
@@ -0,0 +1,150 @@
|
||||
WHATS_NEW | 1 + |
||||
test/shell/lvconvert-raid1-split-trackchanges.sh | 36 +++++++++++++++++++ |
||||
tools/lvconvert.c | 45 ++++++++++++++++++++++++ |
||||
3 files changed, 82 insertions(+) |
||||
create mode 100644 test/shell/lvconvert-raid1-split-trackchanges.sh |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index bdd2fa6..7c74c50 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.181 - |
||||
================================= |
||||
+ lvconvert: reject conversions on raid1 split tracked SubLVs |
||||
|
||||
Version 2.02.180 - 19th July 2018 |
||||
================================= |
||||
diff --git a/test/shell/lvconvert-raid1-split-trackchanges.sh b/test/shell/lvconvert-raid1-split-trackchanges.sh |
||||
new file mode 100644 |
||||
index 0000000..e25a632 |
||||
--- /dev/null |
||||
+++ b/test/shell/lvconvert-raid1-split-trackchanges.sh |
||||
@@ -0,0 +1,36 @@ |
||||
+#!/usr/bin/env bash |
||||
+ |
||||
+# Copyright (C) 2018 Red Hat, Inc. All rights reserved. |
||||
+# |
||||
+# This copyrighted material is made available to anyone wishing to use, |
||||
+# modify, copy, or redistribute it subject to the terms and conditions |
||||
+# of the GNU General Public License v.2. |
||||
+# |
||||
+# You should have received a copy of the GNU General Public License |
||||
+# along with this program; if not, write to the Free Software Foundation, |
||||
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
+ |
||||
+ |
||||
+SKIP_WITH_LVMPOLLD=1 |
||||
+ |
||||
+. lib/inittest |
||||
+ |
||||
+# rhbz1579072/rhbz1579438 |
||||
+ |
||||
+aux have_raid 1 3 0 || skip |
||||
+ |
||||
+# 8 PVs needed for RAID10 testing (4-stripes/2-mirror) |
||||
+aux prepare_pvs 4 2 |
||||
+get_devs |
||||
+vgcreate $SHARED -s 512k "$vg" "${DEVICES[@]}" |
||||
+ |
||||
+lvcreate -y --ty raid1 -m 2 -n $lv1 -l 1 $vg |
||||
+lvconvert -y --splitmirrors 1 --trackchanges $vg/$lv1 |
||||
+ |
||||
+not lvconvert -y --ty striped -m 1 $vg/${lv1}_rimage_2 |
||||
+not lvconvert -y --ty raid1 -m 1 $vg/${lv1}_rimage_2 |
||||
+not lvconvert -y --ty mirror -m 1 $vg/${lv1}_rimage_2 |
||||
+not lvconvert -y --ty cache-pool $vg/${lv1}_rimage_2 |
||||
+not lvconvert -y --ty thin-pool $vg/${lv1}_rimage_2 |
||||
+ |
||||
+vgremove -ff $vg |
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
||||
index 3fad02c..079c3cd 100644 |
||||
--- a/tools/lvconvert.c |
||||
+++ b/tools/lvconvert.c |
||||
@@ -1165,6 +1165,36 @@ static int _lvconvert_validate_thin(struct logical_volume *lv, |
||||
return 0; |
||||
} |
||||
|
||||
+/* Check for raid1 split trackchanges image to reject conversions on it. */ |
||||
+static int _raid_split_image_conversion(struct logical_volume *lv) |
||||
+{ |
||||
+ const char *s; |
||||
+ |
||||
+ if (lv_is_raid_image(lv) && |
||||
+ (s = strstr(lv->name, "_rimage_"))) { |
||||
+ size_t len = s - lv->name; |
||||
+ char raidlv_name[len + 1]; |
||||
+ const struct logical_volume *tmp_lv; |
||||
+ |
||||
+ strncpy(raidlv_name, lv->name, len); |
||||
+ raidlv_name[len] = '\0'; |
||||
+ |
||||
+ if (!(tmp_lv = find_lv(lv->vg, raidlv_name))) { |
||||
+ log_error(INTERNAL_ERROR "Failed to find RaidLV of RAID subvolume %s.", |
||||
+ display_lvname(lv)); |
||||
+ return 1; |
||||
+ } |
||||
+ |
||||
+ if (lv_is_raid_with_tracking(tmp_lv)) { |
||||
+ log_error("Conversion of tracked raid1 subvolume %s is not supported.", |
||||
+ display_lvname(lv)); |
||||
+ return 1; |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
/* |
||||
* _lvconvert_mirrors |
||||
* |
||||
@@ -1180,6 +1210,9 @@ static int _lvconvert_mirrors(struct cmd_context *cmd, |
||||
uint32_t new_mimage_count = 0; |
||||
uint32_t new_log_count = 0; |
||||
|
||||
+ if (_raid_split_image_conversion(lv)) |
||||
+ return 0; |
||||
+ |
||||
if ((lp->corelog || lp->mirrorlog) && *lp->type_str && strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR)) { |
||||
log_error("--corelog and --mirrorlog are only compatible with mirror devices."); |
||||
return 0; |
||||
@@ -1296,6 +1329,9 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
||||
struct cmd_context *cmd = lv->vg->cmd; |
||||
struct lv_segment *seg = first_seg(lv); |
||||
|
||||
+ if (_raid_split_image_conversion(lv)) |
||||
+ return 0; |
||||
+ |
||||
if (_linear_type_requested(lp->type_str)) { |
||||
if (arg_is_set(cmd, mirrors_ARG) && (arg_uint_value(cmd, mirrors_ARG, 0) != 0)) { |
||||
log_error("Cannot specify mirrors with linear type."); |
||||
@@ -2579,6 +2615,9 @@ static int _lvconvert_to_thin_with_external(struct cmd_context *cmd, |
||||
.virtual_extents = lv->le_count, |
||||
}; |
||||
|
||||
+ if (_raid_split_image_conversion(lv)) |
||||
+ return 0; |
||||
+ |
||||
if (lv == thinpool_lv) { |
||||
log_error("Can't use same LV %s for thin pool and thin volume.", |
||||
display_lvname(thinpool_lv)); |
||||
@@ -2888,6 +2927,9 @@ static int _lvconvert_to_pool(struct cmd_context *cmd, |
||||
struct id lockd_meta_id; |
||||
const char *str_seg_type = to_cachepool ? SEG_TYPE_NAME_CACHE_POOL : SEG_TYPE_NAME_THIN_POOL; |
||||
|
||||
+ if (_raid_split_image_conversion(lv)) |
||||
+ return 0; |
||||
+ |
||||
if (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) { |
||||
log_error(INTERNAL_ERROR "LV %s is already a pool.", display_lvname(lv)); |
||||
return 0; |
||||
@@ -3339,6 +3381,9 @@ static int _lvconvert_to_cache_vol(struct cmd_context *cmd, |
||||
struct dm_config_tree *policy_settings = NULL; |
||||
int r = 0; |
||||
|
||||
+ if (_raid_split_image_conversion(lv)) |
||||
+ return 0; |
||||
+ |
||||
/* If LV is inactive here, ensure it's not active elsewhere. */ |
||||
if (!lockd_lv(cmd, lv, "ex", 0)) |
||||
return_0; |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
WHATS_NEW | 4 ++++ |
||||
lib/metadata/cache_manip.c | 5 ----- |
||||
2 files changed, 4 insertions(+), 5 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 546d3e6..17aff08 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 2.02.182 - |
||||
+============================== |
||||
+ Do not pair cache policy and cache metadata format. |
||||
+ |
||||
Version 2.02.181 - |
||||
================================= |
||||
Reject conversions on raid1 LVs with split tracked SubLVs. |
||||
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c |
||||
index c15f117..8376bfb 100644 |
||||
--- a/lib/metadata/cache_manip.c |
||||
+++ b/lib/metadata/cache_manip.c |
||||
@@ -843,15 +843,10 @@ int cache_set_metadata_format(struct lv_segment *seg, cache_metadata_format_t fo |
||||
|
||||
/* |
||||
* If policy is unselected, but format 2 is selected, policy smq is enforced. |
||||
- * ATM no other then smq & cleaner policy is allowed to select format 2. |
||||
*/ |
||||
if (!seg->policy_name) { |
||||
if (format == CACHE_METADATA_FORMAT_2) |
||||
seg->policy_name = "smq"; |
||||
- } else if (strcmp(seg->policy_name, "smq") && |
||||
- strcmp(seg->policy_name, "cleaner")) { |
||||
- seg->cache_metadata_format = CACHE_METADATA_FORMAT_1; |
||||
- return 1; |
||||
} |
||||
|
||||
/* Check if we need to search for configured cache metadata format */ |
@ -0,0 +1,131 @@
@@ -0,0 +1,131 @@
|
||||
From 41d8039e12ebad0727f8c7455ad9392bc61e6414 Mon Sep 17 00:00:00 2001 |
||||
From: Zdenek Kabelac <zkabelac@redhat.com> |
||||
Date: Mon, 27 Aug 2018 10:18:26 +0200 |
||||
Subject: [PATCH 1/2] dmeventd: lvm2 plugin uses envvar registry |
||||
|
||||
Thin plugin started to use configuble setting to allow to configure |
||||
usage of external scripts - however to read this value it needed to |
||||
execute internal command as dmeventd itself has no access to lvm.conf |
||||
and the API for dmeventd plugin has been kept stable. |
||||
|
||||
The call of command itself was not normally 'a big issue' until users |
||||
started to use higher number of monitored LVs and execution of command |
||||
got stuck because other monitored resource already started to execute |
||||
some other lvm2 command and become blocked waiting on VG lock. |
||||
|
||||
This scenario revealed necesity to somehow avoid calling lvm2 command |
||||
during resource registration - but this requires bigger changes - so |
||||
meanwhile this patch tries to minimize the possibility to hit this race |
||||
by obtaining any configurable setting just once - such patch is small |
||||
and covers majority of problem - yet better solution needs to be |
||||
introduced likely with bigger rework of dmeventd. |
||||
|
||||
TODO: Avoid blocking registration of resource with execution of lvm2 |
||||
commands since those can get stuck waiting on mutexes. |
||||
|
||||
(cherry picked from commit a8d59404f7713ae4f9a3b172dd560ed1364d8bee) |
||||
|
||||
Conflicts: |
||||
WHATS_NEW_DM |
||||
--- |
||||
WHATS_NEW_DM | 4 +++ |
||||
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c | 49 +++++++++++++++++++++------- |
||||
2 files changed, 42 insertions(+), 11 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM |
||||
index c42ee17..42cf2a8 100644 |
||||
--- a/WHATS_NEW_DM |
||||
+++ b/WHATS_NEW_DM |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 1.02.151 - |
||||
+============================== |
||||
+ Add hot fix to avoiding locking collision when monitoring thin-pools. |
||||
+ |
||||
Version 1.02.150 - |
||||
================================= |
||||
Add vdo plugin for monitoring VDO devices. |
||||
diff --git a/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c b/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c |
||||
index 930f9fc..5be11f1 100644 |
||||
--- a/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c |
||||
+++ b/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c |
||||
@@ -31,6 +31,13 @@ static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER; |
||||
static int _register_count = 0; |
||||
static struct dm_pool *_mem_pool = NULL; |
||||
static void *_lvm_handle = NULL; |
||||
+static DM_LIST_INIT(_env_registry); |
||||
+ |
||||
+struct env_data { |
||||
+ struct dm_list list; |
||||
+ const char *cmd; |
||||
+ const char *data; |
||||
+}; |
||||
|
||||
DM_EVENT_LOG_FN("#lvm") |
||||
|
||||
@@ -100,6 +107,7 @@ void dmeventd_lvm2_exit(void) |
||||
lvm2_run(_lvm_handle, "_memlock_dec"); |
||||
dm_pool_destroy(_mem_pool); |
||||
_mem_pool = NULL; |
||||
+ dm_list_init(&_env_registry); |
||||
lvm2_exit(_lvm_handle); |
||||
_lvm_handle = NULL; |
||||
log_debug("lvm plugin exited."); |
||||
@@ -124,6 +132,8 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size, |
||||
static char _internal_prefix[] = "_dmeventd_"; |
||||
char *vg = NULL, *lv = NULL, *layer; |
||||
int r; |
||||
+ struct env_data *env_data; |
||||
+ const char *env = NULL; |
||||
|
||||
if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) { |
||||
log_error("Unable to determine VG name from %s.", |
||||
@@ -137,18 +147,35 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size, |
||||
*layer = '\0'; |
||||
|
||||
if (!strncmp(cmd, _internal_prefix, sizeof(_internal_prefix) - 1)) { |
||||
- dmeventd_lvm2_lock(); |
||||
- /* output of internal command passed via env var */ |
||||
- if (!dmeventd_lvm2_run(cmd)) |
||||
- cmd = NULL; |
||||
- else if ((cmd = getenv(cmd))) |
||||
- cmd = dm_pool_strdup(mem, cmd); /* copy with lock */ |
||||
- dmeventd_lvm2_unlock(); |
||||
- |
||||
- if (!cmd) { |
||||
- log_error("Unable to find configured command."); |
||||
- return 0; |
||||
+ /* check if ENVVAR wasn't already resolved */ |
||||
+ dm_list_iterate_items(env_data, &_env_registry) |
||||
+ if (!strcmp(cmd, env_data->cmd)) { |
||||
+ env = env_data->data; |
||||
+ break; |
||||
+ } |
||||
+ |
||||
+ if (!env) { |
||||
+ /* run lvm2 command to find out setting value */ |
||||
+ dmeventd_lvm2_lock(); |
||||
+ if (!dmeventd_lvm2_run(cmd) || |
||||
+ !(env = getenv(cmd))) { |
||||
+ log_error("Unable to find configured command."); |
||||
+ return 0; |
||||
+ } |
||||
+ /* output of internal command passed via env var */ |
||||
+ env = dm_pool_strdup(_mem_pool, env); /* copy with lock */ |
||||
+ dmeventd_lvm2_unlock(); |
||||
+ if (!env || |
||||
+ !(env_data = dm_pool_zalloc(_mem_pool, sizeof(*env_data))) || |
||||
+ !(env_data->cmd = dm_pool_strdup(_mem_pool, cmd))) { |
||||
+ log_error("Unable to allocate env memory."); |
||||
+ return 0; |
||||
+ } |
||||
+ env_data->data = env; |
||||
+ /* add to ENVVAR registry */ |
||||
+ dm_list_add(&_env_registry, &env_data->list); |
||||
} |
||||
+ cmd = env; |
||||
} |
||||
|
||||
r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv); |
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,145 @@
@@ -0,0 +1,145 @@
|
||||
WHATS_NEW | 1 + |
||||
lib/activate/activate.c | 3 +-- |
||||
tools/lvchange.c | 28 +++++++++++++++++++--------- |
||||
tools/vgchange.c | 15 +++++++++++++-- |
||||
4 files changed, 34 insertions(+), 13 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index d8a24b0..a1da4b7 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.182 - |
||||
============================== |
||||
+ Fix change of monitoring in clustered volumes. |
||||
Fix lvconvert striped/raid0/raid0_meta -> raid6 regression. |
||||
Add After=rbdmap.service to {lvm2-activation-net,blk-availability}.service. |
||||
Fix lvconvert conversion attempts to linear. |
||||
diff --git a/lib/activate/activate.c b/lib/activate/activate.c |
||||
index 16704f6..0bc857f 100644 |
||||
--- a/lib/activate/activate.c |
||||
+++ b/lib/activate/activate.c |
||||
@@ -2061,8 +2061,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume |
||||
} else |
||||
continue; |
||||
|
||||
- if (!vg_write_lock_held() && lv_is_mirror(lv)) { |
||||
- mirr_laopts.exclusive = lv_is_active_exclusive_locally(lv) ? 1 : 0; |
||||
+ if (!cmd->is_clvmd && !vg_write_lock_held() && lv_is_mirror(lv)) { |
||||
/* |
||||
* Commands vgchange and lvchange do use read-only lock when changing |
||||
* monitoring (--monitor y|n). All other use cases hold 'write-lock' |
||||
diff --git a/tools/lvchange.c b/tools/lvchange.c |
||||
index 6144852..7e5cb5b 100644 |
||||
--- a/tools/lvchange.c |
||||
+++ b/tools/lvchange.c |
||||
@@ -148,7 +148,8 @@ static int _lvchange_pool_update(struct cmd_context *cmd, |
||||
*/ |
||||
|
||||
static int _lvchange_monitoring(struct cmd_context *cmd, |
||||
- struct logical_volume *lv) |
||||
+ struct logical_volume *lv, |
||||
+ int was_refreshed) |
||||
{ |
||||
struct lvinfo info; |
||||
|
||||
@@ -163,8 +164,15 @@ static int _lvchange_monitoring(struct cmd_context *cmd, |
||||
log_verbose("Monitoring LV %s", display_lvname(lv)); |
||||
else |
||||
log_verbose("Unmonitoring LV %s", display_lvname(lv)); |
||||
- if (!monitor_dev_for_events(cmd, lv, 0, dmeventd_monitor_mode())) |
||||
- return_0; |
||||
+ |
||||
+ if (!was_refreshed) { |
||||
+ if (locking_is_clustered()) { |
||||
+ /* FIXME: doesn't work when the LV is not lockholder */ |
||||
+ if (!lv_refresh(cmd, lv)) |
||||
+ return_0; |
||||
+ } else if (!monitor_dev_for_events(cmd, lv, 0, dmeventd_monitor_mode())) |
||||
+ return_0; |
||||
+ } |
||||
} |
||||
|
||||
return 1; |
||||
@@ -176,7 +184,8 @@ static int _lvchange_monitoring(struct cmd_context *cmd, |
||||
*/ |
||||
|
||||
static int _lvchange_background_polling(struct cmd_context *cmd, |
||||
- struct logical_volume *lv) |
||||
+ struct logical_volume *lv, |
||||
+ int was_refreshed) |
||||
{ |
||||
struct lvinfo info; |
||||
|
||||
@@ -187,7 +196,8 @@ static int _lvchange_background_polling(struct cmd_context *cmd, |
||||
|
||||
if (background_polling()) { |
||||
log_verbose("Polling LV %s", display_lvname(lv)); |
||||
- lv_spawn_background_polling(cmd, lv); |
||||
+ if (!was_refreshed) |
||||
+ lv_spawn_background_polling(cmd, lv); |
||||
} |
||||
|
||||
return 1; |
||||
@@ -1444,11 +1454,11 @@ static int _lvchange_refresh_single(struct cmd_context *cmd, |
||||
* checking poll arg. Pull that out of lv_refresh. |
||||
*/ |
||||
if (arg_is_set(cmd, poll_ARG) && |
||||
- !_lvchange_background_polling(cmd, lv)) |
||||
+ !_lvchange_background_polling(cmd, lv, 1)) |
||||
return_ECMD_FAILED; |
||||
|
||||
if (arg_is_set(cmd, monitor_ARG) && |
||||
- !_lvchange_monitoring(cmd, lv)) |
||||
+ !_lvchange_monitoring(cmd, lv, 1)) |
||||
return_ECMD_FAILED; |
||||
|
||||
return ECMD_PROCESSED; |
||||
@@ -1606,11 +1616,11 @@ static int _lvchange_monitor_poll_single(struct cmd_context *cmd, |
||||
struct processing_handle *handle) |
||||
{ |
||||
if (arg_is_set(cmd, monitor_ARG) && |
||||
- !_lvchange_monitoring(cmd, lv)) |
||||
+ !_lvchange_monitoring(cmd, lv, 0)) |
||||
return_ECMD_FAILED; |
||||
|
||||
if (arg_is_set(cmd, poll_ARG) && |
||||
- !_lvchange_background_polling(cmd, lv)) |
||||
+ !_lvchange_background_polling(cmd, lv, 0)) |
||||
return_ECMD_FAILED; |
||||
|
||||
return ECMD_PROCESSED; |
||||
diff --git a/tools/vgchange.c b/tools/vgchange.c |
||||
index 67be3ec..fa2d585 100644 |
||||
--- a/tools/vgchange.c |
||||
+++ b/tools/vgchange.c |
||||
@@ -42,7 +42,16 @@ static int _monitor_lvs_in_vg(struct cmd_context *cmd, |
||||
if (lv_is_pvmove(lv)) |
||||
continue; |
||||
|
||||
- if (!monitor_dev_for_events(cmd, lv, 0, reg)) { |
||||
+ if (locking_is_clustered()) { |
||||
+ if (lv != lv_lock_holder(lv)) |
||||
+ continue; |
||||
+ if (!lv_refresh(cmd, lv)) { |
||||
+ stack; |
||||
+ r = 0; |
||||
+ continue; |
||||
+ } |
||||
+ } else if (!monitor_dev_for_events(cmd, lv, 0, reg)) { |
||||
+ stack; |
||||
r = 0; |
||||
continue; |
||||
} |
||||
@@ -157,8 +166,10 @@ static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg |
||||
|
||||
if (lvs_in_vg_activated(vg) && |
||||
dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) { |
||||
- if (!_monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode(), &monitored)) |
||||
+ if (!_monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode(), &monitored)) { |
||||
+ stack; |
||||
r = 0; |
||||
+ } |
||||
log_print_unless_silent("%d logical volume(s) in volume group " |
||||
"\"%s\" %smonitored", |
||||
monitored, vg->name, (dmeventd_monitor_mode()) ? "" : "un"); |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
From c43515c7ba1d13d54c92d43b76ca0a661c097292 Mon Sep 17 00:00:00 2001 |
||||
From: Heinz Mauelshagen <heinzm@redhat.com> |
||||
Date: Fri, 31 Aug 2018 19:03:52 +0200 |
||||
Subject: [PATCH] lvconvert: avoid superfluous interim raid type |
||||
|
||||
When converting striped/raid0*/raid6_n_6 <-> raid4, |
||||
avoid superfluous interim raid5_n layout. |
||||
|
||||
Related: rhbz1447809 |
||||
(cherry picked from commit 22a13043683a5647e8cc4e3aead911e5269ffd2f) |
||||
(cherry picked from commit 0e03c686191b036a7cd6e570888793ddbdd5f958) |
||||
--- |
||||
lib/metadata/raid_manip.c | 9 ++++----- |
||||
1 file changed, 4 insertions(+), 5 deletions(-) |
||||
|
||||
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
||||
index d3e3a20..3eee77a 100644 |
||||
--- a/lib/metadata/raid_manip.c |
||||
+++ b/lib/metadata/raid_manip.c |
||||
@@ -6140,7 +6140,7 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
seg_flag = SEG_RAID6_N_6; |
||||
|
||||
if (segtype_is_linear(*segtype) || |
||||
- (!segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype))) |
||||
+ (!segtype_is_raid4(*segtype) && !segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype))) |
||||
seg_flag = SEG_RAID5_N; |
||||
|
||||
/* raid1 -> */ |
||||
@@ -6209,10 +6209,9 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
lvseg_name(seg_from), display_lvname(seg_from->lv), *new_image_count); |
||||
} |
||||
|
||||
- /* raid4 -> !raid4/raid5* */ |
||||
- } else if (seg_is_raid4(seg_from) && |
||||
- !segtype_is_raid4(*segtype) && !segtype_is_any_raid5(*segtype)) { |
||||
- seg_flag = SEG_RAID5_N; |
||||
+ /* raid4 -> * */ |
||||
+ } else if (seg_is_raid4(seg_from) && !segtype_is_raid4(*segtype) && !segtype_is_striped(*segtype)) { |
||||
+ seg_flag = segtype_is_any_raid6(*segtype) ? SEG_RAID6_N_6 : SEG_RAID5_N; |
||||
|
||||
/* raid6 -> striped/raid0/raid5/raid10 */ |
||||
} else if (seg_is_any_raid6(seg_from)) { |
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,268 @@
@@ -0,0 +1,268 @@
|
||||
From 83b93f9f5a72ac67f63e6be2c25ce4b3919c4c84 Mon Sep 17 00:00:00 2001 |
||||
From: Heinz Mauelshagen <heinzm@redhat.com> |
||||
Date: Wed, 22 Aug 2018 16:39:36 +0200 |
||||
Subject: [PATCH] lvconvert: fix conversion attempts to linear |
||||
|
||||
"lvconvert --type linear RaidLV" on striped and raid4/5/6/10 |
||||
have to provide the convenient interim layouts. Fix involves |
||||
a cleanup to the convenience type function. |
||||
|
||||
As a result of testing, add missing sync waits to |
||||
lvconvert-raid-reshape-linear_to_raid6-single-type.sh. |
||||
|
||||
Resolves: rhbz1447809 |
||||
(cherry picked from commit e83c4f07ca4a84808178d5d22cba655e5e370cd8) |
||||
|
||||
Conflicts: |
||||
WHATS_NEW |
||||
|
||||
(cherry picked from commit d910f75d89e02e46cd16f9ddbc8e8358c3c2efd3) |
||||
--- |
||||
WHATS_NEW | 1 + |
||||
lib/metadata/raid_manip.c | 145 +++++++++------------ |
||||
...ert-raid-reshape-linear_to_raid6-single-type.sh | 2 + |
||||
3 files changed, 68 insertions(+), 80 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index e3eee56..92e5c04 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.182 - |
||||
============================== |
||||
+ Fix lvconvert conversion attempts to linear. |
||||
Fix lvconvert raid0/raid0_meta -> striped regression. |
||||
Fix lvconvert --splitmirror for mirror type (2.02.178). |
||||
Do not pair cache policy and cache metadata format. |
||||
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
||||
index 804f78b..d3e3a20 100644 |
||||
--- a/lib/metadata/raid_manip.c |
||||
+++ b/lib/metadata/raid_manip.c |
||||
@@ -6120,8 +6120,7 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
const struct segment_type *segtype_sav = *segtype; |
||||
|
||||
/* Linear -> striped request */ |
||||
- if (seg_is_striped(seg_from) && |
||||
- seg_from->area_count == 1 && |
||||
+ if (seg_is_linear(seg_from) && |
||||
segtype_is_striped(*segtype)) |
||||
; |
||||
/* Bail out if same RAID level is requested. */ |
||||
@@ -6130,24 +6129,20 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
|
||||
log_debug("Checking LV %s requested %s segment type for convenience", |
||||
display_lvname(seg_from->lv), (*segtype)->name); |
||||
- /* striped/raid0 -> raid5/6 */ |
||||
- if (seg_is_striped(seg_from) || seg_is_any_raid0(seg_from)) { |
||||
- /* linear -> raid*, interim/first conversion is to raid1 */ |
||||
- if (seg_from->area_count == 1) |
||||
- seg_flag = SEG_RAID1; |
||||
- |
||||
- else if (seg_is_any_raid0(seg_from) && segtype_is_striped(*segtype)) |
||||
- ; |
||||
- |
||||
- /* If this is any raid5 conversion request -> enforce raid5_n, because we convert from striped */ |
||||
- else if (((segtype_is_striped(*segtype) && !segtype_is_any_raid0(*segtype)) || segtype_is_any_raid5(*segtype)) && |
||||
- !segtype_is_raid5_n(*segtype)) |
||||
- seg_flag = SEG_RAID5_N; |
||||
|
||||
- /* If this is any raid6 conversion request -> enforce raid6_n_6, because we convert from striped */ |
||||
- else if (segtype_is_any_raid6(*segtype) && !segtype_is_raid6_n_6(*segtype)) |
||||
+ /* linear -> */ |
||||
+ if (seg_is_linear(seg_from)) { |
||||
+ seg_flag = SEG_RAID1; |
||||
+ |
||||
+ /* striped/raid0 -> */ |
||||
+ } else if (seg_is_striped(seg_from) || seg_is_any_raid0(seg_from)) { |
||||
+ if (segtype_is_any_raid6(*segtype)) |
||||
seg_flag = SEG_RAID6_N_6; |
||||
|
||||
+ if (segtype_is_linear(*segtype) || |
||||
+ (!segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype))) |
||||
+ seg_flag = SEG_RAID5_N; |
||||
+ |
||||
/* raid1 -> */ |
||||
} else if (seg_is_raid1(seg_from) && !segtype_is_mirror(*segtype)) { |
||||
if (seg_from->area_count != 2) { |
||||
@@ -6157,85 +6152,68 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
} |
||||
|
||||
if (segtype_is_striped(*segtype) || |
||||
- segtype_is_any_raid0(*segtype) || |
||||
- segtype_is_raid10(*segtype)) |
||||
+ segtype_is_any_raid0(*segtype) || |
||||
+ segtype_is_raid10(*segtype)) |
||||
seg_flag = SEG_RAID5_N; |
||||
|
||||
else if (!segtype_is_raid4(*segtype) && !segtype_is_any_raid5(*segtype)) |
||||
seg_flag = SEG_RAID5_LS; |
||||
|
||||
- /* raid4/raid5 -> striped/raid0/raid1/raid6/raid10 */ |
||||
- } else if (seg_is_raid4(seg_from) || seg_is_any_raid5(seg_from)) { |
||||
- if ((segtype_is_raid1(*segtype) || segtype_is_linear(*segtype)) && seg_is_raid5_n(seg_from)) { |
||||
+ /* raid5* -> */ |
||||
+ } else if (seg_is_any_raid5(seg_from)) { |
||||
+ if (segtype_is_raid1(*segtype) || segtype_is_linear(*segtype)) { |
||||
if (seg_from->area_count != 2) { |
||||
log_error("Converting %s LV %s to 2 stripes first.", |
||||
lvseg_name(seg_from), display_lvname(seg_from->lv)); |
||||
*new_image_count = 2; |
||||
- seg_flag = SEG_RAID5_N; |
||||
+ *segtype = seg_from->segtype; |
||||
+ seg_flag = 0; |
||||
} else |
||||
seg_flag = SEG_RAID1; |
||||
|
||||
- } else if (segtype_is_raid1(*segtype) && seg_from->area_count != 2) { |
||||
- log_error("Convert %s LV %s to 2 stripes first (i.e. --stripes 1).", |
||||
- lvseg_name(seg_from), display_lvname(seg_from->lv)); |
||||
- return 0; |
||||
- |
||||
- } else if (seg_is_raid4(seg_from) && |
||||
- (segtype_is_linear(*segtype) || segtype_is_any_raid5(*segtype)) && |
||||
- !segtype_is_raid5_n(*segtype)) |
||||
- seg_flag = SEG_RAID5_N; |
||||
+ } else if (segtype_is_any_raid6(*segtype)) { |
||||
+ if (seg_from->area_count < 4) { |
||||
+ if (*stripes > 3) |
||||
+ *new_image_count = *stripes + seg_from->segtype->parity_devs; |
||||
+ else |
||||
+ *new_image_count = 4; |
||||
|
||||
- else if (seg_is_raid5_n(seg_from) && seg_from->area_count == 2) { |
||||
- if (*stripes >= 2) { |
||||
+ *segtype = seg_from->segtype; |
||||
log_error("Converting %s LV %s to %u stripes first.", |
||||
- lvseg_name(seg_from), display_lvname(seg_from->lv), *stripes); |
||||
+ lvseg_name(seg_from), display_lvname(seg_from->lv), *new_image_count); |
||||
+ |
||||
+ } else |
||||
+ seg_flag = _raid_seg_flag_5_to_6(seg_from); |
||||
+ |
||||
+ } else if (segtype_is_striped(*segtype) || segtype_is_raid10(*segtype)) { |
||||
+ int change = 0; |
||||
+ |
||||
+ if (!seg_is_raid5_n(seg_from)) { |
||||
+ seg_flag = SEG_RAID5_N; |
||||
+ |
||||
+ } else if (*stripes > 2 && *stripes != seg_from->area_count - seg_from->segtype->parity_devs) { |
||||
+ change = 1; |
||||
*new_image_count = *stripes + seg_from->segtype->parity_devs; |
||||
seg_flag = SEG_RAID5_N; |
||||
- } else { |
||||
- log_error("Convert %s LV %s to minimum 3 stripes first (i.e. --stripes 2).", |
||||
- lvseg_name(seg_from), display_lvname(seg_from->lv)); |
||||
- return 0; |
||||
- } |
||||
- } else if (seg_is_any_raid5(seg_from) && |
||||
- (segtype_is_linear(*segtype) || segtype_is_raid4(*segtype)) && |
||||
- !segtype_is_raid5_n(*segtype)) |
||||
- seg_flag = SEG_RAID5_N; |
||||
|
||||
- else if (segtype_is_raid10(*segtype)) { |
||||
- if (seg_from->area_count < 3) { |
||||
- if (*stripes >= 2) { |
||||
- log_error("Converting %s LV %s to %u stripes first.", |
||||
- lvseg_name(seg_from), display_lvname(seg_from->lv), *stripes); |
||||
- *new_image_count = *stripes + seg_from->segtype->parity_devs; |
||||
- seg_flag = SEG_RAID5_N; |
||||
- } else { |
||||
- log_error("Convert %s LV %s to minimum 3 stripes first (i.e. --stripes 2).", |
||||
- lvseg_name(seg_from), display_lvname(seg_from->lv)); |
||||
- return 0; |
||||
- } |
||||
- } else |
||||
- seg_flag = seg_is_raid5_n(seg_from) ? SEG_RAID0_META : SEG_RAID5_N; |
||||
+ } else if (seg_from->area_count < 3) { |
||||
+ change = 1; |
||||
+ *new_image_count = 3; |
||||
+ seg_flag = SEG_RAID5_N; |
||||
|
||||
- } else if (segtype_is_any_raid6(*segtype)) { |
||||
- if (seg_from->area_count < 4 && |
||||
- seg_is_any_raid5(seg_from)) { |
||||
- if (*stripes >= 3) { |
||||
- log_error("Converting %s LV %s to %u stripes first.", |
||||
- lvseg_name(seg_from), display_lvname(seg_from->lv), *stripes); |
||||
- *new_image_count = *stripes + seg_from->segtype->parity_devs; |
||||
- seg_flag = SEG_RAID5_LS; |
||||
- } else { |
||||
- log_error("Convert %s LV %s to minimum 4 stripes first (i.e. --stripes 3).", |
||||
- lvseg_name(seg_from), display_lvname(seg_from->lv)); |
||||
- return 0; |
||||
- } |
||||
+ } else if (!segtype_is_striped(*segtype)) |
||||
+ seg_flag = SEG_RAID0_META; |
||||
|
||||
- } else if (seg_is_raid4(seg_from) && !segtype_is_raid6_n_6(*segtype)) |
||||
- seg_flag = SEG_RAID6_N_6; |
||||
- else |
||||
- seg_flag = _raid_seg_flag_5_to_6(seg_from); |
||||
+ if (change) |
||||
+ log_error("Converting %s LV %s to %u stripes first.", |
||||
+ lvseg_name(seg_from), display_lvname(seg_from->lv), *new_image_count); |
||||
} |
||||
|
||||
+ /* raid4 -> !raid4/raid5* */ |
||||
+ } else if (seg_is_raid4(seg_from) && |
||||
+ !segtype_is_raid4(*segtype) && !segtype_is_any_raid5(*segtype)) { |
||||
+ seg_flag = SEG_RAID5_N; |
||||
+ |
||||
/* raid6 -> striped/raid0/raid5/raid10 */ |
||||
} else if (seg_is_any_raid6(seg_from)) { |
||||
if (segtype_is_raid1(*segtype)) { |
||||
@@ -6247,6 +6225,9 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
} else if (segtype_is_any_raid10(*segtype)) { |
||||
seg_flag = seg_is_raid6_n_6(seg_from) ? SEG_RAID0_META : SEG_RAID6_N_6; |
||||
|
||||
+ } else if (segtype_is_linear(*segtype)) { |
||||
+ seg_flag = seg_is_raid6_n_6(seg_from) ? SEG_RAID5_N : SEG_RAID6_N_6; |
||||
+ |
||||
} else if (segtype_is_striped(*segtype) || segtype_is_any_raid0(*segtype)) { |
||||
if (!seg_is_raid6_n_6(seg_from)) |
||||
seg_flag = SEG_RAID6_N_6; |
||||
@@ -6277,12 +6258,16 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
return 0; |
||||
} |
||||
|
||||
- /* raid10 -> ... */ |
||||
- } else if (seg_is_raid10(seg_from) && |
||||
- !segtype_is_striped(*segtype) && |
||||
- !segtype_is_any_raid0(*segtype)) |
||||
- seg_flag = SEG_RAID0_META; |
||||
+ } else if (seg_is_raid10(seg_from)) { |
||||
+ if (segtype_is_linear(*segtype) || |
||||
+ (!segtype_is_striped(*segtype) && |
||||
+ !segtype_is_any_raid0(*segtype))) { |
||||
+ seg_flag = SEG_RAID0_META; |
||||
+ } |
||||
+ } |
||||
|
||||
+ |
||||
+ /* raid10 -> ... */ |
||||
if (seg_flag) { |
||||
if (!(*segtype = get_segtype_from_flag(cmd, seg_flag))) |
||||
return_0; |
||||
diff --git a/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh b/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh |
||||
index f01e7ef..05cb616 100644 |
||||
--- a/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh |
||||
+++ b/test/shell/lvconvert-raid-reshape-linear_to_raid6-single-type.sh |
||||
@@ -78,6 +78,7 @@ check lv_first_seg_field $vg/$lv data_stripes 3 |
||||
check lv_first_seg_field $vg/$lv stripesize "64.00k" |
||||
check lv_first_seg_field $vg/$lv regionsize "128.00k" |
||||
check lv_first_seg_field $vg/$lv reshape_len_le 0 |
||||
+aux wait_for_sync $vg $lv |
||||
|
||||
# Convert raid6_ls_6 -> raid6(_zr) (reshape) |
||||
lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv |
||||
@@ -88,6 +89,7 @@ check lv_first_seg_field $vg/$lv data_stripes 3 |
||||
check lv_first_seg_field $vg/$lv stripesize "64.00k" |
||||
check lv_first_seg_field $vg/$lv regionsize "128.00k" |
||||
check lv_first_seg_field $vg/$lv reshape_len_le 10 |
||||
+aux wait_for_sync $vg $lv |
||||
|
||||
# Remove reshape space |
||||
lvconvert -y --type raid6 --stripes 3 --stripesize 64K --regionsize 128K $vg/$lv |
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
WHATS_NEW | 1 + |
||||
lib/metadata/raid_manip.c | 3 +++ |
||||
test/shell/lvconvert-raid0-striped.sh | 25 +++++++++++++++++++++++++ |
||||
3 files changed, 29 insertions(+) |
||||
create mode 100644 test/shell/lvconvert-raid0-striped.sh |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 6560357..e3eee56 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.182 - |
||||
============================== |
||||
+ Fix lvconvert raid0/raid0_meta -> striped regression. |
||||
Fix lvconvert --splitmirror for mirror type (2.02.178). |
||||
Do not pair cache policy and cache metadata format. |
||||
|
||||
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
||||
index 705a7f9..804f78b 100644 |
||||
--- a/lib/metadata/raid_manip.c |
||||
+++ b/lib/metadata/raid_manip.c |
||||
@@ -6136,6 +6136,9 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
if (seg_from->area_count == 1) |
||||
seg_flag = SEG_RAID1; |
||||
|
||||
+ else if (seg_is_any_raid0(seg_from) && segtype_is_striped(*segtype)) |
||||
+ ; |
||||
+ |
||||
/* If this is any raid5 conversion request -> enforce raid5_n, because we convert from striped */ |
||||
else if (((segtype_is_striped(*segtype) && !segtype_is_any_raid0(*segtype)) || segtype_is_any_raid5(*segtype)) && |
||||
!segtype_is_raid5_n(*segtype)) |
||||
diff --git a/test/shell/lvconvert-raid0-striped.sh b/test/shell/lvconvert-raid0-striped.sh |
||||
new file mode 100644 |
||||
index 0000000..4521b34 |
||||
--- /dev/null |
||||
+++ b/test/shell/lvconvert-raid0-striped.sh |
||||
@@ -0,0 +1,25 @@ |
||||
+#!/usr/bin/env bash |
||||
+ |
||||
+# Copyright (C) 2018 Red Hat, Inc. All rights reserved. |
||||
+# |
||||
+# This copyrighted material is made available to anyone wishing to use, |
||||
+# modify, copy, or redistribute it subject to the terms and conditions |
||||
+# of the GNU General Public License v.2. |
||||
+# |
||||
+# You should have received a copy of the GNU General Public License |
||||
+# along with this program; if not, write to the Free Software Foundation, |
||||
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
+ |
||||
+ |
||||
+SKIP_WITH_LVMPOLLD=1 |
||||
+ |
||||
+. lib/inittest |
||||
+ |
||||
+aux have_raid 1 7 0 || skip |
||||
+ |
||||
+aux prepare_vg 3 16 |
||||
+ |
||||
+lvcreate -aey --type raid0 -i 3 -l3 -n $lv $vg |
||||
+lvconvert -y --type striped $vg/$lv |
||||
+check lv_field $vg/$lv segtype "striped" |
||||
+vgremove -ff $vg |
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
From 2ee0f6d4ddd6c602def295e3b1dfccbd8a50a4c8 Mon Sep 17 00:00:00 2001 |
||||
From: Heinz Mauelshagen <heinzm@redhat.com> |
||||
Date: Fri, 7 Sep 2018 13:48:13 +0200 |
||||
Subject: [PATCH] lvconvert: fix interim segtype regression on raid6 |
||||
conversions |
||||
|
||||
When converting from striped/raid0/raid0_meta |
||||
to raid6 with > 2 stripes, allow possible |
||||
direct conversion (to raid6_n_6). |
||||
|
||||
In case of 2 stripes, first convert to raid5_n to restripe |
||||
to at least 3 data stripes (the raid6 minimum in lvm2) in |
||||
a second conversion before finally converting to raid6_n_6. |
||||
|
||||
As before, raid6_n_6 then can be converted |
||||
to any other raid6 layout. |
||||
|
||||
Enhance lvconvert-raid-takeover.sh to test the |
||||
2 stripes conversions to raid6. |
||||
|
||||
Resolves: rhbz1624038 |
||||
(cherry picked from commit e2e30a64ab10602951443dfbd3481bd6b32f5459) |
||||
|
||||
Conflicts: |
||||
WHATS_NEW |
||||
|
||||
(cherry picked from commit c26bde42af0930bef2cee95c76951285d801ba70) |
||||
--- |
||||
WHATS_NEW | 1 + |
||||
lib/metadata/raid_manip.c | 6 +++--- |
||||
test/shell/lvconvert-raid-takeover.sh | 16 ++++++++++++---- |
||||
3 files changed, 16 insertions(+), 7 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 9da40b6..d8a24b0 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.182 - |
||||
============================== |
||||
+ Fix lvconvert striped/raid0/raid0_meta -> raid6 regression. |
||||
Add After=rbdmap.service to {lvm2-activation-net,blk-availability}.service. |
||||
Fix lvconvert conversion attempts to linear. |
||||
Fix lvconvert raid0/raid0_meta -> striped regression. |
||||
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
||||
index 3eee77a..cb7202a 100644 |
||||
--- a/lib/metadata/raid_manip.c |
||||
+++ b/lib/metadata/raid_manip.c |
||||
@@ -6137,10 +6137,10 @@ static int _set_convenient_raid145610_segtype_to(const struct lv_segment *seg_fr |
||||
/* striped/raid0 -> */ |
||||
} else if (seg_is_striped(seg_from) || seg_is_any_raid0(seg_from)) { |
||||
if (segtype_is_any_raid6(*segtype)) |
||||
- seg_flag = SEG_RAID6_N_6; |
||||
+ seg_flag = seg_from->area_count < 3 ? SEG_RAID5_N : SEG_RAID6_N_6; |
||||
|
||||
- if (segtype_is_linear(*segtype) || |
||||
- (!segtype_is_raid4(*segtype) && !segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype))) |
||||
+ else if (segtype_is_linear(*segtype) || |
||||
+ (!segtype_is_raid4(*segtype) && !segtype_is_raid10(*segtype) && !segtype_is_striped(*segtype))) |
||||
seg_flag = SEG_RAID5_N; |
||||
|
||||
/* raid1 -> */ |
||||
diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh |
||||
index d1c5d30..d22c11b 100644 |
||||
--- a/test/shell/lvconvert-raid-takeover.sh |
||||
+++ b/test/shell/lvconvert-raid-takeover.sh |
||||
@@ -108,11 +108,19 @@ function _invalid_raid5_conversions |
||||
not _lvconvert raid6 raid6_n_6 4 6 $vg $lv1 |
||||
} |
||||
|
||||
-# Check raid6 conversion constrainst of minimum 3 stripes |
||||
-_lvcreate striped 2 2 4m $vg $lv1 |
||||
-not _lvconvert raid6 raid6_n_6 2 4 $vg $lv1 |
||||
-lvremove -y $vg |
||||
+# Check raid6 conversion constrainst for 2 stripes |
||||
+for type in striped raid0 raid0_meta |
||||
+do |
||||
+ _lvcreate $type 2 2 4m $vg $lv1 |
||||
+ not _lvconvert raid6 raid6_n_6 2 4 $vg $lv1 |
||||
+ _lvconvert raid6 raid5_n 2 3 $vg $lv1 |
||||
+ _lvconvert raid6 raid5_n 3 4 $vg $lv1 |
||||
+ _lvconvert raid6 raid6_n_6 3 5 $vg $lv1 |
||||
+ lvremove -y $vg |
||||
+done |
||||
|
||||
+ |
||||
+# Check raid6 conversion constrainst of minimum 3 stripes |
||||
_lvcreate raid0 3 3 4m $vg $lv1 |
||||
_lvconvert raid6 raid6_n_6 3 5 $vg $lv1 |
||||
lvremove -y $vg |
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,338 @@
@@ -0,0 +1,338 @@
|
||||
From 87bd4a350468023b14251b9bde98f88ffb419268 Mon Sep 17 00:00:00 2001 |
||||
From: David Teigland <teigland@redhat.com> |
||||
Date: Mon, 29 Oct 2018 11:06:00 -0500 |
||||
Subject: [PATCH 2/2] metadata: prevent writing beyond metadata area |
||||
|
||||
lvm uses a bcache block size of 128K. A bcache block |
||||
at the end of the metadata area will overlap the PEs |
||||
from which LVs are allocated. How much depends on |
||||
alignments. When lvm reads and writes one of these |
||||
bcache blocks to update VG metadata, it can also be |
||||
reading and writing PEs that belong to an LV. |
||||
|
||||
If these overlapping PEs are being written to by the |
||||
LV user (e.g. filesystem) at the same time that lvm |
||||
is modifying VG metadata in the overlapping bcache |
||||
block, then the user's updates to the PEs can be lost. |
||||
|
||||
This patch is a quick hack to prevent lvm from writing |
||||
past the end of the metadata area. |
||||
|
||||
(cherry picked from commit ab27d5dc2a5c3bf23ab8fed438f1542015dc723d) |
||||
--- |
||||
lib/device/bcache.c | 79 +++++++++++++++++++++++++++++++++++++++++-- |
||||
lib/device/bcache.h | 3 ++ |
||||
lib/format_text/format-text.c | 10 ++++++ |
||||
lib/label/label.c | 35 ++++++++++++++++++- |
||||
lib/label/label.h | 2 ++ |
||||
lib/metadata/mirror.c | 4 +++ |
||||
6 files changed, 130 insertions(+), 3 deletions(-) |
||||
|
||||
diff --git a/lib/device/bcache.c b/lib/device/bcache.c |
||||
index b1f7d2a..5ac2558 100644 |
||||
--- a/lib/device/bcache.c |
||||
+++ b/lib/device/bcache.c |
||||
@@ -156,6 +156,10 @@ static void _async_destroy(struct io_engine *ioe) |
||||
dm_free(e); |
||||
} |
||||
|
||||
+static int _last_byte_fd; |
||||
+static uint64_t _last_byte_offset; |
||||
+static int _last_byte_sector_size; |
||||
+ |
||||
static bool _async_issue(struct io_engine *ioe, enum dir d, int fd, |
||||
sector_t sb, sector_t se, void *data, void *context) |
||||
{ |
||||
@@ -163,12 +167,53 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd, |
||||
struct iocb *cb_array[1]; |
||||
struct control_block *cb; |
||||
struct async_engine *e = _to_async(ioe); |
||||
+ sector_t offset; |
||||
+ sector_t nbytes; |
||||
+ sector_t limit_nbytes; |
||||
+ sector_t extra_nbytes = 0; |
||||
|
||||
if (((uintptr_t) data) & e->page_mask) { |
||||
log_warn("misaligned data buffer"); |
||||
return false; |
||||
} |
||||
|
||||
+ offset = sb << SECTOR_SHIFT; |
||||
+ nbytes = (se - sb) << SECTOR_SHIFT; |
||||
+ |
||||
+ /* |
||||
+ * If bcache block goes past where lvm wants to write, then clamp it. |
||||
+ */ |
||||
+ if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) { |
||||
+ if (offset > _last_byte_offset) { |
||||
+ log_error("Limit write at %llu len %llu beyond last byte %llu", |
||||
+ (unsigned long long)offset, |
||||
+ (unsigned long long)nbytes, |
||||
+ (unsigned long long)_last_byte_offset); |
||||
+ return false; |
||||
+ } |
||||
+ |
||||
+ if (offset + nbytes > _last_byte_offset) { |
||||
+ limit_nbytes = _last_byte_offset - offset; |
||||
+ if (limit_nbytes % _last_byte_sector_size) |
||||
+ extra_nbytes = _last_byte_sector_size - (limit_nbytes % _last_byte_sector_size); |
||||
+ |
||||
+ if (extra_nbytes) { |
||||
+ log_debug("Limit write at %llu len %llu to len %llu rounded to %llu", |
||||
+ (unsigned long long)offset, |
||||
+ (unsigned long long)nbytes, |
||||
+ (unsigned long long)limit_nbytes, |
||||
+ (unsigned long long)(limit_nbytes + extra_nbytes)); |
||||
+ nbytes = limit_nbytes + extra_nbytes; |
||||
+ } else { |
||||
+ log_debug("Limit write at %llu len %llu to len %llu", |
||||
+ (unsigned long long)offset, |
||||
+ (unsigned long long)nbytes, |
||||
+ (unsigned long long)limit_nbytes); |
||||
+ nbytes = limit_nbytes; |
||||
+ } |
||||
+ } |
||||
+ } |
||||
+ |
||||
cb = _cb_alloc(e->cbs, context); |
||||
if (!cb) { |
||||
log_warn("couldn't allocate control block"); |
||||
@@ -179,10 +224,22 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd, |
||||
|
||||
cb->cb.aio_fildes = (int) fd; |
||||
cb->cb.u.c.buf = data; |
||||
- cb->cb.u.c.offset = sb << SECTOR_SHIFT; |
||||
- cb->cb.u.c.nbytes = (se - sb) << SECTOR_SHIFT; |
||||
+ cb->cb.u.c.offset = offset; |
||||
+ cb->cb.u.c.nbytes = nbytes; |
||||
cb->cb.aio_lio_opcode = (d == DIR_READ) ? IO_CMD_PREAD : IO_CMD_PWRITE; |
||||
|
||||
+#if 0 |
||||
+ if (d == DIR_READ) { |
||||
+ log_debug("io R off %llu bytes %llu", |
||||
+ (unsigned long long)cb->cb.u.c.offset, |
||||
+ (unsigned long long)cb->cb.u.c.nbytes); |
||||
+ } else { |
||||
+ log_debug("io W off %llu bytes %llu", |
||||
+ (unsigned long long)cb->cb.u.c.offset, |
||||
+ (unsigned long long)cb->cb.u.c.nbytes); |
||||
+ } |
||||
+#endif |
||||
+ |
||||
cb_array[0] = &cb->cb; |
||||
do { |
||||
r = io_submit(e->aio_context, 1, cb_array); |
||||
@@ -1145,3 +1202,21 @@ bool bcache_invalidate_fd(struct bcache *cache, int fd) |
||||
|
||||
//---------------------------------------------------------------- |
||||
|
||||
+void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size) |
||||
+{ |
||||
+ _last_byte_fd = fd; |
||||
+ _last_byte_offset = offset; |
||||
+ _last_byte_sector_size = sector_size; |
||||
+ if (!sector_size) |
||||
+ _last_byte_sector_size = 512; |
||||
+} |
||||
+ |
||||
+void bcache_unset_last_byte(struct bcache *cache, int fd) |
||||
+{ |
||||
+ if (_last_byte_fd == fd) { |
||||
+ _last_byte_fd = 0; |
||||
+ _last_byte_offset = 0; |
||||
+ _last_byte_sector_size = 0; |
||||
+ } |
||||
+} |
||||
+ |
||||
diff --git a/lib/device/bcache.h b/lib/device/bcache.h |
||||
index b0aebb4..cb902ef 100644 |
||||
--- a/lib/device/bcache.h |
||||
+++ b/lib/device/bcache.h |
||||
@@ -158,6 +158,9 @@ bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len |
||||
bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len); |
||||
bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val); |
||||
|
||||
+void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size); |
||||
+void bcache_unset_last_byte(struct bcache *cache, int fd); |
||||
+ |
||||
//---------------------------------------------------------------- |
||||
|
||||
#endif |
||||
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c |
||||
index 792d75a..36afba1 100644 |
||||
--- a/lib/format_text/format-text.c |
||||
+++ b/lib/format_text/format-text.c |
||||
@@ -400,10 +400,14 @@ static int _raw_write_mda_header(const struct format_type *fmt, |
||||
MDA_HEADER_SIZE - |
||||
sizeof(mdah->checksum_xl))); |
||||
|
||||
+ dev_set_last_byte(dev, start_byte + MDA_HEADER_SIZE); |
||||
+ |
||||
if (!dev_write_bytes(dev, start_byte, MDA_HEADER_SIZE, mdah)) { |
||||
+ dev_unset_last_byte(dev); |
||||
log_error("Failed to write mda header to %s fd %d", dev_name(dev), dev->bcache_fd); |
||||
return 0; |
||||
} |
||||
+ dev_unset_last_byte(dev); |
||||
|
||||
return 1; |
||||
} |
||||
@@ -677,10 +681,13 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg, |
||||
(unsigned long long)(mdac->rlocn.size - new_wrap), |
||||
(unsigned long long)new_wrap); |
||||
|
||||
+ dev_set_last_byte(mdac->area.dev, mdac->area.start + mdah->size); |
||||
+ |
||||
if (!dev_write_bytes(mdac->area.dev, mdac->area.start + mdac->rlocn.offset, |
||||
(size_t) (mdac->rlocn.size - new_wrap), |
||||
fidtc->raw_metadata_buf)) { |
||||
log_error("Failed to write metadata to %s fd %d", dev_name(mdac->area.dev), mdac->area.dev->bcache_fd); |
||||
+ dev_unset_last_byte(mdac->area.dev); |
||||
goto out; |
||||
} |
||||
|
||||
@@ -694,10 +701,13 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg, |
||||
(size_t) new_wrap, |
||||
fidtc->raw_metadata_buf + mdac->rlocn.size - new_wrap)) { |
||||
log_error("Failed to write metadata wrap to %s fd %d", dev_name(mdac->area.dev), mdac->area.dev->bcache_fd); |
||||
+ dev_unset_last_byte(mdac->area.dev); |
||||
goto out; |
||||
} |
||||
} |
||||
|
||||
+ dev_unset_last_byte(mdac->area.dev); |
||||
+ |
||||
mdac->rlocn.checksum = calc_crc(INITIAL_CRC, (uint8_t *)fidtc->raw_metadata_buf, |
||||
(uint32_t) (mdac->rlocn.size - |
||||
new_wrap)); |
||||
diff --git a/lib/label/label.c b/lib/label/label.c |
||||
index bafa543..d2cfe62 100644 |
||||
--- a/lib/label/label.c |
||||
+++ b/lib/label/label.c |
||||
@@ -172,6 +172,7 @@ int label_write(struct device *dev, struct label *label) |
||||
{ |
||||
char buf[LABEL_SIZE] __attribute__((aligned(8))); |
||||
struct label_header *lh = (struct label_header *) buf; |
||||
+ uint64_t offset; |
||||
int r = 1; |
||||
|
||||
if (!label->labeller->ops->write) { |
||||
@@ -206,11 +207,17 @@ int label_write(struct device *dev, struct label *label) |
||||
return 0; |
||||
} |
||||
|
||||
- if (!dev_write_bytes(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) { |
||||
+ offset = label->sector << SECTOR_SHIFT; |
||||
+ |
||||
+ dev_set_last_byte(dev, offset + LABEL_SIZE); |
||||
+ |
||||
+ if (!dev_write_bytes(dev, offset, LABEL_SIZE, buf)) { |
||||
log_debug_devs("Failed to write label to %s", dev_name(dev)); |
||||
r = 0; |
||||
} |
||||
|
||||
+ dev_unset_last_byte(dev); |
||||
+ |
||||
return r; |
||||
} |
||||
|
||||
@@ -1256,9 +1263,12 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len) |
||||
} |
||||
} |
||||
|
||||
+ dev_set_last_byte(dev, start + len); |
||||
+ |
||||
if (!bcache_zero_bytes(scan_bcache, dev->bcache_fd, start, len)) { |
||||
log_error("Error writing device %s at %llu length %u.", |
||||
dev_name(dev), (unsigned long long)start, (uint32_t)len); |
||||
+ dev_unset_last_byte(dev); |
||||
label_scan_invalidate(dev); |
||||
return false; |
||||
} |
||||
@@ -1266,9 +1276,11 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len) |
||||
if (!bcache_flush(scan_bcache)) { |
||||
log_error("Error writing device %s at %llu length %u.", |
||||
dev_name(dev), (unsigned long long)start, (uint32_t)len); |
||||
+ dev_unset_last_byte(dev); |
||||
label_scan_invalidate(dev); |
||||
return false; |
||||
} |
||||
+ dev_unset_last_byte(dev); |
||||
return true; |
||||
} |
||||
|
||||
@@ -1302,9 +1314,12 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val) |
||||
} |
||||
} |
||||
|
||||
+ dev_set_last_byte(dev, start + len); |
||||
+ |
||||
if (!bcache_set_bytes(scan_bcache, dev->bcache_fd, start, len, val)) { |
||||
log_error("Error writing device %s at %llu length %u.", |
||||
dev_name(dev), (unsigned long long)start, (uint32_t)len); |
||||
+ dev_unset_last_byte(dev); |
||||
label_scan_invalidate(dev); |
||||
return false; |
||||
} |
||||
@@ -1312,9 +1327,27 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val) |
||||
if (!bcache_flush(scan_bcache)) { |
||||
log_error("Error writing device %s at %llu length %u.", |
||||
dev_name(dev), (unsigned long long)start, (uint32_t)len); |
||||
+ dev_unset_last_byte(dev); |
||||
label_scan_invalidate(dev); |
||||
return false; |
||||
} |
||||
+ |
||||
+ dev_unset_last_byte(dev); |
||||
return true; |
||||
} |
||||
|
||||
+void dev_set_last_byte(struct device *dev, uint64_t offset) |
||||
+{ |
||||
+ unsigned int phys_block_size = 0; |
||||
+ unsigned int block_size = 0; |
||||
+ |
||||
+ dev_get_block_size(dev, &phys_block_size, &block_size); |
||||
+ |
||||
+ bcache_set_last_byte(scan_bcache, dev->bcache_fd, offset, phys_block_size); |
||||
+} |
||||
+ |
||||
+void dev_unset_last_byte(struct device *dev) |
||||
+{ |
||||
+ bcache_unset_last_byte(scan_bcache, dev->bcache_fd); |
||||
+} |
||||
+ |
||||
diff --git a/lib/label/label.h b/lib/label/label.h |
||||
index 5ed8bc8..e2b8263 100644 |
||||
--- a/lib/label/label.h |
||||
+++ b/lib/label/label.h |
||||
@@ -125,5 +125,7 @@ bool dev_read_bytes(struct device *dev, uint64_t start, size_t len, void *data); |
||||
bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data); |
||||
bool dev_write_zeros(struct device *dev, uint64_t start, size_t len); |
||||
bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val); |
||||
+void dev_set_last_byte(struct device *dev, uint64_t offset); |
||||
+void dev_unset_last_byte(struct device *dev); |
||||
|
||||
#endif |
||||
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c |
||||
index c7d8a9e..b1dcaa0 100644 |
||||
--- a/lib/metadata/mirror.c |
||||
+++ b/lib/metadata/mirror.c |
||||
@@ -302,10 +302,14 @@ static int _write_log_header(struct cmd_context *cmd, struct logical_volume *lv) |
||||
return 0; |
||||
} |
||||
|
||||
+ dev_set_last_byte(dev, sizeof(log_header)); |
||||
+ |
||||
if (!dev_write_bytes(dev, UINT64_C(0), sizeof(log_header), &log_header)) { |
||||
+ dev_unset_last_byte(dev); |
||||
log_error("Failed to write log header to %s.", name); |
||||
return 0; |
||||
} |
||||
+ dev_unset_last_byte(dev); |
||||
|
||||
label_scan_invalidate(dev); |
||||
|
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
WHATS_NEW | 1 + |
||||
lib/activate/activate.c | 5 +++++ |
||||
lib/metadata/mirror.c | 2 +- |
||||
3 files changed, 7 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 17aff08..6560357 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.182 - |
||||
============================== |
||||
+ Fix lvconvert --splitmirror for mirror type (2.02.178). |
||||
Do not pair cache policy and cache metadata format. |
||||
|
||||
Version 2.02.181 - |
||||
diff --git a/lib/activate/activate.c b/lib/activate/activate.c |
||||
index e38ab03..16704f6 100644 |
||||
--- a/lib/activate/activate.c |
||||
+++ b/lib/activate/activate.c |
||||
@@ -2125,6 +2125,11 @@ static int _preload_detached_lv(struct logical_volume *lv, void *data) |
||||
!lv_is_raid_metadata(lv_pre) && lv_is_active(lv) && |
||||
!_lv_preload(lv_pre, detached->laopts, detached->flush_required)) |
||||
return_0; |
||||
+ } else if (lv_is_mirror_image(lv)) { |
||||
+ if ((lv_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) && |
||||
+ !lv_is_mirror_image(lv_pre) && lv_is_active(lv) && |
||||
+ !_lv_preload(lv_pre, detached->laopts, detached->flush_required)) |
||||
+ return_0; |
||||
} |
||||
|
||||
if (!lv_is_visible(lv) && (lv_pre = find_lv(detached->lv_pre->vg, lv->name)) && |
||||
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c |
||||
index 7f38d4f..c7d8a9e 100644 |
||||
--- a/lib/metadata/mirror.c |
||||
+++ b/lib/metadata/mirror.c |
||||
@@ -786,7 +786,7 @@ static int _split_mirror_images(struct logical_volume *lv, |
||||
|
||||
act = lv_is_active(lv_lock_holder(lv)); |
||||
|
||||
- if (act && !_activate_lv_like_model(lv, new_lv)) { |
||||
+ if (act && (!deactivate_lv(cmd, new_lv) || !_activate_lv_like_model(lv, new_lv))) { |
||||
log_error("Failed to rename newly split LV in the kernel"); |
||||
return 0; |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
lib/activate/activate.c | 2 ++ |
||||
1 file changed, 2 insertions(+) |
||||
|
||||
diff --git a/lib/activate/activate.c b/lib/activate/activate.c |
||||
index 18f4b84..e38ab03 100644 |
||||
--- a/lib/activate/activate.c |
||||
+++ b/lib/activate/activate.c |
||||
@@ -1864,6 +1864,8 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume |
||||
|
||||
if (!laopts) |
||||
laopts = &zlaopts; |
||||
+ else |
||||
+ mirr_laopts.read_only = laopts->read_only; |
||||
|
||||
/* skip dmeventd code altogether */ |
||||
if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE) |
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
From 4484518f67dd41151571e0841ef13134abe39408 Mon Sep 17 00:00:00 2001 |
||||
From: Peter Rajnoha <prajnoha@redhat.com> |
||||
Date: Thu, 30 Aug 2018 12:35:58 +0200 |
||||
Subject: [PATCH 2/2] scripts: add After=rbdmap.service to |
||||
{lvm2-activation-net,blk-availability}.service |
||||
|
||||
We need to have Ceph RBD devices mapped first before use in a stack |
||||
where LVM is on top so make sure rbdmap.service is called before |
||||
generated lvm2-activation-net.service. |
||||
|
||||
On shutdown, we need to stop blk-availability first before we stop the |
||||
rbdmap.service. |
||||
|
||||
Resolves: rhbz1623479 |
||||
(cherry picked from commit cb17ef221bdefea3625a22c19c6d8f5504441771) |
||||
|
||||
Conflicts: |
||||
WHATS_NEW |
||||
|
||||
(cherry picked from commit 3374a592502ef099d38491b0c2020a6945d825b1) |
||||
|
||||
Conflicts: |
||||
WHATS_NEW |
||||
--- |
||||
WHATS_NEW | 2 ++ |
||||
scripts/blk_availability_systemd_red_hat.service.in | 2 +- |
||||
scripts/lvm2_activation_generator_systemd_red_hat.c | 2 +- |
||||
3 files changed, 4 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 92e5c04..9da40b6 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,9 +1,11 @@ |
||||
Version 2.02.182 - |
||||
============================== |
||||
+ Add After=rbdmap.service to {lvm2-activation-net,blk-availability}.service. |
||||
Fix lvconvert conversion attempts to linear. |
||||
Fix lvconvert raid0/raid0_meta -> striped regression. |
||||
Fix lvconvert --splitmirror for mirror type (2.02.178). |
||||
Do not pair cache policy and cache metadata format. |
||||
+ Fix mirrors honoring read_only_volume_list. |
||||
|
||||
Version 2.02.181 - |
||||
================================= |
||||
diff --git a/scripts/blk_availability_systemd_red_hat.service.in b/scripts/blk_availability_systemd_red_hat.service.in |
||||
index 1198baa..9462072 100644 |
||||
--- a/scripts/blk_availability_systemd_red_hat.service.in |
||||
+++ b/scripts/blk_availability_systemd_red_hat.service.in |
||||
@@ -1,6 +1,6 @@ |
||||
[Unit] |
||||
Description=Availability of block devices |
||||
-After=lvm2-activation.service lvm2-lvmetad.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service |
||||
+After=lvm2-activation.service lvm2-lvmetad.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service rbdmap.service |
||||
DefaultDependencies=no |
||||
Conflicts=shutdown.target |
||||
|
||||
diff --git a/scripts/lvm2_activation_generator_systemd_red_hat.c b/scripts/lvm2_activation_generator_systemd_red_hat.c |
||||
index 0f7f89c..487582f 100644 |
||||
--- a/scripts/lvm2_activation_generator_systemd_red_hat.c |
||||
+++ b/scripts/lvm2_activation_generator_systemd_red_hat.c |
||||
@@ -128,7 +128,7 @@ static int generate_unit(const char *dir, int unit, int sysinit_needed) |
||||
"DefaultDependencies=no\n", f); |
||||
|
||||
if (unit == UNIT_NET) { |
||||
- fprintf(f, "After=%s iscsi.service fcoe.service\n" |
||||
+ fprintf(f, "After=%s iscsi.service fcoe.service rbdmap.service\n" |
||||
"Before=remote-fs-pre.target shutdown.target\n\n" |
||||
"[Service]\n" |
||||
"ExecStartPre=/usr/bin/udevadm settle\n", unit_names[UNIT_MAIN]); |
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
lib/label/label.c | 6 +++--- |
||||
tools/toollib.c | 7 +++++++ |
||||
2 files changed, 10 insertions(+), 3 deletions(-) |
||||
|
||||
diff --git a/lib/label/label.c b/lib/label/label.c |
||||
index ac37713..bafa543 100644 |
||||
--- a/lib/label/label.c |
||||
+++ b/lib/label/label.c |
||||
@@ -1190,7 +1190,7 @@ bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data) |
||||
return false; |
||||
} |
||||
|
||||
- if (!(dev->flags & DEV_BCACHE_WRITE)) { |
||||
+ if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_WRITE)) { |
||||
/* FIXME: avoid tossing out bcache blocks just to replace fd. */ |
||||
log_debug("Close and reopen to write %s", dev_name(dev)); |
||||
bcache_invalidate_fd(scan_bcache, dev->bcache_fd); |
||||
@@ -1236,7 +1236,7 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len) |
||||
return false; |
||||
} |
||||
|
||||
- if (!(dev->flags & DEV_BCACHE_WRITE)) { |
||||
+ if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_WRITE)) { |
||||
/* FIXME: avoid tossing out bcache blocks just to replace fd. */ |
||||
log_debug("Close and reopen to write %s", dev_name(dev)); |
||||
bcache_invalidate_fd(scan_bcache, dev->bcache_fd); |
||||
@@ -1282,7 +1282,7 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val) |
||||
return false; |
||||
} |
||||
|
||||
- if (!(dev->flags & DEV_BCACHE_WRITE)) { |
||||
+ if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_WRITE)) { |
||||
/* FIXME: avoid tossing out bcache blocks just to replace fd. */ |
||||
log_debug("Close and reopen to write %s", dev_name(dev)); |
||||
bcache_invalidate_fd(scan_bcache, dev->bcache_fd); |
||||
diff --git a/tools/toollib.c b/tools/toollib.c |
||||
index b60ff06..e1c86f9 100644 |
||||
--- a/tools/toollib.c |
||||
+++ b/tools/toollib.c |
||||
@@ -5897,6 +5897,13 @@ do_command: |
||||
pd->name); |
||||
} |
||||
|
||||
+ /* |
||||
+ * Don't keep devs open excl in bcache because the excl will prevent |
||||
+ * using that dev elsewhere. |
||||
+ */ |
||||
+ dm_list_iterate_items(devl, &rescan_devs) |
||||
+ label_scan_invalidate(devl->dev); |
||||
+ |
||||
dm_list_iterate_items(pd, &pp->arg_fail) |
||||
log_debug("%s: command failed for %s.", |
||||
cmd->command->name, pd->name); |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue