Module Name:    src
Committed By:   mrg
Date:           Wed May 26 06:11:50 UTC 2021

Modified Files:
        src/sys/dev/raidframe: rf_compat80.c rf_driver.c rf_netbsdkintf.c

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/raidframe/rf_compat80.c
cvs rdiff -u -r1.136 -r1.137 src/sys/dev/raidframe/rf_driver.c
cvs rdiff -u -r1.393 -r1.394 src/sys/dev/raidframe/rf_netbsdkintf.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/raidframe/rf_compat80.c
diff -u src/sys/dev/raidframe/rf_compat80.c:1.14 src/sys/dev/raidframe/rf_compat80.c:1.15
--- src/sys/dev/raidframe/rf_compat80.c:1.14	Thu Dec 12 02:15:43 2019
+++ src/sys/dev/raidframe/rf_compat80.c	Wed May 26 06:11:50 2021
@@ -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_label80(RF_Raid_t *raid
 	}
 
 	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));
 

Index: src/sys/dev/raidframe/rf_driver.c
diff -u src/sys/dev/raidframe/rf_driver.c:1.136 src/sys/dev/raidframe/rf_driver.c:1.137
--- src/sys/dev/raidframe/rf_driver.c:1.136	Thu Oct 10 03:43:59 2019
+++ src/sys/dev/raidframe/rf_driver.c	Wed May 26 06:11:50 2021
@@ -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_Configure(RF_Raid_t *raidPtr, RF_Conf
 {
 	RF_RowCol_t col;
 	int rc;
+	bool swapped = false;
+	bool first = true;
 
 	rf_lock_mutex2(configureMutex);
 	configureCount++;
@@ -430,10 +432,21 @@ rf_Configure(RF_Raid_t *raidPtr, RF_Conf
 	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 @@ rf_Configure(RF_Raid_t *raidPtr, RF_Conf
 	       raidPtr->totalSectors,
 	       (raidPtr->totalSectors / 1024 *
 				(1 << raidPtr->logBytesPerSector) / 1024));
+	if (swapped)
+		printf("raid%d: Using swapped-endian component labels.\n",
+		    raidPtr->raidid);
 
 	return (0);
 }

Index: src/sys/dev/raidframe/rf_netbsdkintf.c
diff -u src/sys/dev/raidframe/rf_netbsdkintf.c:1.393 src/sys/dev/raidframe/rf_netbsdkintf.c:1.394
--- src/sys/dev/raidframe/rf_netbsdkintf.c:1.393	Mon May 24 07:43:15 2021
+++ src/sys/dev/raidframe/rf_netbsdkintf.c	Wed May 26 06:11:50 2021
@@ -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 @@ int
 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 @@ raidflush_component_label(RF_Raid_t *rai
 	    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 @@ raidread_component_area(dev_t dev, struc
 	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 @@ rf_reasonable_label(RF_ComponentLabel_t 
 {
 
 	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 @@ rf_cleanup_config_set(RF_ConfigSet_t *cs
 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 @@ rf_get_component_label(RF_Raid_t *raidPt
 		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;
 }

Reply via email to