mdadm/DDF-handle-fake-RAIDs-with-changing-subarray-UUIDs.patch
Neil Brown 9eeca8cc12 - DDF-handle-fake-RAIDs-with-changing-subarray-UUIDs.patch
- 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
2013-11-11 00:47:33 +00:00

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);