Module Name:    src
Committed By:   pgoyette
Date:           Sat Dec 26 00:58:45 UTC 2015

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

Log Message:
Modularize the raidframe driver, including rework of the unit attach
code to permit detaching (and possible module unloading).  Also,
convert tsleep()/wakeup() locking to use cv_wait_sig()/cv_broadcast().

Tested in non-modular, modular-builtin, and modular-loaded-at-runtime
environments.


To generate a diff of this commit:
cvs rdiff -u -r1.131 -r1.132 src/sys/dev/raidframe/rf_driver.c
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/raidframe/rf_driver.h
cvs rdiff -u -r1.326 -r1.327 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_driver.c
diff -u src/sys/dev/raidframe/rf_driver.c:1.131 src/sys/dev/raidframe/rf_driver.c:1.132
--- src/sys/dev/raidframe/rf_driver.c:1.131	Mon Dec 10 08:36:03 2012
+++ src/sys/dev/raidframe/rf_driver.c	Sat Dec 26 00:58:45 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: rf_driver.c,v 1.131 2012/12/10 08:36:03 msaitoh Exp $	*/
+/*	$NetBSD: rf_driver.c,v 1.132 2015/12/26 00:58:45 pgoyette 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.131 2012/12/10 08:36:03 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.132 2015/12/26 00:58:45 pgoyette Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_raid_diagnostic.h"
@@ -158,16 +158,21 @@ static void rf_alloc_mutex_cond(RF_Raid_
 
 /* called at system boot time */
 int
-rf_BootRaidframe(void)
+rf_BootRaidframe(bool boot)
 {
 
-	if (raidframe_booted)
-		return (EBUSY);
-	raidframe_booted = 1;
-	rf_init_mutex2(configureMutex, IPL_NONE);
- 	configureCount = 0;
-	isconfigged = 0;
-	globalShutdown = NULL;
+	if (boot) {
+		if (raidframe_booted)
+			return (EBUSY);
+		raidframe_booted = 1;
+		rf_init_mutex2(configureMutex, IPL_NONE);
+ 		configureCount = 0;
+		isconfigged = 0;
+		globalShutdown = NULL;
+	} else {
+		rf_destroy_mutex2(configureMutex);
+		raidframe_booted = 0;
+	}
 	return (0);
 }
 

Index: src/sys/dev/raidframe/rf_driver.h
diff -u src/sys/dev/raidframe/rf_driver.h:1.19 src/sys/dev/raidframe/rf_driver.h:1.20
--- src/sys/dev/raidframe/rf_driver.h:1.19	Sat Apr 30 01:44:36 2011
+++ src/sys/dev/raidframe/rf_driver.h	Sat Dec 26 00:58:45 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: rf_driver.h,v 1.19 2011/04/30 01:44:36 mrg Exp $	*/
+/*	$NetBSD: rf_driver.h,v 1.20 2015/12/26 00:58:45 pgoyette Exp $	*/
 /*
  * rf_driver.h
  */
@@ -42,7 +42,7 @@
 #endif
 
 extern rf_declare_mutex2(rf_printf_mutex);
-int rf_BootRaidframe(void);
+int rf_BootRaidframe(bool);
 int rf_UnbootRaidframe(void);
 int rf_Shutdown(RF_Raid_t *);
 int rf_Configure(RF_Raid_t *, RF_Config_t *, RF_AutoConfig_t *);

Index: src/sys/dev/raidframe/rf_netbsdkintf.c
diff -u src/sys/dev/raidframe/rf_netbsdkintf.c:1.326 src/sys/dev/raidframe/rf_netbsdkintf.c:1.327
--- src/sys/dev/raidframe/rf_netbsdkintf.c:1.326	Tue Dec  8 20:36:15 2015
+++ src/sys/dev/raidframe/rf_netbsdkintf.c	Sat Dec 26 00:58:45 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: rf_netbsdkintf.c,v 1.326 2015/12/08 20:36:15 christos Exp $	*/
+/*	$NetBSD: rf_netbsdkintf.c,v 1.327 2015/12/26 00:58:45 pgoyette 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.326 2015/12/08 20:36:15 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.327 2015/12/26 00:58:45 pgoyette Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -126,6 +126,7 @@ __KERNEL_RCSID(0, "$NetBSD: rf_netbsdkin
 #include <sys/bufq.h>
 #include <sys/reboot.h>
 #include <sys/kauth.h>
+#include <sys/module.h>
 
 #include <prop/proplib.h>
 
@@ -241,6 +242,8 @@ struct raid_softc {
 	int	sc_unit;
 	int     sc_flags;	/* flags */
 	int     sc_cflags;	/* configuration flags */
+	kmutex_t sc_mutex;	/* interlock mutex */
+	kcondvar_t sc_cv;	/* and the condvar */
 	uint64_t sc_size;	/* size of the raid device */
 	char    sc_xname[20];	/* XXX external name */
 	struct disk sc_dkdev;	/* generic disk device info */
@@ -350,17 +353,21 @@ raidcreate(int unit) {
 	}
 	sc->sc_unit = unit;
 	bufq_alloc(&sc->buf_queue, "fcfs", BUFQ_SORT_RAWBLOCK);
+	cv_init(&sc->sc_cv, "raidunit");
+	mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
 	return sc;
 }
 
 static void
 raiddestroy(struct raid_softc *sc) {
+	cv_destroy(&sc->sc_cv);
+	mutex_destroy(&sc->sc_mutex);
 	bufq_free(sc->buf_queue);
 	kmem_free(sc, sizeof(*sc));
 }
 
 static struct raid_softc *
-raidget(int unit) {
+raidget(int unit, bool create) {
 	struct raid_softc *sc;
 	if (unit < 0) {
 #ifdef DIAGNOSTIC
@@ -376,6 +383,8 @@ raidget(int unit) {
 		}
 	}
 	mutex_exit(&raid_lock);
+	if (!create)
+		return NULL;
 	if ((sc = raidcreate(unit)) == NULL)
 		return NULL;
 	mutex_enter(&raid_lock);
@@ -395,34 +404,11 @@ raidput(struct raid_softc *sc) {
 void
 raidattach(int num)
 {
-	mutex_init(&raid_lock, MUTEX_DEFAULT, IPL_NONE);
-	/* This is where all the initialization stuff gets done. */
-
-#if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0)
-	rf_init_mutex2(rf_sparet_wait_mutex, IPL_VM);
-	rf_init_cond2(rf_sparet_wait_cv, "sparetw");
-	rf_init_cond2(rf_sparet_resp_cv, "rfgst");
-
-	rf_sparet_wait_queue = rf_sparet_resp_queue = NULL;
-#endif
-
-	if (rf_BootRaidframe() == 0)
-		aprint_verbose("Kernelized RAIDframe activated\n");
-	else
-		panic("Serious error booting RAID!!");
-
-	if (config_cfattach_attach(raid_cd.cd_name, &raid_ca)) {
-		aprint_error("raidattach: config_cfattach_attach failed?\n");
-	}
-
-	raidautoconfigdone = false;
 
 	/*
-	 * Register a finalizer which will be used to auto-config RAID
-	 * sets once all real hardware devices have been found.
+	 * Device attachment and associated initialization now occurs
+	 * as part of the module initialization.
 	 */
-	if (config_finalize_register(NULL, rf_autoconfig) != 0)
-		aprint_error("WARNING: unable to register RAIDframe finalizer\n");
 }
 
 int
@@ -606,7 +592,7 @@ raidsize(dev_t dev)
 	int     part, unit, omask, size;
 
 	unit = raidunit(dev);
-	if ((rs = raidget(unit)) == NULL)
+	if ((rs = raidget(unit, false)) == NULL)
 		return -1;
 	if ((rs->sc_flags & RAIDF_INITED) == 0)
 		return (-1);
@@ -643,7 +629,7 @@ raiddump(dev_t dev, daddr_t blkno, void 
 	int     part, c, sparecol, j, scol, dumpto;
 	int     error = 0;
 
-	if ((rs = raidget(unit)) == NULL)
+	if ((rs = raidget(unit, false)) == NULL)
 		return ENXIO;
 
 	raidPtr = &rs->sc_r;
@@ -656,7 +642,6 @@ raiddump(dev_t dev, daddr_t blkno, void 
 	    raidPtr->Layout.numParityCol != 1)
 		return EINVAL;
 
-
 	if ((error = raidlock(rs)) != 0)
 		return error;
 
@@ -779,7 +764,7 @@ raidopen(dev_t dev, int flags, int fmt,
 	int     part, pmask;
 	int     error = 0;
 
-	if ((rs = raidget(unit)) == NULL)
+	if ((rs = raidget(unit, true)) == NULL)
 		return ENXIO;
 	if ((error = raidlock(rs)) != 0)
 		return (error);
@@ -863,7 +848,7 @@ raidclose(dev_t dev, int flags, int fmt,
 	int     error = 0;
 	int     part;
 
-	if ((rs = raidget(unit)) == NULL)
+	if ((rs = raidget(unit, false)) == NULL)
 		return ENXIO;
 
 	if ((error = raidlock(rs)) != 0)
@@ -893,15 +878,31 @@ raidclose(dev_t dev, int flags, int fmt,
 
 		rf_update_component_labels(&rs->sc_r,
 						 RF_FINAL_COMPONENT_UPDATE);
-
-		/* If the kernel is shutting down, it will detach
-		 * this RAID set soon enough.
+	}
+	if ((rs->sc_dkdev.dk_openmask == 0) &&
+	    ((rs->sc_flags & RAIDF_SHUTDOWN) != 0)) {
+		/*
+		 * Detach this raid unit
 		 */
+		cfdata_t cf = NULL;
+		int retcode = 0;
+
+		if (rs->sc_dev != NULL) {
+			cf = device_cfdata(rs->sc_dev);
+
+			raidunlock(rs);
+			retcode = config_detach(rs->sc_dev, DETACH_QUIET);
+			if (retcode == 0)
+				/* free the pseudo device attach bits */
+				free(cf, M_RAIDFRAME);
+		} else {
+			raidput(rs);
+		}
+		return retcode;
 	}
 
 	raidunlock(rs);
 	return (0);
-
 }
 
 static void
@@ -912,7 +913,7 @@ raidstrategy(struct buf *bp)
 	int     wlabel;
 	struct raid_softc *rs;
 
-	if ((rs = raidget(unit)) == NULL) {
+	if ((rs = raidget(unit, false)) == NULL) {
 		bp->b_error = ENXIO;
 		goto done;
 	}
@@ -982,7 +983,7 @@ raidread(dev_t dev, struct uio *uio, int
 	int     unit = raidunit(dev);
 	struct raid_softc *rs;
 
-	if ((rs = raidget(unit)) == NULL)
+	if ((rs = raidget(unit, false)) == NULL)
 		return ENXIO;
 
 	if ((rs->sc_flags & RAIDF_INITED) == 0)
@@ -999,7 +1000,7 @@ raidwrite(dev_t dev, struct uio *uio, in
 	int     unit = raidunit(dev);
 	struct raid_softc *rs;
 
-	if ((rs = raidget(unit)) == NULL)
+	if ((rs = raidget(unit, false)) == NULL)
 		return ENXIO;
 
 	if ((rs->sc_flags & RAIDF_INITED) == 0)
@@ -1036,6 +1037,9 @@ raid_detach_unlocked(struct raid_softc *
 	disk_detach(&rs->sc_dkdev);
 	disk_destroy(&rs->sc_dkdev);
 
+	/* Free the softc */
+	raidput(rs);
+
 	aprint_normal_dev(rs->sc_dev, "detached\n");
 
 	return 0;
@@ -1070,7 +1074,7 @@ raidioctl(dev_t dev, u_long cmd, void *d
 	struct disklabel newlabel;
 #endif
 
-	if ((rs = raidget(unit)) == NULL)
+	if ((rs = raidget(unit, false)) == NULL)
 		return ENXIO;
 	raidPtr = &rs->sc_r;
 
@@ -1190,23 +1194,27 @@ raidioctl(dev_t dev, u_long cmd, void *d
 			RF_Free(k_cfg, sizeof(RF_Config_t));
 			db1_printf(("rf_ioctl: retcode=%d copyin.1\n",
 				retcode));
-			return (retcode);
+			goto no_config;
 		}
 		goto config;
 	config:
+		rs->sc_flags &= ~RAIDF_SHUTDOWN;
+
 		/* allocate a buffer for the layout-specific data, and copy it
 		 * in */
 		if (k_cfg->layoutSpecificSize) {
 			if (k_cfg->layoutSpecificSize > 10000) {
 				/* sanity check */
 				RF_Free(k_cfg, sizeof(RF_Config_t));
-				return (EINVAL);
+				retcode = EINVAL;
+				goto no_config;
 			}
 			RF_Malloc(specific_buf, k_cfg->layoutSpecificSize,
 			    (u_char *));
 			if (specific_buf == NULL) {
 				RF_Free(k_cfg, sizeof(RF_Config_t));
-				return (ENOMEM);
+				retcode = ENOMEM;
+				goto no_config;
 			}
 			retcode = copyin(k_cfg->layoutSpecific, specific_buf,
 			    k_cfg->layoutSpecificSize);
@@ -1216,7 +1224,7 @@ raidioctl(dev_t dev, u_long cmd, void *d
 					k_cfg->layoutSpecificSize);
 				db1_printf(("rf_ioctl: retcode=%d copyin.2\n",
 					retcode));
-				return (retcode);
+				goto no_config;
 			}
 		} else
 			specific_buf = NULL;
@@ -1253,6 +1261,13 @@ raidioctl(dev_t dev, u_long cmd, void *d
 		}
 		RF_Free(k_cfg, sizeof(RF_Config_t));
 
+	no_config:
+		/*
+		 * If configuration failed, set sc_flags so that we
+		 * will detach the device when we close it.
+		 */
+		if (retcode != 0)
+			rs->sc_flags |= RAIDF_SHUTDOWN;
 		return (retcode);
 
 		/* shutdown the system */
@@ -2391,7 +2406,7 @@ raidgetdisklabel(dev_t dev)
 	struct cpu_disklabel *clp;
 	RF_Raid_t *raidPtr;
 
-	if ((rs = raidget(unit)) == NULL)
+	if ((rs = raidget(unit, false)) == NULL)
 		return;
 
 	lp = rs->sc_dkdev.dk_label;
@@ -2476,13 +2491,15 @@ raidlock(struct raid_softc *rs)
 {
 	int     error;
 
+	mutex_enter(&rs->sc_mutex);
 	while ((rs->sc_flags & RAIDF_LOCKED) != 0) {
 		rs->sc_flags |= RAIDF_WANTED;
-		if ((error =
-			tsleep(rs, PRIBIO | PCATCH, "raidlck", 0)) != 0)
+		error = cv_wait_sig(&rs->sc_cv, &rs->sc_mutex);
+		if (error != 0)
 			return (error);
 	}
 	rs->sc_flags |= RAIDF_LOCKED;
+	mutex_exit(&rs->sc_mutex);
 	return (0);
 }
 /*
@@ -2492,11 +2509,13 @@ static void
 raidunlock(struct raid_softc *rs)
 {
 
+	mutex_enter(&rs->sc_mutex);
 	rs->sc_flags &= ~RAIDF_LOCKED;
 	if ((rs->sc_flags & RAIDF_WANTED) != 0) {
 		rs->sc_flags &= ~RAIDF_WANTED;
-		wakeup(rs);
+		cv_broadcast(&rs->sc_cv);
 	}
+	mutex_exit(&rs->sc_mutex);
 }
 
 
@@ -3765,7 +3784,7 @@ rf_auto_config_set(RF_ConfigSet_t *cset)
 	/* 1. Create a config structure */
 	config = malloc(sizeof(*config), M_RAIDFRAME, M_NOWAIT|M_ZERO);
 	if (config == NULL) {
-		printf("Out of mem!?!?\n");
+		printf("%s: Out of mem - config!?!?\n", __func__);
 				/* XXX do something more intelligent here. */
 		return NULL;
 	}
@@ -3777,12 +3796,22 @@ rf_auto_config_set(RF_ConfigSet_t *cset)
 	*/
 
 	raidID = cset->ac->clabel->last_unit;
-	for (sc = raidget(raidID); sc->sc_r.valid != 0; sc = raidget(++raidID))
+	for (sc = raidget(raidID, false); sc && sc->sc_r.valid != 0;
+	     sc = raidget(++raidID, false))
 		continue;
 #ifdef DEBUG
 	printf("Configuring raid%d:\n",raidID);
 #endif
 
+	if (sc == NULL)
+		sc = raidget(raidID, true);
+	if (sc == NULL) {
+		printf("%s: Out of mem - softc!?!?\n", __func__);
+				/* XXX do something more intelligent here. */
+		free(config, M_RAIDFRAME);
+		return NULL;
+	}
+
 	raidPtr = &sc->sc_r;
 
 	/* XXX all this stuff should be done SOMEWHERE ELSE! */
@@ -3900,7 +3929,7 @@ static int
 raid_detach(device_t self, int flags)
 {
 	int error;
-	struct raid_softc *rs = raidget(device_unit(self));
+	struct raid_softc *rs = raidget(device_unit(self), false);
 
 	if (rs == NULL)
 		return ENXIO;
@@ -3910,9 +3939,8 @@ raid_detach(device_t self, int flags)
 
 	error = raid_detach_unlocked(rs);
 
-	raidunlock(rs);
-
-	/* XXXkd: raidput(rs) ??? */
+	if (error != 0)
+		raidunlock(rs);
 
 	return error;
 }
@@ -3979,3 +4007,154 @@ rf_sync_component_caches(RF_Raid_t *raid
 	}
 	return error;
 }
+
+/*
+ * Module interface
+ */
+
+MODULE(MODULE_CLASS_DRIVER, raid, "dk_subr");
+
+#ifdef _MODULE
+CFDRIVER_DECL(raid, DV_DISK, NULL);
+#endif
+
+static int raid_modcmd(modcmd_t, void *);
+static int raid_modcmd_init(void);
+static int raid_modcmd_fini(void);
+
+static int
+raid_modcmd(modcmd_t cmd, void *data)
+{
+	int error;
+
+	error = 0;
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		error = raid_modcmd_init();
+		break;
+	case MODULE_CMD_FINI:
+		error = raid_modcmd_fini();
+		break;
+	default:
+		error = ENOTTY;
+		break;
+	}
+	return error;
+}
+
+static int
+raid_modcmd_init(void)
+{
+	int error;
+	int bmajor, cmajor;
+
+	mutex_init(&raid_lock, MUTEX_DEFAULT, IPL_NONE);
+	mutex_enter(&raid_lock);
+#if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0)
+	rf_init_mutex2(rf_sparet_wait_mutex, IPL_VM);
+	rf_init_cond2(rf_sparet_wait_cv, "sparetw");
+	rf_init_cond2(rf_sparet_resp_cv, "rfgst");
+
+	rf_sparet_wait_queue = rf_sparet_resp_queue = NULL;
+#endif
+
+	bmajor = cmajor = -1;
+	error = devsw_attach("raid", &raid_bdevsw, &bmajor,
+	    &raid_cdevsw, &cmajor);
+	if (error != 0 && error != EEXIST) {
+		aprint_error("%s: devsw_attach failed %d\n", __func__, error);
+		mutex_exit(&raid_lock);
+		return error;
+	}
+#ifdef _MODULE
+	error = config_cfdriver_attach(&raid_cd);
+	if (error != 0) {
+		aprint_error("%s: config_cfdriver_attach failed %d\n",
+		    __func__, error);
+		devsw_detach(&raid_bdevsw, &raid_cdevsw);
+		mutex_exit(&raid_lock);
+		return error;
+	}
+#endif
+	error = config_cfattach_attach(raid_cd.cd_name, &raid_ca);
+	if (error != 0) {
+		aprint_error("%s: config_cfattach_attach failed %d\n",
+		    __func__, error);
+#ifdef _MODULE
+		config_cfdriver_detach(&raid_cd);
+#endif
+		devsw_detach(&raid_bdevsw, &raid_cdevsw);
+		mutex_exit(&raid_lock);
+		return error;
+	}
+
+	raidautoconfigdone = false;
+
+	mutex_exit(&raid_lock);
+
+	if (error == 0) {
+		if (rf_BootRaidframe(true) == 0)
+			aprint_verbose("Kernelized RAIDframe activated\n");
+		else
+			panic("Serious error activating RAID!!");
+	}
+
+	/*
+	 * Register a finalizer which will be used to auto-config RAID
+	 * sets once all real hardware devices have been found.
+	 */
+	error = config_finalize_register(NULL, rf_autoconfig);
+	if (error != 0) {
+		aprint_error("WARNING: unable to register RAIDframe "
+		    "finalizer\n");
+	}
+
+	return error;
+}
+
+static int
+raid_modcmd_fini(void)
+{
+	int error;
+
+	mutex_enter(&raid_lock);
+
+	/* Don't allow unload if raid device(s) exist.  */
+	if (!LIST_EMPTY(&raids)) {
+		mutex_exit(&raid_lock);
+		return EBUSY;
+	}
+
+	error = config_cfattach_detach(raid_cd.cd_name, &raid_ca);
+	if (error != 0) {
+		mutex_exit(&raid_lock);
+		return error;
+	}
+#ifdef _MODULE
+	error = config_cfdriver_detach(&raid_cd);
+	if (error != 0) {
+		config_cfattach_attach(raid_cd.cd_name, &raid_ca);
+		mutex_exit(&raid_lock);
+		return error;
+	}
+#endif
+	error = devsw_detach(&raid_bdevsw, &raid_cdevsw);
+	if (error != 0) {
+#ifdef _MODULE
+		config_cfdriver_attach(&raid_cd);
+#endif
+		config_cfattach_attach(raid_cd.cd_name, &raid_ca);
+		mutex_exit(&raid_lock);
+		return error;
+	}
+	rf_BootRaidframe(false);
+#if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0)
+	rf_destroy_mutex2(rf_sparet_wait_mutex);
+	rf_destroy_cond2(rf_sparet_wait_cv);
+	rf_destroy_cond2(rf_sparet_resp_cv);
+#endif
+	mutex_exit(&raid_lock);
+	mutex_destroy(&raid_lock);
+
+	return error;
+}

Reply via email to