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/2800adf344e3
branches:  trunk
changeset: 983467:2800adf344e3
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 70dcdbc5fc4a -r 2800adf344e3 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 70dcdbc5fc4a -r 2800adf344e3 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 70dcdbc5fc4a -r 2800adf344e3 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