Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/raidframe support different endian raidframe compone...
details: https://anonhg.NetBSD.org/src/rev/cd3b984858ad
branches: trunk
changeset: 1021314:cd3b984858ad
user: mrg <mrg%NetBSD.org@localhost>
date: Wed May 26 06:11:50 2021 +0000
description:
support different endian raidframe component label.
there are two on-disk formats in use in raidframe:
- the component label
- the parity map
the parity map is a bitmap implemented as bytes, so it has no
endian issue. the component label is the problem, as most of
the fields are 32 bit. this change only supports version 2 of
raidframe (active since the year 2000.)
as component labels are read and used before a raidPtr for the
raid set has been created, there is no obvious storage for the
swapped indicator, so the in-core version remains the on-disk
version, while the rest of in-core label is swapped.
in raidread_component_label() and raidwrite_component_label(),
check if the swapped version, and if so, call new rf_swap_label()
and ensure that the in-core label is native-byte order. for the
write method, an on-stack copy is modified before writing, so
that the in-core version remains valid. (this stack usage is
below other stack usage in similar functions here.)
adjust the label ioctls RAIDFRAME_GET_COMPONENT_LABEL and
RAIDFRAME_GET_COMPONENT_LABEL80 to return the byte-swapped
version so that eg, raidctl -s reports the right version.
when performing final configuration of a raidset, report if a
label swapped, and also complain if there are differently swapped
versions on the other components.
tested on arm64, sparc64 and amd64
ok @oster
diffstat:
sys/dev/raidframe/rf_compat80.c | 6 ++-
sys/dev/raidframe/rf_driver.c | 20 +++++++++-
sys/dev/raidframe/rf_netbsdkintf.c | 70 +++++++++++++++++++++++++++++++++----
3 files changed, 85 insertions(+), 11 deletions(-)
diffs (220 lines):
diff -r 43607e413db6 -r cd3b984858ad sys/dev/raidframe/rf_compat80.c
--- a/sys/dev/raidframe/rf_compat80.c Wed May 26 04:28:15 2021 +0000
+++ b/sys/dev/raidframe/rf_compat80.c Wed May 26 06:11:50 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_compat80.c,v 1.14 2019/12/12 02:15:43 pgoyette Exp $ */
+/* $NetBSD: rf_compat80.c,v 1.15 2021/05/26 06:11:50 mrg Exp $ */
/*
* Copyright (c) 2017 Matthew R. Green
@@ -215,6 +215,10 @@
}
rf_get_component_label(raidPtr, clabel);
+ /* Fix-up for userland. */
+ if (clabel->version == bswap32(RF_COMPONENT_LABEL_VERSION))
+ clabel->version = RF_COMPONENT_LABEL_VERSION;
+
retcode = copyout(clabel, *clabel_ptr, sizeof(**clabel_ptr));
RF_Free(clabel, sizeof(*clabel));
diff -r 43607e413db6 -r cd3b984858ad sys/dev/raidframe/rf_driver.c
--- a/sys/dev/raidframe/rf_driver.c Wed May 26 04:28:15 2021 +0000
+++ b/sys/dev/raidframe/rf_driver.c Wed May 26 06:11:50 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_driver.c,v 1.136 2019/10/10 03:43:59 christos Exp $ */
+/* $NetBSD: rf_driver.c,v 1.137 2021/05/26 06:11:50 mrg Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -66,7 +66,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.136 2019/10/10 03:43:59 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.137 2021/05/26 06:11:50 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_raid_diagnostic.h"
@@ -300,6 +300,8 @@
{
RF_RowCol_t col;
int rc;
+ bool swapped = false;
+ bool first = true;
rf_lock_mutex2(configureMutex);
configureCount++;
@@ -430,10 +432,21 @@
printf("raid%d: Components:", raidPtr->raidid);
for (col = 0; col < raidPtr->numCol; col++) {
+ RF_ComponentLabel_t *clabel;
+ bool compswapped;
+
printf(" %s", raidPtr->Disks[col].devname);
if (RF_DEAD_DISK(raidPtr->Disks[col].status)) {
printf("[**FAILED**]");
}
+ clabel = raidget_component_label(raidPtr, col);
+ compswapped = clabel->version ==
+ bswap32(RF_COMPONENT_LABEL_VERSION);
+ if (first)
+ swapped = compswapped;
+ else if (swapped != compswapped)
+ printf("raid%d: Component %d has different endian "
+ "than first component.", raidPtr->raidid, col);
}
printf("\n");
printf("raid%d: Total Sectors: %" PRIu64 " (%" PRIu64 " MB)\n",
@@ -441,6 +454,9 @@
raidPtr->totalSectors,
(raidPtr->totalSectors / 1024 *
(1 << raidPtr->logBytesPerSector) / 1024));
+ if (swapped)
+ printf("raid%d: Using swapped-endian component labels.\n",
+ raidPtr->raidid);
return (0);
}
diff -r 43607e413db6 -r cd3b984858ad sys/dev/raidframe/rf_netbsdkintf.c
--- a/sys/dev/raidframe/rf_netbsdkintf.c Wed May 26 04:28:15 2021 +0000
+++ b/sys/dev/raidframe/rf_netbsdkintf.c Wed May 26 06:11:50 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_netbsdkintf.c,v 1.393 2021/05/24 07:43:15 mrg Exp $ */
+/* $NetBSD: rf_netbsdkintf.c,v 1.394 2021/05/26 06:11:50 mrg Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2008-2011 The NetBSD Foundation, Inc.
@@ -101,7 +101,7 @@
***********************************************************/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.393 2021/05/24 07:43:15 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.394 2021/05/26 06:11:50 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_raid_autoconfig.h"
@@ -2264,6 +2264,7 @@
raidfetch_component_label(RF_Raid_t *raidPtr, RF_RowCol_t col)
{
KASSERT(raidPtr->bytesPerSector);
+
return raidread_component_label(raidPtr->bytesPerSector,
raidPtr->Disks[col].dev,
raidPtr->raid_cinfo[col].ci_vp,
@@ -2291,15 +2292,54 @@
raidPtr->raid_cinfo[col].ci_vp, label);
}
+/*
+ * Swap the label endianness.
+ *
+ * Everything in the component label is 4-byte-swapped except the version,
+ * which is kept in the byte-swapped version at all times, and indicates
+ * for the writer that a swap is necessary.
+ *
+ * For reads it is expected that out_label == clabel, but writes expect
+ * separate labels so only the re-swapped label is written out to disk,
+ * leaving the swapped-except-version internally.
+ *
+ * Only support swapping label version 2.
+ */
+static void
+rf_swap_label(RF_ComponentLabel_t *clabel, RF_ComponentLabel_t *out_label)
+{
+ int *in, *out, *in_last;
+
+ KASSERT(clabel->version == bswap32(RF_COMPONENT_LABEL_VERSION));
+
+ /* Don't swap the label, but do copy it. */
+ out_label->version = clabel->version;
+
+ in = &clabel->serial_number;
+ in_last = &clabel->future_use2[42];
+ out = &out_label->serial_number;
+
+ for (; in < in_last; in++, out++)
+ *out = bswap32(*in);
+}
static int
raidread_component_label(unsigned secsize, dev_t dev, struct vnode *b_vp,
RF_ComponentLabel_t *clabel)
{
- return raidread_component_area(dev, b_vp, clabel,
+ int error;
+
+ error = raidread_component_area(dev, b_vp, clabel,
sizeof(RF_ComponentLabel_t),
rf_component_info_offset(),
rf_component_info_size(secsize));
+
+ if (error == 0 &&
+ clabel->version == bswap32(RF_COMPONENT_LABEL_VERSION)) {
+ rf_swap_label(clabel, clabel);
+ }
+
+ return error;
}
/* ARGSUSED */
@@ -2340,15 +2380,24 @@
return(error);
}
-
static int
raidwrite_component_label(unsigned secsize, dev_t dev, struct vnode *b_vp,
RF_ComponentLabel_t *clabel)
{
- return raidwrite_component_area(dev, b_vp, clabel,
+ RF_ComponentLabel_t *clabel_write = clabel;
+ RF_ComponentLabel_t lclabel;
+ int error;
+
+ if (clabel->version == bswap32(RF_COMPONENT_LABEL_VERSION)) {
+ clabel_write = &lclabel;
+ rf_swap_label(clabel, clabel_write);
+ }
+ error = raidwrite_component_area(dev, b_vp, clabel_write,
sizeof(RF_ComponentLabel_t),
rf_component_info_offset(),
rf_component_info_size(secsize), 0);
+
+ return error;
}
/* ARGSUSED */
@@ -2962,7 +3011,8 @@
{
if ((clabel->version==RF_COMPONENT_LABEL_VERSION_1 ||
- clabel->version==RF_COMPONENT_LABEL_VERSION) &&
+ clabel->version==RF_COMPONENT_LABEL_VERSION ||
+ clabel->version == bswap32(RF_COMPONENT_LABEL_VERSION)) &&
(clabel->clean == RF_RAID_CLEAN ||
clabel->clean == RF_RAID_DIRTY) &&
clabel->row >=0 &&
@@ -3404,8 +3454,9 @@
void
raid_init_component_label(RF_Raid_t *raidPtr, RF_ComponentLabel_t *clabel)
{
- /* current version number */
- clabel->version = RF_COMPONENT_LABEL_VERSION;
+ /* avoid over-writing byteswapped version. */
+ if (clabel->version != bswap32(RF_COMPONENT_LABEL_VERSION))
+ clabel->version = RF_COMPONENT_LABEL_VERSION;
clabel->serial_number = raidPtr->serial_number;
clabel->mod_counter = raidPtr->mod_counter;
@@ -3795,6 +3846,9 @@
return EINVAL;
raid_clabel = raidget_component_label(raidPtr, column);
memcpy(clabel, raid_clabel, sizeof *clabel);
+ /* Fix-up for userland. */
+ if (clabel->version == bswap32(RF_COMPONENT_LABEL_VERSION))
+ clabel->version = RF_COMPONENT_LABEL_VERSION;
return 0;
}
Home |
Main Index |
Thread Index |
Old Index