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
This commit is contained in:
parent
5c26b9e3f5
commit
b74c0695d2
@ -0,0 +1,310 @@
|
||||
From d16142f90fdcf2aef42a51ecabd0c4ff11733d7c Mon Sep 17 00:00:00 2001
|
||||
From: David Teigland <teigland@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
|
||||
|
169
bug-1150021_02-bcache-add-bcache_abort.patch
Normal file
169
bug-1150021_02-bcache-add-bcache_abort.patch
Normal file
@ -0,0 +1,169 @@
|
||||
From 2938b4dcca0a1df661758abfab7f402ea7aab018 Mon Sep 17 00:00:00 2001
|
||||
From: Joe Thornber <ejt@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
|
||||
|
@ -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 */
|
||||
}
|
55
bug-1150021_04-bcache-add-unit-test.patch
Normal file
55
bug-1150021_04-bcache-add-unit-test.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 5fdebf9bbf68a53b9d2153dbd8bf27a36e0ef3cd Mon Sep 17 00:00:00 2001
|
||||
From: Joe Thornber <ejt@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
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 25e7bf021a4e7c5ad5f925b86605bf025ff1a949 Mon Sep 17 00:00:00 2001
|
||||
From: Joe Thornber <ejt@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
|
||||
|
121
bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch
Normal file
121
bug-1150021_06-fix-dev_unset_last_byte-after-write-error.patch
Normal file
@ -0,0 +1,121 @@
|
||||
From 13c254fc05386d05ab6bbda2806f9ca4d3358a0c Mon Sep 17 00:00:00 2001
|
||||
From: Heming Zhao <heming.zhao@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.zhao@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
|
||||
|
@ -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
|
||||
|
||||
|
13
lvm2.changes
13
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
|
||||
|
||||
|
72
lvm2.spec
72
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
|
||||
|
Loading…
Reference in New Issue
Block a user