9eeca8cc12
- DDF-compare_super_ddf-fix-sequence-number-check.patch - Monitor-don-t-set-arrays-dirty-after-transition-to-r.patch - DDF-add_to_super_ddf-be-careful-with-workspace_lba.patch - Monitor-write-meta-data-in-readonly-state-sometimes.patch - Assembe-fix-bug-in-force_array-it-wasn-t-forcing-pro.patch Various bugfixes from upstream - several to improve DDF support, one which fixes a nasty bug in "--assemble --force". - DDF-brief_examine_subarrays_ddf-print-array-name.patch DDF-factor-out-array-name-generation.patch Include name in "-Db" output for DDF FATE#316007 OBS-URL: https://build.opensuse.org/package/show/Base:System/mdadm?expand=0&rev=96
116 lines
3.5 KiB
Diff
116 lines
3.5 KiB
Diff
From 7087f02b90ef7b5817193d385b8d83148565bff9 Mon Sep 17 00:00:00 2001
|
|
From: "mwilck@arcor.de" <mwilck@arcor.de>
|
|
Date: Mon, 9 Sep 2013 20:40:14 +0200
|
|
Subject: [PATCH] DDF: handle fake RAIDs with changing subarray UUIDs
|
|
|
|
Some fake RAID BIOSes (in particular, LSI ones) change the
|
|
VD GUID at every boot. These GUIDs are not suitable for
|
|
identifying an array. Luckily the header GUID appears to
|
|
remain constant.
|
|
|
|
We construct a pseudo-UUID from the header GUID and those
|
|
properties of the subarray that we expect to remain constant.
|
|
This is only array name and index; all else might change e.g.
|
|
during grow.
|
|
|
|
Don't do this for all non-MD arrays, only for those known
|
|
to use varying volume GUIDs.
|
|
|
|
This patch obsoletes my previous patch "DDF: new algorithm
|
|
for subarray UUID"
|
|
|
|
Signed-off-by: Martin Wilck <mwilck@arcor.de>
|
|
Signed-off-by: NeilBrown <neilb@suse.de>
|
|
---
|
|
super-ddf.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
|
1 file changed, 50 insertions(+), 5 deletions(-)
|
|
|
|
--- mdadm-3.3.orig/super-ddf.c
|
|
+++ mdadm-3.3/super-ddf.c
|
|
@@ -1584,6 +1584,7 @@ static void brief_examine_subarrays_ddf(
|
|
continue;
|
|
memcpy(vcl.conf.guid, ve->guid, DDF_GUID_LEN);
|
|
ddf->currentconf =&vcl;
|
|
+ vcl.vcnum = i;
|
|
uuid_from_super_ddf(st, info.uuid);
|
|
fname_from_uuid(st, &info, nbuf1, ':');
|
|
_ddf_array_name(namebuf, ddf, i);
|
|
@@ -1678,6 +1679,52 @@ static void detail_super_ddf(struct supe
|
|
*/
|
|
}
|
|
|
|
+static const char *vendors_with_variable_volume_UUID[] = {
|
|
+ "LSI ",
|
|
+};
|
|
+
|
|
+static int volume_id_is_reliable(const struct ddf_super *ddf)
|
|
+{
|
|
+ int n = sizeof(vendors_with_variable_volume_UUID) /
|
|
+ sizeof(vendors_with_variable_volume_UUID[0]);
|
|
+ int i;
|
|
+ for (i = 0; i < n; i++)
|
|
+ if (!memcmp(ddf->controller.guid,
|
|
+ vendors_with_variable_volume_UUID[i], 8))
|
|
+ return 0;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static void uuid_of_ddf_subarray(const struct ddf_super *ddf,
|
|
+ unsigned int vcnum, int uuid[4])
|
|
+{
|
|
+ char buf[DDF_GUID_LEN+18], sha[20], *p;
|
|
+ struct sha1_ctx ctx;
|
|
+ if (volume_id_is_reliable(ddf)) {
|
|
+ uuid_from_ddf_guid(ddf->virt->entries[vcnum].guid, uuid);
|
|
+ return;
|
|
+ }
|
|
+ /*
|
|
+ * Some fake RAID BIOSes (in particular, LSI ones) change the
|
|
+ * VD GUID at every boot. These GUIDs are not suitable for
|
|
+ * identifying an array. Luckily the header GUID appears to
|
|
+ * remain constant.
|
|
+ * We construct a pseudo-UUID from the header GUID and those
|
|
+ * properties of the subarray that we expect to remain constant.
|
|
+ */
|
|
+ memset(buf, 0, sizeof(buf));
|
|
+ p = buf;
|
|
+ memcpy(p, ddf->anchor.guid, DDF_GUID_LEN);
|
|
+ p += DDF_GUID_LEN;
|
|
+ memcpy(p, ddf->virt->entries[vcnum].name, 16);
|
|
+ p += 16;
|
|
+ *((__u16 *) p) = vcnum;
|
|
+ sha1_init_ctx(&ctx);
|
|
+ sha1_process_bytes(buf, sizeof(buf), &ctx);
|
|
+ sha1_finish_ctx(&ctx, sha);
|
|
+ memcpy(uuid, sha, 4*4);
|
|
+}
|
|
+
|
|
static void brief_detail_super_ddf(struct supertype *st)
|
|
{
|
|
struct mdinfo info;
|
|
@@ -1689,7 +1736,7 @@ static void brief_detail_super_ddf(struc
|
|
else if (vcnum == DDF_NOTFOUND)
|
|
return;
|
|
else
|
|
- uuid_from_ddf_guid(ddf->virt->entries[vcnum].guid, info.uuid);
|
|
+ uuid_of_ddf_subarray(ddf, vcnum, info.uuid);
|
|
fname_from_uuid(st, &info, nbuf,':');
|
|
printf(" UUID=%s", nbuf + 5);
|
|
}
|
|
@@ -1832,13 +1879,11 @@ static void uuid_from_super_ddf(struct s
|
|
*/
|
|
struct ddf_super *ddf = st->sb;
|
|
struct vcl *vcl = ddf->currentconf;
|
|
- char *guid;
|
|
|
|
if (vcl)
|
|
- guid = vcl->conf.guid;
|
|
+ uuid_of_ddf_subarray(ddf, vcl->vcnum, uuid);
|
|
else
|
|
- guid = ddf->anchor.guid;
|
|
- uuid_from_ddf_guid(guid, uuid);
|
|
+ uuid_from_ddf_guid(ddf->anchor.guid, uuid);
|
|
}
|
|
|
|
static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map);
|