summaryrefslogtreecommitdiff
path: root/sys/dev/raidframe
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2019-02-05 17:13:37 +0000
committerchristos <christos@NetBSD.org>2019-02-05 17:13:37 +0000
commitc0f4f595f33628c17d90262423b43147cc1c0bdf (patch)
tree4598d30a7a57ead04044d51fd2c4952f51c1b958 /sys/dev/raidframe
parent92a054e46d7c52b0c0860cb761d265fabb93f568 (diff)
- Fix the FAIL_DISK handling (it would prolly trash the wrong disk before
since the request structs are different and the row in the old struct is the col in the new one). - Restructure the way compat modules are loaded so that we only load them for the ioctls that need them. Put a comment explaining why... - Set retcode after loading compat (now that the fail disk passthrough hack is gone), so that various ioctls don't always fail.
Diffstat (limited to 'sys/dev/raidframe')
-rw-r--r--sys/dev/raidframe/rf_compat80.c21
-rw-r--r--sys/dev/raidframe/rf_netbsd.h4
-rw-r--r--sys/dev/raidframe/rf_netbsdkintf.c312
3 files changed, 189 insertions, 148 deletions
diff --git a/sys/dev/raidframe/rf_compat80.c b/sys/dev/raidframe/rf_compat80.c
index aeaec3d437e..16d93a106f7 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.8 2019/02/03 08:02:24 pgoyette Exp $ */
+/* $NetBSD: rf_compat80.c,v 1.9 2019/02/05 17:13:37 christos Exp $ */
/*
* Copyright (c) 2017 Matthew R. Green
@@ -222,6 +222,16 @@ rf_config80(RF_Raid_t *raidPtr, int unit, void *data, RF_Config_t **k_cfgp)
return 0;
}
+static int
+rf_fail_disk80(RF_Raid_t *raidPtr, struct rf_recon_req80 *req80)
+{
+ struct rf_recon_req req = {
+ .col = req80.col,
+ .flags = req80.flags,
+ };
+ return rf_fail_disk(raidPtr, &req);
+}
+
int
raidframe_ioctl_80(u_long cmd, int initted, RF_Raid_t *raidPtr, int unit,
void *data, RF_Config_t **k_cfg)
@@ -238,9 +248,8 @@ raidframe_ioctl_80(u_long cmd, int initted, RF_Raid_t *raidPtr, int unit,
return ENXIO;
break;
case RAIDFRAME_CONFIGURE80:
- break;
case RAIDFRAME_FAIL_DISK80:
- return EPASSTHROUGH;
+ break;
default:
return EPASSTHROUGH;
}
@@ -261,8 +270,12 @@ raidframe_ioctl_80(u_long cmd, int initted, RF_Raid_t *raidPtr, int unit,
if (error != 0)
return error;
return EAGAIN; /* flag mainline to call generic config */
+ case RAIDFRAME_FAIL_DISK80:
+ return rf_fail_disk80(raidPtr, data);
+ default:
+ /* abort really */
+ return EPASSTHROUGH;
}
- return EPASSTHROUGH;
}
static void
diff --git a/sys/dev/raidframe/rf_netbsd.h b/sys/dev/raidframe/rf_netbsd.h
index 28c339a7dcf..9342a868465 100644
--- a/sys/dev/raidframe/rf_netbsd.h
+++ b/sys/dev/raidframe/rf_netbsd.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_netbsd.h,v 1.30 2013/04/27 21:18:42 christos Exp $ */
+/* $NetBSD: rf_netbsd.h,v 1.31 2019/02/05 17:13:37 christos Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -103,4 +103,6 @@ typedef struct RF_ConfigSet_s {
struct RF_ConfigSet_s *next;
} RF_ConfigSet_t;
+int rf_fail_disk(RF_Raid_t *, struct rf_recon_req *);
+
#endif /* _RF__RF_NETBSDSTUFF_H_ */
diff --git a/sys/dev/raidframe/rf_netbsdkintf.c b/sys/dev/raidframe/rf_netbsdkintf.c
index bed654e1440..161990ce8cc 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.365 2019/02/05 09:45:38 mrg Exp $ */
+/* $NetBSD: rf_netbsdkintf.c,v 1.366 2019/02/05 17:13:37 christos 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.365 2019/02/05 09:45:38 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.366 2019/02/05 17:13:37 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_raid_autoconfig.h"
@@ -149,6 +149,7 @@ __KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.365 2019/02/05 09:45:38 mrg Exp
#include "rf_parityscan.h"
#include "rf_threadstuff.h"
+#include "rf_compat50.h"
#include "rf_compat80.h"
#ifdef COMPAT_NETBSD32
@@ -1049,6 +1050,145 @@ raid_detach_unlocked(struct raid_softc *rs)
return 0;
}
+static bool
+rf_must_be_initialized(const struct raid_softc *rs, u_long cmd)
+{
+ switch (cmd) {
+ case RAIDFRAME_ADD_HOT_SPARE:
+ case RAIDFRAME_CHECK_COPYBACK_STATUS:
+ case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT:
+ case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT80:
+ case RAIDFRAME_CHECK_PARITY:
+ case RAIDFRAME_CHECK_PARITYREWRITE_STATUS:
+ case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT:
+ case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT80:
+ case RAIDFRAME_CHECK_RECON_STATUS:
+ case RAIDFRAME_CHECK_RECON_STATUS_EXT:
+ case RAIDFRAME_CHECK_RECON_STATUS_EXT80:
+ case RAIDFRAME_COPYBACK:
+ case RAIDFRAME_DELETE_COMPONENT:
+ case RAIDFRAME_FAIL_DISK:
+ case RAIDFRAME_FAIL_DISK80:
+ case RAIDFRAME_GET_ACCTOTALS:
+ case RAIDFRAME_GET_COMPONENT_LABEL:
+ case RAIDFRAME_GET_COMPONENT_LABEL80:
+ case RAIDFRAME_GET_INFO:
+#ifdef RAID_COMPAT32
+ case RAIDFRAME_GET_INFO32:
+#endif
+ case RAIDFRAME_GET_INFO50:
+ case RAIDFRAME_GET_INFO80:
+ case RAIDFRAME_GET_SIZE:
+ case RAIDFRAME_INCORPORATE_HOT_SPARE:
+ case RAIDFRAME_INIT_LABELS:
+ case RAIDFRAME_KEEP_ACCTOTALS:
+ case RAIDFRAME_PARITYMAP_GET_DISABLE:
+ case RAIDFRAME_PARITYMAP_SET_DISABLE:
+ case RAIDFRAME_PARITYMAP_SET_PARAMS:
+ case RAIDFRAME_PARITYMAP_STATUS:
+ case RAIDFRAME_REBUILD_IN_PLACE:
+ case RAIDFRAME_REMOVE_HOT_SPARE:
+ case RAIDFRAME_RESET_ACCTOTALS:
+ case RAIDFRAME_REWRITEPARITY:
+ case RAIDFRAME_SET_AUTOCONFIG:
+ case RAIDFRAME_SET_COMPONENT_LABEL:
+ case RAIDFRAME_SET_ROOT:
+ return (rs->sc_flags & RAIDF_INITED) != 0;
+ }
+ return false;
+}
+
+/*
+ * Really this should be done as part of the default in the ioctl
+ * switch like other compat code, but it is too messy to do that
+ * right now, so we list all the compat ioctls we know about,
+ * and load appropriately.
+ *
+ * XXX[1] what about combinations of compat32 and compat80 ioctls?
+ * XXX[2] what about autoloading the compat32 code? Is there a compat32
+ * ioctl module? Should there be one?
+ */
+static int
+rf_handle_compat(struct raid_softc *rs, int unit, u_long cmd, void *data,
+ RF_Config_t **k_cfg)
+{
+ RF_Raid_t *raidPtr = &rs->sc_r;
+ int retcode = EPASSTHROUGH;
+ switch (cmd) {
+ case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT80:
+ case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT80:
+ case RAIDFRAME_CHECK_RECON_STATUS_EXT80:
+ case RAIDFRAME_CONFIGURE80:
+ case RAIDFRAME_FAIL_DISK80:
+ case RAIDFRAME_GET_COMPONENT_LABEL80:
+ case RAIDFRAME_GET_INFO80:
+ module_autoload("compat_raid_80", MODULE_CLASS_EXEC);
+ MODULE_CALL_HOOK(raidframe_ioctl_80_hook, (cmd,
+ (rs->sc_flags & RAIDF_INITED), raidPtr, unit, data, k_cfg),
+ enosys(), retcode);
+ break;
+ case RAIDFRAME_CONFIGURE50:
+ case RAIDFRAME_GET_INFO50:
+ module_autoload("compat_raid_50", MODULE_CLASS_EXEC);
+ MODULE_CALL_HOOK(raidframe_ioctl_50_hook, (cmd,
+ (rs->sc_flags & RAIDF_INITED), raidPtr, unit, data, k_cfg),
+ enosys(), retcode);
+ break;
+ default:
+ break;
+ }
+ return retcode;
+}
+
+int
+rf_fail_disk(RF_Raid_t *raidPtr, struct rf_recon_req *rr)
+{
+ struct rf_recon_req_internal *rrint;
+
+ if (raidPtr->Layout.map->faultsTolerated == 0) {
+ /* Can't do this on a RAID 0!! */
+ return EINVAL;
+ }
+
+ if (rr->col < 0 || rr->col >= raidPtr->numCol) {
+ /* bad column */
+ return EINVAL;
+ }
+
+ rf_lock_mutex2(raidPtr->mutex);
+ if (raidPtr->status == rf_rs_reconstructing) {
+ /* you can't fail a disk while we're reconstructing! */
+ /* XXX wrong for RAID6 */
+ goto out;
+ }
+ if ((raidPtr->Disks[rr->col].status == rf_ds_optimal) &&
+ (raidPtr->numFailures > 0)) {
+ /* some other component has failed. Let's not make
+ things worse. XXX wrong for RAID6 */
+ goto out;
+ }
+ if (raidPtr->Disks[rr->col].status == rf_ds_spared) {
+ /* Can't fail a spared disk! */
+ goto out;
+ }
+ rf_unlock_mutex2(raidPtr->mutex);
+
+ /* make a copy of the recon request so that we don't rely on
+ * the user's buffer */
+ RF_Malloc(rrint, sizeof(*rrint), (struct rf_recon_req_internal *));
+ if (rrint == NULL)
+ return(ENOMEM);
+ rrint->col = rr->col;
+ rrint->flags = rr->flags;
+ rrint->raidPtr = raidPtr;
+
+ return RF_CREATE_THREAD(raidPtr->recon_thread, rf_ReconThread,
+ rrint, "raid_recon");
+out:
+ rf_unlock_mutex2(raidPtr->mutex);
+ return EINVAL;
+}
+
static int
raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
@@ -1061,12 +1201,11 @@ raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
RF_Raid_t *raidPtr;
RF_RaidDisk_t *diskPtr;
RF_AccTotals_t *totals;
- RF_DeviceConfig_t *d_cfg, *ucfgp;
+ RF_DeviceConfig_t *d_cfg, *ucfgp = data;
u_char *specific_buf;
int retcode = 0;
int column;
/* int raidid; */
- struct rf_recon_req *rr;
struct rf_recon_req_internal *rrint;
RF_ComponentLabel_t *clabel;
RF_ComponentLabel_t *ci_label;
@@ -1076,100 +1215,38 @@ raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
if ((rs = raidget(unit, false)) == NULL)
return ENXIO;
+
dksc = &rs->sc_dksc;
raidPtr = &rs->sc_r;
db1_printf(("raidioctl: %d %d %d %lu\n", (int) dev,
- (int) DISKPART(dev), (int) unit, cmd));
+ (int) DISKPART(dev), (int) unit, cmd));
/* Must be initialized for these... */
- switch (cmd) {
- case RAIDFRAME_REWRITEPARITY:
- case RAIDFRAME_GET_INFO:
- case RAIDFRAME_RESET_ACCTOTALS:
- case RAIDFRAME_GET_ACCTOTALS:
- case RAIDFRAME_KEEP_ACCTOTALS:
- case RAIDFRAME_GET_SIZE:
- case RAIDFRAME_FAIL_DISK:
- case RAIDFRAME_COPYBACK:
- case RAIDFRAME_CHECK_RECON_STATUS:
- case RAIDFRAME_CHECK_RECON_STATUS_EXT:
- case RAIDFRAME_GET_COMPONENT_LABEL:
- case RAIDFRAME_SET_COMPONENT_LABEL:
- case RAIDFRAME_ADD_HOT_SPARE:
- case RAIDFRAME_REMOVE_HOT_SPARE:
- case RAIDFRAME_INIT_LABELS:
- case RAIDFRAME_REBUILD_IN_PLACE:
- case RAIDFRAME_CHECK_PARITY:
- case RAIDFRAME_CHECK_PARITYREWRITE_STATUS:
- case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT:
- case RAIDFRAME_CHECK_COPYBACK_STATUS:
- case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT:
- case RAIDFRAME_SET_AUTOCONFIG:
- case RAIDFRAME_SET_ROOT:
- case RAIDFRAME_DELETE_COMPONENT:
- case RAIDFRAME_INCORPORATE_HOT_SPARE:
- case RAIDFRAME_PARITYMAP_STATUS:
- case RAIDFRAME_PARITYMAP_GET_DISABLE:
- case RAIDFRAME_PARITYMAP_SET_DISABLE:
- case RAIDFRAME_PARITYMAP_SET_PARAMS:
-#ifdef RAID_COMPAT32
- case RAIDFRAME_GET_INFO32:
-#endif
- if ((rs->sc_flags & RAIDF_INITED) == 0)
- return (ENXIO);
- }
-
- /*
- * Handle compat ioctl calls
- *
- * * If compat code is not loaded, stub returns ENOSYS and we just
- * check the "native" cmd's
- * * If compat code is loaded but does not recognize the cmd, it
- * returns EPASSTHROUGH, and we just check the "native" cmd's
- * * If compat code returns EAGAIN, we need to finish via config
- * * Otherwise the cmd has been handled and we just return
- */
- module_autoload("compat_raid_50", MODULE_CLASS_EXEC);
- MODULE_CALL_HOOK(raidframe_ioctl_50_hook,
- (cmd, (rs->sc_flags & RAIDF_INITED),raidPtr, unit, data, &k_cfg),
- enosys(), retcode);
- if (retcode == ENOSYS)
- retcode = 0;
- else if (retcode == EAGAIN)
- goto config;
- else if (retcode != EPASSTHROUGH)
- return retcode;
+ if (rf_must_be_initialized(rs, cmd))
+ return ENXIO;
- module_autoload("compat_raid_80", MODULE_CLASS_EXEC);
- MODULE_CALL_HOOK(raidframe_ioctl_80_hook,
- (cmd, (rs->sc_flags & RAIDF_INITED),raidPtr, unit, data, &k_cfg),
- enosys(), retcode);
- if (retcode == ENOSYS)
+ switch (retcode = rf_handle_compat(rs, unit, cmd, data, &k_cfg)) {
+ case EPASSTHROUGH:
+ /* Not compat, keep going */
retcode = 0;
- else if (retcode == EAGAIN)
+ break;
+ case EAGAIN:
goto config;
- else if (retcode != EPASSTHROUGH)
+ default:
+ /* compat but could not handle it or load the module */
return retcode;
-
- /*
- * XXX
- * Handling of FAIL_DISK80 command requires us to retain retcode's
- * value of EPASSTHROUGH. If you add more compat code later, make
- * sure you don't overwrite retcode and break this!
- */
-
+ }
+
switch (cmd) {
-
/* configure the system */
case RAIDFRAME_CONFIGURE:
#ifdef RAID_COMPAT32
case RAIDFRAME_CONFIGURE32:
#endif
-
if (raidPtr->valid) {
/* There is a valid RAID set running on this unit! */
- printf("raid%d: Device already configured!\n",unit);
+ printf("raid%d: Device already configured!\n", unit);
return(EINVAL);
}
@@ -1487,28 +1564,25 @@ raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
rrint, "raid_reconip");
return(retcode);
- case RAIDFRAME_GET_INFO:
#ifdef RAID_COMPAT32
case RAIDFRAME_GET_INFO32:
+ if (!raidframe_netbsd32_config_hook.hooked)
+ return ENOSYS;
+ ucfgp = NETBSD32PTR64(*(netbsd32_pointer_t *)data);
+ /*FALLTHROUGH*/
#endif
+ case RAIDFRAME_GET_INFO:
RF_Malloc(d_cfg, sizeof(RF_DeviceConfig_t),
(RF_DeviceConfig_t *));
if (d_cfg == NULL)
- return (ENOMEM);
+ return ENOMEM;
retcode = rf_get_info(raidPtr, d_cfg);
if (retcode == 0) {
-#ifdef RAID_COMPAT32
- if (raidframe_netbsd32_config_hook.hooked &&
- cmd == RAIDFRAME_GET_INFO32)
- ucfgp = NETBSD32PTR64(*(netbsd32_pointer_t *)data);
- else
-#endif
- ucfgp = *(RF_DeviceConfig_t **)data;
- retcode = copyout(d_cfg, ucfgp, sizeof(RF_DeviceConfig_t));
+ retcode = copyout(d_cfg, ucfgp, sizeof(*d_cfg));
}
RF_Free(d_cfg, sizeof(RF_DeviceConfig_t));
- return (retcode);
+ return retcode;
case RAIDFRAME_CHECK_PARITY:
*(int *) data = raidPtr->parity_good;
@@ -1551,66 +1625,18 @@ raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
case RAIDFRAME_GET_ACCTOTALS:
totals = (RF_AccTotals_t *) data;
*totals = raidPtr->acc_totals;
- return (0);
+ return 0;
case RAIDFRAME_KEEP_ACCTOTALS:
raidPtr->keep_acc_totals = *(int *)data;
- return (0);
+ return 0;
case RAIDFRAME_GET_SIZE:
*(int *) data = raidPtr->totalSectors;
- return (0);
+ return 0;
- /* fail a disk & optionally start reconstruction */
- case RAIDFRAME_FAIL_DISK80:
- /* Check if we called compat code for this cmd */
- if (retcode != EPASSTHROUGH)
- return EINVAL;
- /* FALLTHRU */
case RAIDFRAME_FAIL_DISK:
- if (raidPtr->Layout.map->faultsTolerated == 0) {
- /* Can't do this on a RAID 0!! */
- return(EINVAL);
- }
-
- rr = (struct rf_recon_req *) data;
- if (rr->col < 0 || rr->col >= raidPtr->numCol)
- return (EINVAL);
-
- rf_lock_mutex2(raidPtr->mutex);
- if (raidPtr->status == rf_rs_reconstructing) {
- /* you can't fail a disk while we're reconstructing! */
- /* XXX wrong for RAID6 */
- rf_unlock_mutex2(raidPtr->mutex);
- return (EINVAL);
- }
- if ((raidPtr->Disks[rr->col].status ==
- rf_ds_optimal) && (raidPtr->numFailures > 0)) {
- /* some other component has failed. Let's not make
- things worse. XXX wrong for RAID6 */
- rf_unlock_mutex2(raidPtr->mutex);
- return (EINVAL);
- }
- if (raidPtr->Disks[rr->col].status == rf_ds_spared) {
- /* Can't fail a spared disk! */
- rf_unlock_mutex2(raidPtr->mutex);
- return (EINVAL);
- }
- rf_unlock_mutex2(raidPtr->mutex);
-
- /* make a copy of the recon request so that we don't rely on
- * the user's buffer */
- RF_Malloc(rrint, sizeof(*rrint), (struct rf_recon_req_internal *));
- if (rrint == NULL)
- return(ENOMEM);
- rrint->col = rr->col;
- rrint->flags = rr->flags;
- rrint->raidPtr = raidPtr;
-
- retcode = RF_CREATE_THREAD(raidPtr->recon_thread,
- rf_ReconThread,
- rrint, "raid_recon");
- return (0);
+ return rf_fail_disk(raidPtr, data);
/* invoke a copyback operation after recon on whatever disk
* needs it, if any */