Hello community,

here is the log from the commit of package lvm2 for openSUSE:Factory checked in 
at 2019-12-27 13:43:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lvm2 (Old)
 and      /work/SRC/openSUSE:Factory/.lvm2.new.6675 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "lvm2"

Fri Dec 27 13:43:46 2019 rev:131 rq:759147 version:2.03.05

Changes:
--------
--- /work/SRC/openSUSE:Factory/lvm2/lvm2.changes        2019-12-23 
22:36:58.525808118 +0100
+++ /work/SRC/openSUSE:Factory/.lvm2.new.6675/lvm2.changes      2019-12-27 
13:43:53.628254934 +0100
@@ -1,0 +2,13 @@
+Mon Dec 23 07:22:00 UTC 2019 - heming.z...@suse.com
+
+- LVM Metadata Error: Error writing device at 4096 length 512 (bsc#1150021)
+ + bug-1150021_01-scanning-open-devs-rw-when-rescanning-for-write.patch
+ + bug-1150021_02-bcache-add-bcache_abort.patch
+ + bug-1150021_03-label-Use-bcache_abort_fd-to-ensure-blocks-are-no-lo.patch
+ + bug-1150021_04-bcache-add-unit-test.patch
+ + bug-1150021_05-bcache-bcache_invalidate_fd-only-remove-prefixes-on.patch
+ + bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch
+- Update patch, according to bug-1150021_01-scanning-xxx.patch
+ + bug-1158861_06-fix-segfault-for-invalid-characters-in-vg-name.patch
+
+-------------------------------------------------------------------

New:
----
  bug-1150021_01-scanning-open-devs-rw-when-rescanning-for-write.patch
  bug-1150021_02-bcache-add-bcache_abort.patch
  bug-1150021_03-label-Use-bcache_abort_fd-to-ensure-blocks-are-no-lo.patch
  bug-1150021_04-bcache-add-unit-test.patch
  bug-1150021_05-bcache-bcache_invalidate_fd-only-remove-prefixes-on.patch
  bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ lvm2.spec ++++++
--- /var/tmp/diff_new_pack.nObjPU/_old  2019-12-27 13:43:54.768255744 +0100
+++ /var/tmp/diff_new_pack.nObjPU/_new  2019-12-27 13:43:54.772255747 +0100
@@ -56,36 +56,42 @@
 Source99:       baselibs.conf
 # Upstream patches
 Patch0001:      bug-1122666_devices-drop-open-error-message.patch
-Patch0002:      bug-1149408_Fix-rounding-writes-up-to-sector-size.patch
-Patch0003:      
bug-1149408_vgcreate-vgextend-restrict-PVs-with-mixed-block-size.patch
-Patch0004:      
bug-1152378-md-component-detection-for-differing-PV-and-device-s.patch
-Patch0005:      
bug-1152378-pvscan-fix-PV-online-when-device-has-a-different-siz.patch
-Patch0006:      jcs-SLE5498_pvscan-allow-use-of-noudevsync-option.patch
-Patch0007:      
bug-1154655_udev-remove-unsupported-OPTIONS-event_timeout-rule.patch
-Patch0008:      bug-1158628_01-tests-replaces-grep-q-usage.patch
-Patch0009:      bug-1158628_02-tests-fix-ra-checking.patch
-Patch0010:      bug-1158628_03-tests-simplify-some-var-settings.patch
-Patch0011:      bug-1158628-04-pvmove-correcting-read_ahead-setting.patch
-Patch0012:      bug-1158628_05-activation-add-synchronization-point.patch
-Patch0013:      bug-1158628_06-pvmove-add-missing-synchronization.patch
-Patch0014:      
bug-1158628_07-activation-extend-handling-of-pending_delete.patch
-Patch0015:      bug-1158628_08-lv_manip-add-synchronizations.patch
-Patch0016:      
bug-1158628_09-lvconvert-improve-validation-thin-and-cache-pool-con.patch
-Patch0017:      bug-1158628_10-thin-activate-layer-pool-aas-read-only-LV.patch
-Patch0018:      bug-1158628_11-tests-mdadm-stop-in-test-cleanup.patch
-Patch0019:      
bug-1158628_12-test-increase-size-of-raid10-LV-allowing-tests-to-su.patch
-Patch0020:      
bug-1158628_13-lvconvert-fix-return-value-when-zeroing-fails.patch
-Patch0021:      bug-1158628_14-tests-add-extra-settle.patch
-Patch0022:      
bug-1158628_15-test-Fix-handling-leftovers-from-previous-tests.patch
-Patch0023:      bug-1158861_01-config-remove-filter-typo.patch
-Patch0024:      
bug-1158861_02-config-Fix-default-option-which-makes-no-sense.patch
-Patch0025:      
bug-1158861_03-vgchange-don-t-fail-monitor-command-if-vg-is-exporte.patch
-Patch0026:      bug-1158861_04-fix-duplicate-pv-size-check.patch
-Patch0027:      bug-1158861_05-hints-fix-copy-of-filter.patch
-Patch0028:      
bug-1158861_06-fix-segfault-for-invalid-characters-in-vg-name.patch
-Patch0029:      
bug-1158861_07-vgck-let-updatemetadata-repair-mismatched-metadata.patch
-Patch0030:      bug-1158861_08-hints-fix-mem-leaking-buffers.patch
-Patch0031:      
bug-1158861_09-pvcreate-pvremove-fix-reacquiring-global-lock-after.patch
+Patch0002:      
bug-1150021_01-scanning-open-devs-rw-when-rescanning-for-write.patch
+Patch0003:      bug-1149408_Fix-rounding-writes-up-to-sector-size.patch
+Patch0004:      
bug-1149408_vgcreate-vgextend-restrict-PVs-with-mixed-block-size.patch
+Patch0005:      
bug-1152378-md-component-detection-for-differing-PV-and-device-s.patch
+Patch0006:      
bug-1152378-pvscan-fix-PV-online-when-device-has-a-different-siz.patch
+Patch0007:      jcs-SLE5498_pvscan-allow-use-of-noudevsync-option.patch
+Patch0008:      
bug-1154655_udev-remove-unsupported-OPTIONS-event_timeout-rule.patch
+Patch0009:      bug-1158628_01-tests-replaces-grep-q-usage.patch
+Patch0010:      bug-1158628_02-tests-fix-ra-checking.patch
+Patch0011:      bug-1158628_03-tests-simplify-some-var-settings.patch
+Patch0012:      bug-1158628-04-pvmove-correcting-read_ahead-setting.patch
+Patch0013:      bug-1158628_05-activation-add-synchronization-point.patch
+Patch0014:      bug-1158628_06-pvmove-add-missing-synchronization.patch
+Patch0015:      
bug-1158628_07-activation-extend-handling-of-pending_delete.patch
+Patch0016:      bug-1158628_08-lv_manip-add-synchronizations.patch
+Patch0017:      
bug-1158628_09-lvconvert-improve-validation-thin-and-cache-pool-con.patch
+Patch0018:      bug-1158628_10-thin-activate-layer-pool-aas-read-only-LV.patch
+Patch0019:      bug-1158628_11-tests-mdadm-stop-in-test-cleanup.patch
+Patch0020:      
bug-1158628_12-test-increase-size-of-raid10-LV-allowing-tests-to-su.patch
+Patch0021:      
bug-1158628_13-lvconvert-fix-return-value-when-zeroing-fails.patch
+Patch0022:      bug-1158628_14-tests-add-extra-settle.patch
+Patch0023:      
bug-1158628_15-test-Fix-handling-leftovers-from-previous-tests.patch
+Patch0024:      bug-1158861_01-config-remove-filter-typo.patch
+Patch0025:      
bug-1158861_02-config-Fix-default-option-which-makes-no-sense.patch
+Patch0026:      
bug-1158861_03-vgchange-don-t-fail-monitor-command-if-vg-is-exporte.patch
+Patch0027:      bug-1158861_04-fix-duplicate-pv-size-check.patch
+Patch0028:      bug-1158861_05-hints-fix-copy-of-filter.patch
+Patch0029:      
bug-1158861_06-fix-segfault-for-invalid-characters-in-vg-name.patch
+Patch0030:      
bug-1158861_07-vgck-let-updatemetadata-repair-mismatched-metadata.patch
+Patch0031:      bug-1158861_08-hints-fix-mem-leaking-buffers.patch
+Patch0032:      
bug-1158861_09-pvcreate-pvremove-fix-reacquiring-global-lock-after.patch
+Patch0033:      bug-1150021_02-bcache-add-bcache_abort.patch
+Patch0034:      
bug-1150021_03-label-Use-bcache_abort_fd-to-ensure-blocks-are-no-lo.patch
+Patch0035:      bug-1150021_04-bcache-add-unit-test.patch
+Patch0036:      
bug-1150021_05-bcache-bcache_invalidate_fd-only-remove-prefixes-on.patch
+Patch0037:      bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch
 # SUSE patches: 1000+ for LVM
 # Never upstream
 Patch1001:      cmirrord_remove_date_time_from_compilation.patch
@@ -170,6 +176,12 @@
 %patch0029 -p1
 %patch0030 -p1
 %patch0031 -p1
+%patch0032 -p1
+%patch0033 -p1
+%patch0034 -p1
+%patch0035 -p1
+%patch0036 -p1
+%patch0037 -p1
 %patch1001 -p1
 %patch1002 -p1
 %patch1003 -p1


++++++ bug-1150021_01-scanning-open-devs-rw-when-rescanning-for-write.patch 
++++++
>From d16142f90fdcf2aef42a51ecabd0c4ff11733d7c Mon Sep 17 00:00:00 2001
From: David Teigland <teigl...@redhat.com>
Date: Tue, 11 Jun 2019 16:17:24 -0500
Subject: [PATCH] scanning: open devs rw when rescanning for write

When vg_read rescans devices with the intention of
writing the VG, the label rescan can open the devs
RW so they do not need to be closed and reopened
RW in dev_write_bytes.
---
 lib/cache/lvmcache.c             | 17 ++++++++--
 lib/cache/lvmcache.h             |  1 +
 lib/label/label.c                | 32 +++++++++++++++++-
 lib/label/label.h                |  1 +
 lib/metadata/metadata-exported.h |  5 +--
 lib/metadata/metadata.c          | 72 ++++++++++++++++++++++++++--------------
 tools/lvchange.c                 |  2 +-
 tools/pvscan.c                   |  2 +-
 tools/vgchange.c                 |  4 ++-
 9 files changed, 103 insertions(+), 33 deletions(-)

diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 1d92e0198d..e2d19e8996 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -772,7 +772,7 @@ next:
  * to that VG after a scan.
  */
 
-int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, 
const char *vgid)
+static int _label_rescan_vg(struct cmd_context *cmd, const char *vgname, const 
char *vgid, int rw)
 {
        struct dm_list devs;
        struct device_list *devl, *devl2;
@@ -804,7 +804,10 @@ int lvmcache_label_rescan_vg(struct cmd_context *cmd, 
const char *vgname, const
        /* FIXME: should we also rescan unused_duplicate_devs for devs
           being rescanned here and then repeat resolving the duplicates? */
 
-       label_scan_devs(cmd, cmd->filter, &devs);
+       if (rw)
+               label_scan_devs_rw(cmd, cmd->filter, &devs);
+       else
+               label_scan_devs(cmd, cmd->filter, &devs);
 
        dm_list_iterate_items_safe(devl, devl2, &devs) {
                dm_list_del(&devl->list);
@@ -819,6 +822,16 @@ int lvmcache_label_rescan_vg(struct cmd_context *cmd, 
const char *vgname, const
        return 1;
 }
 
+int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, 
const char *vgid)
+{
+       return _label_rescan_vg(cmd, vgname, vgid, 0);
+}
+
+int lvmcache_label_rescan_vg_rw(struct cmd_context *cmd, const char *vgname, 
const char *vgid)
+{
+       return _label_rescan_vg(cmd, vgname, vgid, 1);
+}
+
 /*
  * Uses label_scan to populate lvmcache with 'vginfo' struct for each VG
  * and associated 'info' structs for those VGs.  Only VG summary information
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 5b78d7afb2..e2d967c625 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -71,6 +71,7 @@ void lvmcache_destroy(struct cmd_context *cmd, int 
retain_orphans, int reset);
 
 int lvmcache_label_scan(struct cmd_context *cmd);
 int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, 
const char *vgid);
+int lvmcache_label_rescan_vg_rw(struct cmd_context *cmd, const char *vgname, 
const char *vgid);
 
 /* Add/delete a device */
 struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
diff --git a/lib/label/label.c b/lib/label/label.c
index a8d87ec16c..185e51b0c3 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1118,7 +1118,37 @@ int label_scan_devs(struct cmd_context *cmd, struct 
dev_filter *f, struct dm_lis
 
        _scan_list(cmd, f, devs, NULL);
 
-       /* FIXME: this function should probably fail if any devs couldn't be 
scanned */
+       return 1;
+}
+
+/*
+ * This function is used when the caller plans to write to the devs, so opening
+ * them RW during rescan avoids needing to close and reopen with WRITE in
+ * dev_write_bytes.
+ */
+
+int label_scan_devs_rw(struct cmd_context *cmd, struct dev_filter *f, struct 
dm_list *devs)
+{
+       struct device_list *devl;
+
+       if (!scan_bcache) {
+               if (!_setup_bcache(0))
+                       return 0;
+       }
+
+       dm_list_iterate_items(devl, devs) {
+               if (_in_bcache(devl->dev)) {
+                       bcache_invalidate_fd(scan_bcache, devl->dev->bcache_fd);
+                       _scan_dev_close(devl->dev);
+               }
+               /*
+                * With this flag set, _scan_dev_open() done by
+                * _scan_list() will do open RW
+                */
+               devl->dev->flags |= DEV_BCACHE_WRITE;
+       }
+
+       _scan_list(cmd, f, devs, NULL);
 
        return 1;
 }
diff --git a/lib/label/label.h b/lib/label/label.h
index 07bb77d884..f06b7df639 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -104,6 +104,7 @@ extern struct bcache *scan_bcache;
 
 int label_scan(struct cmd_context *cmd);
 int label_scan_devs(struct cmd_context *cmd, struct dev_filter *f, struct 
dm_list *devs);
+int label_scan_devs_rw(struct cmd_context *cmd, struct dev_filter *f, struct 
dm_list *devs);
 int label_scan_devs_excl(struct dm_list *devs);
 void label_scan_invalidate(struct device *dev);
 void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume 
*lv);
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 9029d3f640..966c88f95e 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -184,8 +184,9 @@
 #define READ_ALLOW_EXPORTED    0x00020000U
 #define READ_OK_NOTFOUND       0x00040000U
 #define READ_WARN_INCONSISTENT 0x00080000U
-#define READ_FOR_UPDATE                0x00100000U /* A meta-flag, useful with 
toollib for_each_* functions. */
-#define PROCESS_SKIP_SCAN       0x00200000U /* skip lvmcache_label_scan in 
process_each_pv */
+#define READ_FOR_UPDATE                0x00100000U /* command tells vg_read it 
plans to write the vg */
+#define PROCESS_SKIP_SCAN      0x00200000U /* skip lvmcache_label_scan in 
process_each_pv */
+#define READ_FOR_ACTIVATE      0x00400000U /* command tells vg_read it plans 
to activate the vg */
 
 /* vg_read returns these in error_flags */
 #define FAILED_NOT_ENABLED     0x00000001U
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 039a7d690d..7b0d6ce923 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -4476,7 +4476,8 @@ void vg_write_commit_bad_mdas(struct cmd_context *cmd, 
struct volume_group *vg)
 static struct volume_group *_vg_read(struct cmd_context *cmd,
                                     const char *vgname,
                                     const char *vgid,
-                                    unsigned precommitted)
+                                    unsigned precommitted,
+                                    int writing)
 {
        const struct format_type *fmt = cmd->fmt;
        struct format_instance *fid = NULL;
@@ -4530,8 +4531,11 @@ static struct volume_group *_vg_read(struct cmd_context 
*cmd,
         * we can also skip the rescan in that case.
         */
        if (!cmd->can_use_one_scan || lvmcache_scan_mismatch(cmd, vgname, 
vgid)) {
-               log_debug_metadata("Rescanning devices for %s", vgname);
-               lvmcache_label_rescan_vg(cmd, vgname, vgid);
+               log_debug_metadata("Rescanning devices for %s %s", vgname, 
writing ? "rw" : "");
+               if (writing)
+                       lvmcache_label_rescan_vg_rw(cmd, vgname, vgid);
+               else
+                       lvmcache_label_rescan_vg(cmd, vgname, vgid);
        } else {
                log_debug_metadata("Skipped rescanning devices for %s", vgname);
        }
@@ -4752,6 +4756,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, 
const char *vg_name, const
        int missing_pv_flag = 0;
        uint32_t failure = 0;
        int writing = (read_flags & READ_FOR_UPDATE);
+       int activating = (read_flags & READ_FOR_ACTIVATE);
 
        if (is_orphan_vg(vg_name)) {
                log_very_verbose("Reading orphan VG %s", vg_name);
@@ -4766,13 +4771,23 @@ struct volume_group *vg_read(struct cmd_context *cmd, 
const char *vg_name, const
                return NULL;
        }
 
-       if (!lock_vol(cmd, vg_name, writing ? LCK_VG_WRITE : LCK_VG_READ, 
NULL)) {
+       /*
+        * When a command is reading the VG with the intention of eventually
+        * writing it, it passes the READ_FOR_UPDATE flag.  This causes vg_read
+        * to acquire an exclusive VG lock, and causes vg_read to do some more
+        * checks, e.g. that the VG is writable and not exported.  It also
+        * means that when the label scan is repeated on the VG's devices, the
+        * VG's PVs can be reopened read-write when rescanning in anticipation
+        * of needing to write to them.
+        */
+
+       if (!lock_vol(cmd, vg_name, (writing || activating) ? LCK_VG_WRITE : 
LCK_VG_READ, NULL)) {
                log_error("Can't get lock for %s", vg_name);
                failure |= FAILED_LOCKING;
                goto_bad;
        }
 
-       if (!(vg = _vg_read(cmd, vg_name, vgid, 0))) {
+       if (!(vg = _vg_read(cmd, vg_name, vgid, 0, writing))) {
                /* Some callers don't care if the VG doesn't exist and don't 
want an error message. */
                if (!(read_flags & READ_OK_NOTFOUND))
                        log_error("Volume group \"%s\" not found", vg_name);
@@ -4883,29 +4898,36 @@ struct volume_group *vg_read(struct cmd_context *cmd, 
const char *vg_name, const
                goto_bad;
        }
 
-       if (writing && !(read_flags & READ_ALLOW_EXPORTED) && 
vg_is_exported(vg)) {
-               log_error("Volume group %s is exported", vg->name);
-               failure |= FAILED_EXPORTED;
-               goto_bad;
-       }
+       /*
+        * If the command intends to write or activate the VG, there are
+        * additional restrictions.  FIXME: These restrictions should
+        * probably be checked/applied after vg_read returns.
+        */
+       if (writing || activating) {
+               if (!(read_flags & READ_ALLOW_EXPORTED) && vg_is_exported(vg)) {
+                       log_error("Volume group %s is exported", vg->name);
+                       failure |= FAILED_EXPORTED;
+                       goto_bad;
+               }
 
-       if (writing && !(vg->status & LVM_WRITE)) {
-               log_error("Volume group %s is read-only", vg->name);
-               failure |= FAILED_READ_ONLY;
-               goto_bad;
-       }
+               if (!(vg->status & LVM_WRITE)) {
+                       log_error("Volume group %s is read-only", vg->name);
+                       failure |= FAILED_READ_ONLY;
+                       goto_bad;
+               }
 
-       if (!cmd->handles_missing_pvs && (missing_pv_dev || missing_pv_flag) && 
writing) {
-               log_error("Cannot change VG %s while PVs are missing.", 
vg->name);
-               log_error("See vgreduce --removemissing and vgextend 
--restoremissing.");
-               failure |= FAILED_NOT_ENABLED;
-               goto_bad;
-       }
+               if (!cmd->handles_missing_pvs && (missing_pv_dev || 
missing_pv_flag)) {
+                       log_error("Cannot change VG %s while PVs are missing.", 
vg->name);
+                       log_error("See vgreduce --removemissing and vgextend 
--restoremissing.");
+                       failure |= FAILED_NOT_ENABLED;
+                       goto_bad;
+               }
 
-       if (!cmd->handles_unknown_segments && vg_has_unknown_segments(vg) && 
writing) {
-               log_error("Cannot change VG %s with unknown segments in it!", 
vg->name);
-               failure |= FAILED_NOT_ENABLED; /* FIXME new failure code here? 
*/
-               goto_bad;
+               if (!cmd->handles_unknown_segments && 
vg_has_unknown_segments(vg)) {
+                       log_error("Cannot change VG %s with unknown segments in 
it!", vg->name);
+                       failure |= FAILED_NOT_ENABLED; /* FIXME new failure 
code here? */
+                       goto_bad;
+               }
        }
 
        /*
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 7bdf99742a..e7fb57d1d3 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -1435,7 +1435,7 @@ int lvchange_activate_cmd(struct cmd_context *cmd, int 
argc, char **argv)
        } else /* Component LVs might be active, support easy deactivation */
                cmd->process_component_lvs = 1;
 
-       ret = process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE,
+       ret = process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_ACTIVATE,
                              NULL, &_lvchange_activate_check, 
&_lvchange_activate_single);
 
        if (ret != ECMD_PROCESSED)
diff --git a/tools/pvscan.c b/tools/pvscan.c
index d41345fac2..12711cb0ae 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -900,7 +900,7 @@ static int _pvscan_aa(struct cmd_context *cmd, struct 
pvscan_aa_params *pp,
                return ECMD_PROCESSED;
        }
 
-       ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, READ_FOR_UPDATE, 0, 
handle, _pvscan_aa_single);
+       ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, READ_FOR_ACTIVATE, 
0, handle, _pvscan_aa_single);
 
        destroy_processing_handle(cmd, handle);
 
diff --git a/tools/vgchange.c b/tools/vgchange.c
index a17f4566ff..aad6db32fb 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -800,8 +800,10 @@ int vgchange(struct cmd_context *cmd, int argc, char 
**argv)
                        cmd->lockd_vg_enforce_sh = 1;
        }
 
-       if (update || arg_is_set(cmd, activate_ARG))
+       if (update)
                flags |= READ_FOR_UPDATE;
+       else if (arg_is_set(cmd, activate_ARG))
+               flags |= READ_FOR_ACTIVATE;
 
        if (!(handle = init_processing_handle(cmd, NULL))) {
                log_error("Failed to initialize processing handle.");
-- 
2.16.4

++++++ bug-1150021_02-bcache-add-bcache_abort.patch ++++++
>From 2938b4dcca0a1df661758abfab7f402ea7aab018 Mon Sep 17 00:00:00 2001
From: Joe Thornber <e...@redhat.com>
Date: Mon, 28 Oct 2019 14:29:47 +0000
Subject: [PATCH] [bcache] add bcache_abort()

This gives us a way to cope with write failures.
---
 lib/device/bcache.c  | 33 ++++++++++++++++++++++++++
 lib/device/bcache.h  |  7 ++++++
 test/unit/bcache_t.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index d100419770..b0edf28062 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -1382,6 +1382,39 @@ bool bcache_invalidate_fd(struct bcache *cache, int fd)
 
 //----------------------------------------------------------------
 
+static bool _abort_v(struct radix_tree_iterator *it,
+                     uint8_t *kb, uint8_t *ke, union radix_value v)
+{
+       struct block *b = v.ptr;
+
+       if (b->ref_count) {
+               log_fatal("bcache_abort: block (%d, %llu) still held",
+                        b->fd, (unsigned long long) b->index);
+               return true;
+       }
+
+       _unlink_block(b);
+       _free_block(b);
+
+       // We can't remove the block from the radix tree yet because
+       // we're in the middle of an iteration.
+       return true;
+}
+
+void bcache_abort_fd(struct bcache *cache, int fd)
+{
+        union key k;
+       struct radix_tree_iterator it;
+
+       k.parts.fd = fd;
+
+       it.visit = _abort_v;
+       radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), 
&it);
+       radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + 
sizeof(k.parts.fd));
+}
+
+//----------------------------------------------------------------
+
 void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int 
sector_size)
 {
        _last_byte_fd = fd;
diff --git a/lib/device/bcache.h b/lib/device/bcache.h
index 8c16caa199..7622fd354f 100644
--- a/lib/device/bcache.h
+++ b/lib/device/bcache.h
@@ -144,6 +144,13 @@ bool bcache_invalidate(struct bcache *cache, int fd, 
block_address index);
  */
 bool bcache_invalidate_fd(struct bcache *cache, int fd);
 
+/*
+ * Call this function if flush, or invalidate fail and you do not
+ * wish to retry the writes.  This will throw away any dirty data
+ * not written.  If any blocks for fd are held, then it will call
+ * abort().
+ */
+void bcache_abort_fd(struct bcache *cache, int fd);
 
 //----------------------------------------------------------------
 // The next four functions are utilities written in terms of the above api.
diff --git a/test/unit/bcache_t.c b/test/unit/bcache_t.c
index 92c2d57d4d..668d24d776 100644
--- a/test/unit/bcache_t.c
+++ b/test/unit/bcache_t.c
@@ -793,7 +793,6 @@ static void test_invalidate_after_write_error(void *context)
 
 static void test_invalidate_held_block(void *context)
 {
-
        struct fixture *f = context;
        struct mock_engine *me = f->me;
        struct bcache *cache = f->cache;
@@ -809,6 +808,67 @@ static void test_invalidate_held_block(void *context)
        bcache_put(b);
 }
 
+//----------------------------------------------------------------
+// abort tests
+
+static void test_abort_no_blocks(void *context)
+{
+       struct fixture *f = context;
+       struct bcache *cache = f->cache;
+       int fd = 17;
+
+       // We have no expectations
+       bcache_abort_fd(cache, fd);
+}
+
+static void test_abort_single_block(void *context)
+{
+       struct fixture *f = context;
+       struct bcache *cache = f->cache;
+       struct block *b;
+       int fd = 17;
+
+       T_ASSERT(bcache_get(cache, fd, 0, GF_ZERO, &b));
+       bcache_put(b);
+
+       bcache_abort_fd(cache, fd);
+
+       // no write should be issued
+       T_ASSERT(bcache_flush(cache));
+}
+
+static void test_abort_only_specific_fd(void *context)
+{
+       struct fixture *f = context;
+       struct mock_engine *me = f->me;
+       struct bcache *cache = f->cache;
+       struct block *b;
+       int fd1 = 17, fd2 = 18;
+
+       T_ASSERT(bcache_get(cache, fd1, 0, GF_ZERO, &b));
+       bcache_put(b);
+
+       T_ASSERT(bcache_get(cache, fd1, 1, GF_ZERO, &b));
+       bcache_put(b);
+
+       T_ASSERT(bcache_get(cache, fd2, 0, GF_ZERO, &b));
+       bcache_put(b);
+
+       T_ASSERT(bcache_get(cache, fd2, 1, GF_ZERO, &b));
+       bcache_put(b);
+
+       bcache_abort_fd(cache, fd2);
+
+       // writes for fd1 should still be issued
+       _expect_write(me, fd1, 0);
+       _expect_write(me, fd1, 1);
+
+       _expect(me, E_WAIT);
+       _expect(me, E_WAIT);
+
+       T_ASSERT(bcache_flush(cache));
+}
+
 //----------------------------------------------------------------
 // Chasing a bug reported by dct
 
@@ -897,6 +957,11 @@ static struct test_suite *_small_tests(void)
        T("invalidate-read-error", "invalidate a block that errored", 
test_invalidate_after_read_error);
        T("invalidate-write-error", "invalidate a block that errored", 
test_invalidate_after_write_error);
        T("invalidate-fails-in-held", "invalidating a held block fails", 
test_invalidate_held_block);
+
+       T("abort-with-no-blocks", "you can call abort, even if there are no 
blocks in the cache", test_abort_no_blocks);
+       T("abort-single-block", "single block get silently discarded", 
test_abort_single_block);
+       T("abort-specific-fd", "abort doesn't effect other fds", 
test_abort_only_specific_fd);
+
        T("concurrent-reads-after-invalidate", "prefetch should still issue 
concurrent reads after invalidate",
           test_concurrent_reads_after_invalidate);
 
-- 
2.16.4

++++++ 
bug-1150021_03-label-Use-bcache_abort_fd-to-ensure-blocks-are-no-lo.patch ++++++
diff -Nupr a/lib/label/label.c b/lib/label/label.c
--- a/lib/label/label.c 2019-12-23 16:01:02.144729254 +0800
+++ b/lib/label/label.c 2019-12-23 16:01:25.752772110 +0800
@@ -619,6 +619,14 @@ static void _drop_bad_aliases(struct dev
        }
 }
 
+// Like bcache_invalidate, only it throws any dirty data away if the
+// write fails.
+static void _invalidate_fd(struct bcache *cache, int fd)
+{
+       if (!bcache_invalidate_fd(cache, fd))
+               bcache_abort_fd(cache, fd);
+}
+
 /*
  * Read or reread label/metadata from selected devs.
  *
@@ -730,7 +738,7 @@ static int _scan_list(struct cmd_context
                 * drop it from bcache.
                 */
                if (scan_failed || !is_lvm_device) {
-                       bcache_invalidate_fd(scan_bcache, devl->dev->bcache_fd);
+                       _invalidate_fd(scan_bcache, devl->dev->bcache_fd);
                        _scan_dev_close(devl->dev);
                }
 
@@ -935,7 +943,7 @@ int label_scan(struct cmd_context *cmd)
                 * so this will usually not be true.
                 */
                if (_in_bcache(dev)) {
-                       bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+                       _invalidate_fd(scan_bcache, dev->bcache_fd);
                        _scan_dev_close(dev);
                }
 
@@ -1111,7 +1119,7 @@ int label_scan_devs(struct cmd_context *
 
        dm_list_iterate_items(devl, devs) {
                if (_in_bcache(devl->dev)) {
-                       bcache_invalidate_fd(scan_bcache, devl->dev->bcache_fd);
+                       _invalidate_fd(scan_bcache, devl->dev->bcache_fd);
                        _scan_dev_close(devl->dev);
                }
        }
@@ -1138,7 +1146,7 @@ int label_scan_devs_rw(struct cmd_contex
 
        dm_list_iterate_items(devl, devs) {
                if (_in_bcache(devl->dev)) {
-                       bcache_invalidate_fd(scan_bcache, devl->dev->bcache_fd);
+                       _invalidate_fd(scan_bcache, devl->dev->bcache_fd);
                        _scan_dev_close(devl->dev);
                }
                /*
@@ -1160,7 +1168,7 @@ int label_scan_devs_excl(struct dm_list
 
        dm_list_iterate_items(devl, devs) {
                if (_in_bcache(devl->dev)) {
-                       bcache_invalidate_fd(scan_bcache, devl->dev->bcache_fd);
+                       _invalidate_fd(scan_bcache, devl->dev->bcache_fd);
                        _scan_dev_close(devl->dev);
                }
                /*
@@ -1180,7 +1188,7 @@ int label_scan_devs_excl(struct dm_list
 void label_scan_invalidate(struct device *dev)
 {
        if (_in_bcache(dev)) {
-               bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+               _invalidate_fd(scan_bcache, dev->bcache_fd);
                _scan_dev_close(dev);
        }
 }
@@ -1262,7 +1270,7 @@ int label_read(struct device *dev)
        dm_list_add(&one_dev, &devl->list);
 
        if (_in_bcache(dev)) {
-               bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+               _invalidate_fd(scan_bcache, dev->bcache_fd);
                _scan_dev_close(dev);
        }
 
@@ -1304,7 +1312,7 @@ int label_scan_open_excl(struct device *
        if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_EXCL)) {
                /* FIXME: avoid tossing out bcache blocks just to replace fd. */
                log_debug("Close and reopen excl %s", dev_name(dev));
-               bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+               _invalidate_fd(scan_bcache, dev->bcache_fd);
                _scan_dev_close(dev);
        }
        dev->flags |= DEV_BCACHE_EXCL;
@@ -1317,7 +1325,7 @@ int label_scan_open_rw(struct device *de
        if (_in_bcache(dev) && !(dev->flags & DEV_BCACHE_WRITE)) {
                /* FIXME: avoid tossing out bcache blocks just to replace fd. */
                log_debug("Close and reopen rw %s", dev_name(dev));
-               bcache_invalidate_fd(scan_bcache, dev->bcache_fd);
+               _invalidate_fd(scan_bcache, dev->bcache_fd);
                _scan_dev_close(dev);
        }
        dev->flags |= DEV_BCACHE_WRITE;
@@ -1365,7 +1373,7 @@ bool dev_write_bytes(struct device *dev,
        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);
+               _invalidate_fd(scan_bcache, dev->bcache_fd);
                _scan_dev_close(dev);
 
                dev->flags |= DEV_BCACHE_WRITE;
@@ -1411,7 +1419,7 @@ bool dev_write_zeros(struct device *dev,
        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);
+               _invalidate_fd(scan_bcache, dev->bcache_fd);
                _scan_dev_close(dev);
 
                dev->flags |= DEV_BCACHE_WRITE;
@@ -1462,7 +1470,7 @@ bool dev_set_bytes(struct device *dev, u
        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);
+               _invalidate_fd(scan_bcache, dev->bcache_fd);
                _scan_dev_close(dev);
                /* goes to label_scan_open() since bcache_fd < 0 */
        }
++++++ bug-1150021_04-bcache-add-unit-test.patch ++++++
>From 5fdebf9bbf68a53b9d2153dbd8bf27a36e0ef3cd Mon Sep 17 00:00:00 2001
From: Joe Thornber <e...@redhat.com>
Date: Tue, 29 Oct 2019 10:33:31 +0000
Subject: [PATCH] [bcache] add unit test

abort-forces-read
---
 test/unit/bcache_t.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/test/unit/bcache_t.c b/test/unit/bcache_t.c
index 668d24d776..2a8f931e45 100644
--- a/test/unit/bcache_t.c
+++ b/test/unit/bcache_t.c
@@ -837,6 +837,29 @@ static void test_abort_single_block(void *context)
        T_ASSERT(bcache_flush(cache));
 }
 
+static void test_abort_forces_reread(void *context)
+{
+       struct fixture *f = context;
+       struct mock_engine *me = f->me;
+       struct bcache *cache = f->cache;
+       struct block *b;
+       int fd = 17;
+
+       _expect_read(me, fd, 0);
+       _expect(me, E_WAIT);
+       T_ASSERT(bcache_get(cache, fd, 0, GF_DIRTY, &b));
+       bcache_put(b);
+
+       bcache_abort_fd(cache, fd);
+       T_ASSERT(bcache_flush(cache));
+
+       // Check the block is re-read
+       _expect_read(me, fd, 0);
+       _expect(me, E_WAIT);
+       T_ASSERT(bcache_get(cache, fd, 0, 0, &b));
+       bcache_put(b);
+}
+
 static void test_abort_only_specific_fd(void *context)
 {
        struct fixture *f = context;
@@ -960,6 +983,7 @@ static struct test_suite *_small_tests(void)
 
        T("abort-with-no-blocks", "you can call abort, even if there are no 
blocks in the cache", test_abort_no_blocks);
        T("abort-single-block", "single block get silently discarded", 
test_abort_single_block);
+       T("abort-forces-read", "if a block has been discarded then another read 
is necc.", test_abort_forces_reread);
        T("abort-specific-fd", "abort doesn't effect other fds", 
test_abort_only_specific_fd);
 
        T("concurrent-reads-after-invalidate", "prefetch should still issue 
concurrent reads after invalidate",
-- 
2.16.4

++++++ bug-1150021_05-bcache-bcache_invalidate_fd-only-remove-prefixes-on.patch 
++++++
>From 25e7bf021a4e7c5ad5f925b86605bf025ff1a949 Mon Sep 17 00:00:00 2001
From: Joe Thornber <e...@redhat.com>
Date: Tue, 29 Oct 2019 15:21:11 +0000
Subject: [PATCH] [bcache] bcache_invalidate_fd, only remove prefixes on
 success.

---
 lib/device/bcache.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index b0edf28062..04d49f1656 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -1376,7 +1376,10 @@ bool bcache_invalidate_fd(struct bcache *cache, int fd)
        it.success = true;
        it.it.visit = _invalidate_v;
        radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), 
&it.it);
-       radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + 
sizeof(k.parts.fd));
+
+       if (it.success)
+               radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + 
sizeof(k.parts.fd));
+
        return it.success;
 }
 
-- 
2.16.4

++++++ bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch ++++++
>From 13c254fc05386d05ab6bbda2806f9ca4d3358a0c Mon Sep 17 00:00:00 2001
From: Heming Zhao <heming.z...@suse.com>
Date: Wed, 13 Nov 2019 09:15:07 -0600
Subject: [PATCH] fix dev_unset_last_byte after write error

dev_unset_last_byte() must be called while the fd is still valid.
After a write error, dev_unset_last_byte() must be called before
closing the dev and resetting the fd.

In the write error path, dev_unset_last_byte() was being called
after label_scan_invalidate() which meant that it would not unset
the last_byte values.

After a write error, dev_unset_last_byte() is now called in
dev_write_bytes() before label_scan_invalidate(), instead of by
the caller of dev_write_bytes().

In the common case of a successful write, the sequence is still:
dev_set_last_byte(); dev_write_bytes(); dev_unset_last_byte();

Signed-off-by: Zhao Heming <heming.z...@suse.com>
---
 lib/format_text/format-text.c | 3 ---
 lib/label/label.c             | 8 ++++----
 lib/metadata/mirror.c         | 1 -
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 6ec47bfcef..894a71007d 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -277,7 +277,6 @@ static int _raw_write_mda_header(const struct format_type 
*fmt,
        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;
        }
@@ -769,7 +768,6 @@ static int _vg_write_raw(struct format_i
        if (!dev_write_bytes(mdac->area.dev, mdac->area.start + 
rlocn_new->offset,
                                (size_t) (rlocn_new->size - new_wrap), 
new_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;
        }
 
@@ -782,7 +780,6 @@ static int _vg_write_raw(struct format_i
                if (!dev_write_bytes(mdac->area.dev, mdac->area.start + 
MDA_HEADER_SIZE,
                                        (size_t) new_wrap, new_buf + 
rlocn_new->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;
                }
        }
diff --git a/lib/label/label.c b/lib/label/label.c
index 7dcaf8afd5..05986cbe70 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -218,7 +218,7 @@ int label_write(struct device *dev, struct label *label)
 
        if (!dev_write_bytes(dev, offset, LABEL_SIZE, buf)) {
                log_debug_devs("Failed to write label to %s", dev_name(dev));
-               r = 0;
+               return 0;
        }
 
        dev_unset_last_byte(dev);
@@ -655,7 +655,6 @@ static int _scan_list(struct cmd_context *cmd, struct 
dev_filter *f,
        int submit_count;
        int scan_failed;
        int is_lvm_device;
-       int error;
        int ret;
 
        dm_list_init(&wait_devs);
@@ -702,12 +701,11 @@ static int _scan_list(struct cmd_context *cmd, struct 
dev_filter *f,
 
        dm_list_iterate_items_safe(devl, devl2, &wait_devs) {
                bb = NULL;
-               error = 0;
                scan_failed = 0;
                is_lvm_device = 0;
 
                if (!bcache_get(scan_bcache, devl->dev->bcache_fd, 0, 0, &bb)) {
-                       log_debug_devs("Scan failed to read %s error %d.", 
dev_name(devl->dev), error);
+                       log_debug_devs("Scan failed to read %s.", 
dev_name(devl->dev));
                        scan_failed = 1;
                        scan_read_errors++;
                        scan_failed_count++;
@@ -1451,6 +1449,7 @@ bool dev_write_bytes(struct device *dev, uint64_t start, 
size_t len, void *data)
        if (!bcache_write_bytes(scan_bcache, dev->bcache_fd, start, len, data)) 
{
                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;
        }
@@ -1458,6 +1457,7 @@ bool dev_write_bytes(struct device *dev, uint64_t start, 
size_t len, void *data)
        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;
        }
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
index 01f0246b90..d8803b3e3f 100644
--- a/lib/metadata/mirror.c
+++ b/lib/metadata/mirror.c
@@ -266,7 +266,6 @@ static int _write_log_header(struct cmd_context *cmd, 
struct logical_volume *lv)
        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;
        }
-- 
2.16.4

++++++ bug-1158861_06-fix-segfault-for-invalid-characters-in-vg-name.patch 
++++++
--- /var/tmp/diff_new_pack.nObjPU/_old  2019-12-27 13:43:54.988255900 +0100
+++ /var/tmp/diff_new_pack.nObjPU/_new  2019-12-27 13:43:54.992255903 +0100
@@ -15,10 +15,11 @@
  lib/metadata/metadata.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
 
-diff -Nupr a/lib/metadata/metadata.c b/lib/metadata/metadata.c
---- a/lib/metadata/metadata.c  2019-12-09 15:26:11.751210108 +0800
-+++ b/lib/metadata/metadata.c  2019-12-09 15:26:58.103346514 +0800
-@@ -4829,7 +4829,8 @@ struct volume_group *vg_read(struct cmd_
+diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
+index 2c61bdeca2..6d21ff99cc 100644
+--- a/lib/metadata/metadata.c
++++ b/lib/metadata/metadata.c
+@@ -4900,7 +4900,8 @@ struct volume_group *vg_read(struct cmd_context *cmd, 
const char *vg_name, const
  
        if (!validate_name(vg_name)) {
                log_error("Volume group name \"%s\" has invalid characters.", 
vg_name);
@@ -27,4 +28,7 @@
 +              goto_bad;
        }
  
-       if (!lock_vol(cmd, vg_name, writing ? LCK_VG_WRITE : LCK_VG_READ, 
NULL)) {
+       /*
+-- 
+2.16.4
+


Reply via email to