From b74c0695d27d7bd1cb9e4bde722447edb9b1e375b28f1cd21f747d80a3d744b0 Mon Sep 17 00:00:00 2001 From: Gang He Date: Wed, 25 Dec 2019 02:03:58 +0000 Subject: [PATCH] Accepting request 759060 from home:hmzhao:branches:openSUSE:Factory 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 OBS-URL: https://build.opensuse.org/request/show/759060 OBS-URL: https://build.opensuse.org/package/show/Base:System/lvm2?expand=0&rev=263 --- ...en-devs-rw-when-rescanning-for-write.patch | 310 ++++++++++++++++++ bug-1150021_02-bcache-add-bcache_abort.patch | 169 ++++++++++ ..._abort_fd-to-ensure-blocks-are-no-lo.patch | 126 +++++++ bug-1150021_04-bcache-add-unit-test.patch | 55 ++++ ...nvalidate_fd-only-remove-prefixes-on.patch | 29 ++ ...ev_unset_last_byte-after-write-error.patch | 121 +++++++ ...lt-for-invalid-characters-in-vg-name.patch | 14 +- lvm2.changes | 13 + lvm2.spec | 72 ++-- 9 files changed, 874 insertions(+), 35 deletions(-) create mode 100644 bug-1150021_01-scanning-open-devs-rw-when-rescanning-for-write.patch create mode 100644 bug-1150021_02-bcache-add-bcache_abort.patch create mode 100644 bug-1150021_03-label-Use-bcache_abort_fd-to-ensure-blocks-are-no-lo.patch create mode 100644 bug-1150021_04-bcache-add-unit-test.patch create mode 100644 bug-1150021_05-bcache-bcache_invalidate_fd-only-remove-prefixes-on.patch create mode 100644 bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch diff --git a/bug-1150021_01-scanning-open-devs-rw-when-rescanning-for-write.patch b/bug-1150021_01-scanning-open-devs-rw-when-rescanning-for-write.patch new file mode 100644 index 0000000..ce6f693 --- /dev/null +++ b/bug-1150021_01-scanning-open-devs-rw-when-rescanning-for-write.patch @@ -0,0 +1,310 @@ +From d16142f90fdcf2aef42a51ecabd0c4ff11733d7c Mon Sep 17 00:00:00 2001 +From: David Teigland +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 + diff --git a/bug-1150021_02-bcache-add-bcache_abort.patch b/bug-1150021_02-bcache-add-bcache_abort.patch new file mode 100644 index 0000000..0102236 --- /dev/null +++ b/bug-1150021_02-bcache-add-bcache_abort.patch @@ -0,0 +1,169 @@ +From 2938b4dcca0a1df661758abfab7f402ea7aab018 Mon Sep 17 00:00:00 2001 +From: Joe Thornber +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 + diff --git a/bug-1150021_03-label-Use-bcache_abort_fd-to-ensure-blocks-are-no-lo.patch b/bug-1150021_03-label-Use-bcache_abort_fd-to-ensure-blocks-are-no-lo.patch new file mode 100644 index 0000000..406267c --- /dev/null +++ b/bug-1150021_03-label-Use-bcache_abort_fd-to-ensure-blocks-are-no-lo.patch @@ -0,0 +1,126 @@ +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 */ + } diff --git a/bug-1150021_04-bcache-add-unit-test.patch b/bug-1150021_04-bcache-add-unit-test.patch new file mode 100644 index 0000000..8fe008a --- /dev/null +++ b/bug-1150021_04-bcache-add-unit-test.patch @@ -0,0 +1,55 @@ +From 5fdebf9bbf68a53b9d2153dbd8bf27a36e0ef3cd Mon Sep 17 00:00:00 2001 +From: Joe Thornber +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 + diff --git a/bug-1150021_05-bcache-bcache_invalidate_fd-only-remove-prefixes-on.patch b/bug-1150021_05-bcache-bcache_invalidate_fd-only-remove-prefixes-on.patch new file mode 100644 index 0000000..6bcc579 --- /dev/null +++ b/bug-1150021_05-bcache-bcache_invalidate_fd-only-remove-prefixes-on.patch @@ -0,0 +1,29 @@ +From 25e7bf021a4e7c5ad5f925b86605bf025ff1a949 Mon Sep 17 00:00:00 2001 +From: Joe Thornber +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 + diff --git a/bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch b/bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch new file mode 100644 index 0000000..f21091d --- /dev/null +++ b/bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch @@ -0,0 +1,121 @@ +From 13c254fc05386d05ab6bbda2806f9ca4d3358a0c Mon Sep 17 00:00:00 2001 +From: Heming Zhao +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 +--- + 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 + diff --git a/bug-1158861_06-fix-segfault-for-invalid-characters-in-vg-name.patch b/bug-1158861_06-fix-segfault-for-invalid-characters-in-vg-name.patch index f155e96..8d60c2c 100644 --- a/bug-1158861_06-fix-segfault-for-invalid-characters-in-vg-name.patch +++ b/bug-1158861_06-fix-segfault-for-invalid-characters-in-vg-name.patch @@ -15,10 +15,11 @@ _vg_make_handle function. 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 @@ diff -Nupr a/lib/metadata/metadata.c b/lib/metadata/metadata.c + goto_bad; } - if (!lock_vol(cmd, vg_name, writing ? LCK_VG_WRITE : LCK_VG_READ, NULL)) { + /* +-- +2.16.4 + diff --git a/lvm2.changes b/lvm2.changes index c0598c5..d0a24e1 100644 --- a/lvm2.changes +++ b/lvm2.changes @@ -1,3 +1,16 @@ +------------------------------------------------------------------- +Mon Dec 23 07:22:00 UTC 2019 - heming.zhao@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 + ------------------------------------------------------------------- Tue Dec 10 08:26:00 UTC 2019 - heming.zhao@suse.com diff --git a/lvm2.spec b/lvm2.spec index 7806a49..bbd5666 100644 --- a/lvm2.spec +++ b/lvm2.spec @@ -56,36 +56,42 @@ Source42: ftp://sources.redhat.com/pub/lvm2/LVM2.%{version}.tgz.asc 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 @@ Volume Manager. %patch0029 -p1 %patch0030 -p1 %patch0031 -p1 +%patch0032 -p1 +%patch0033 -p1 +%patch0034 -p1 +%patch0035 -p1 +%patch0036 -p1 +%patch0037 -p1 %patch1001 -p1 %patch1002 -p1 %patch1003 -p1