diff options
| author | mrg <mrg@NetBSD.org> | 2021-05-26 06:11:50 +0000 |
|---|---|---|
| committer | mrg <mrg@NetBSD.org> | 2021-05-26 06:11:50 +0000 |
| commit | be4b0375e23be3c3f5e8616823b8b5cba4a6c9db (patch) | |
| tree | 5058f9faa372f20ddaaba056cca7b7feb12be9b5 /sys/dev/raidframe | |
| parent | 17dbb091a84333824706e9c38bef8bb696dbec6b (diff) | |
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 (limited to 'sys/dev/raidframe')
| -rw-r--r-- | sys/dev/raidframe/rf_compat80.c | 6 | ||||
| -rw-r--r-- | sys/dev/raidframe/rf_driver.c | 20 | ||||
| -rw-r--r-- | sys/dev/raidframe/rf_netbsdkintf.c | 70 |
3 files changed, 85 insertions, 11 deletions
diff --git a/sys/dev/raidframe/rf_compat80.c b/sys/dev/raidframe/rf_compat80.c index e7d2cad918b..64872eff370 100644 --- a/sys/dev/raidframe/rf_compat80.c +++ b/sys/dev/raidframe/rf_compat80.c @@ -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 *raidPtr, void *data) } 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 --git a/sys/dev/raidframe/rf_driver.c b/sys/dev/raidframe/rf_driver.c index 16ab0057057..19e2d6ee3da 100644 --- a/sys/dev/raidframe/rf_driver.c +++ b/sys/dev/raidframe/rf_driver.c @@ -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_Config_t *cfgPtr, RF_AutoConfig_t *ac) { 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_Config_t *cfgPtr, RF_AutoConfig_t *ac) 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_Config_t *cfgPtr, RF_AutoConfig_t *ac) 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 --git a/sys/dev/raidframe/rf_netbsdkintf.c b/sys/dev/raidframe/rf_netbsdkintf.c index 421cc1c39cf..beb3ba08171 100644 --- a/sys/dev/raidframe/rf_netbsdkintf.c +++ b/sys/dev/raidframe/rf_netbsdkintf.c @@ -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 *raidPtr, RF_RowCol_t col) 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, struct vnode *b_vp, void *data, 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 *clabel, uint64_t numsecs) { 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 *cset) 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 *raidPtr, void *data) 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; } |
