diff options
author | Thierry Deval <tdeval@cvs.openbsd.org> | 2001-12-29 21:51:19 +0000 |
---|---|---|
committer | Thierry Deval <tdeval@cvs.openbsd.org> | 2001-12-29 21:51:19 +0000 |
commit | 964e9e640612bb9fc98b99bf2aaf60770ac83eb8 (patch) | |
tree | 18491c777f12628e0ab2cbe6e1d643094487eb9d | |
parent | d9ddae19b8207c9f6b31d3af76064047a9aedce5 (diff) |
Enable the RAIDFrame auto-configuration feature.
This permits one to setup a kernel able to automatically retrieve, during
boot, the raid configuration from disks previously used in a RAIDFrame
set. Moreover, one can define a raid set to contain a bootable partition
that will be mounted on / before the system has started.
A new RAID_AUTOCONFIG kernel option is used, in conjunction with the raid
pseudo-device, to activate the feature.
ok drahn@, deraadt@
-rw-r--r-- | sys/dev/raidframe/rf_engine.c | 127 | ||||
-rw-r--r-- | sys/dev/raidframe/rf_kintf.h | 5 | ||||
-rw-r--r-- | sys/dev/raidframe/rf_openbsdkintf.c | 416 | ||||
-rw-r--r-- | sys/dev/raidframe/rf_states.c | 13 |
4 files changed, 449 insertions, 112 deletions
diff --git a/sys/dev/raidframe/rf_engine.c b/sys/dev/raidframe/rf_engine.c index 5482dd5bac5..9c641334c1c 100644 --- a/sys/dev/raidframe/rf_engine.c +++ b/sys/dev/raidframe/rf_engine.c @@ -1,5 +1,5 @@ -/* $OpenBSD: rf_engine.c,v 1.6 2001/09/20 17:02:31 mpech Exp $ */ -/* $NetBSD: rf_engine.c,v 1.9 2000/01/08 22:57:31 oster Exp $ */ +/* $OpenBSD: rf_engine.c,v 1.7 2001/12/29 21:51:18 tdeval Exp $ */ +/* $NetBSD: rf_engine.c,v 1.10 2000/08/20 16:51:03 thorpej Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. @@ -67,7 +67,14 @@ #include "rf_shutdown.h" #include "rf_raid.h" -static void DAGExecutionThread(RF_ThreadArg_t arg); +#ifdef RAID_AUTOCONFIG +#define RF_ENGINE_PID 10 +extern int numraid; +extern pid_t lastpid; +static void **rf_startuphook_cookie; +void DAGExecutionThread_pre(RF_ThreadArg_t arg); +#endif /* RAID_AUTOCONFIG */ +void DAGExecutionThread(RF_ThreadArg_t arg); #define DO_INIT(_l_,_r_) { \ int _rc; \ @@ -86,14 +93,28 @@ static void DAGExecutionThread(RF_ThreadArg_t arg); /* * XXX Is this spl-ing really necessary? */ -#define DO_LOCK(_r_) { ks = splbio(); RF_LOCK_MUTEX((_r_)->node_queue_mutex); } -#define DO_UNLOCK(_r_) { RF_UNLOCK_MUTEX((_r_)->node_queue_mutex); splx(ks); } -#define DO_WAIT(_r_) tsleep(&(_r_)->node_queue, PRIBIO, "raidframe nq",0) -#define DO_SIGNAL(_r_) wakeup(&(_r_)->node_queue) +#define DO_LOCK(_r_) \ +do { \ + ks = splbio(); \ + RF_LOCK_MUTEX((_r_)->node_queue_mutex); \ +} while (0) -static void rf_ShutdownEngine(void *); +#define DO_UNLOCK(_r_) \ +do { \ + RF_UNLOCK_MUTEX((_r_)->node_queue_mutex); \ + splx(ks); \ +} while (0) -static void +#define DO_WAIT(_r_) \ + RF_WAIT_COND((_r_)->node_queue, (_r_)->node_queue_mutex) + +/* XXX RF_SIGNAL_COND? */ +#define DO_SIGNAL(_r_) \ + RF_BROADCAST_COND((_r_)->node_queue) + +void rf_ShutdownEngine(void *); + +void rf_ShutdownEngine(arg) void *arg; { @@ -111,6 +132,7 @@ rf_ConfigureEngine( RF_Config_t * cfgPtr) { int rc; + char raidname[16]; DO_INIT(listp, raidPtr); @@ -127,21 +149,37 @@ rf_ConfigureEngine( if (rf_engineDebug) { printf("raid%d: Creating engine thread\n", raidPtr->raidid); } - if (RF_CREATE_THREAD(raidPtr->engine_thread, DAGExecutionThread, raidPtr,"raid")) { - RF_ERRORMSG("RAIDFRAME: Unable to create engine thread\n"); - return (ENOMEM); - } - if (rf_engineDebug) { - printf("raid%d: Created engine thread\n", raidPtr->raidid); +#ifdef RAID_AUTOCONFIG + if (initproc == NULL) { + if (rf_startuphook_cookie == NULL) { + rf_startuphook_cookie = + malloc(numraid * sizeof(void*), + M_RAIDFRAME, M_NOWAIT); + if (rf_startuphook_cookie == NULL) + return (ENOMEM); + bzero(rf_startuphook_cookie, numraid * sizeof(void*)); + } + rf_startuphook_cookie[raidPtr->raidid] = + startuphook_establish(DAGExecutionThread_pre, raidPtr); + } else { +#endif /* RAID_AUTOCONFIG */ + snprintf(&raidname[0], 16, "raid%d", raidPtr->raidid); + if (RF_CREATE_THREAD(raidPtr->engine_thread, + DAGExecutionThread, raidPtr, &raidname[0])) { + RF_ERRORMSG("RAIDFRAME: Unable to create engine thread\n"); + return (ENOMEM); + } + if (rf_engineDebug) { + printf("raid%d: Created engine thread\n", raidPtr->raidid); + } + RF_THREADGROUP_STARTED(&raidPtr->engine_tg); +#ifdef RAID_AUTOCONFIG } - RF_THREADGROUP_STARTED(&raidPtr->engine_tg); +#endif /* XXX something is missing here... */ #ifdef debug printf("Skipping the WAIT_START!!\n"); #endif -#if 0 - RF_THREADGROUP_WAIT_START(&raidPtr->engine_tg); -#endif /* engine thread is now running and waiting for work */ if (rf_engineDebug) { printf("raid%d: Engine thread running and waiting for events\n", raidPtr->raidid); @@ -267,7 +305,7 @@ FireNode(RF_DagNode_t * node) node->dagHdr->raidPtr->raidid, (unsigned long) node, node->name); } - if (node->flags & RF_DAGNODE_FLAG_YIELD) + if (node->flags & RF_DAGNODE_FLAG_YIELD) { #if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(_KERNEL) /* thread_block(); */ /* printf("Need to block the thread here...\n"); */ @@ -276,6 +314,7 @@ FireNode(RF_DagNode_t * node) #else thread_block(); #endif + } (*(node->undoFunc)) (node); break; default: @@ -704,7 +743,49 @@ rf_DispatchDAG( * characteristics from the aio_completion_thread. */ -static void +#ifdef RAID_AUTOCONFIG +void +DAGExecutionThread_pre(RF_ThreadArg_t arg) +{ + RF_Raid_t *raidPtr; + char raidname[16]; + int len; + pid_t oldpid = lastpid; + + raidPtr = (RF_Raid_t *) arg; + + if (rf_startuphook_cookie && rf_startuphook_cookie[raidPtr->raidid]) + startuphook_disestablish(rf_startuphook_cookie[raidPtr->raidid]); + + if (rf_engineDebug) { + printf("raid%d: Creating engine thread\n", raidPtr->raidid); + } + lastpid = -2; + + len = sprintf(&raidname[0], "raid%d", raidPtr->raidid); +#ifdef DIAGNOSTIC + if (len >= sizeof(raidname)) + panic("raidname expansion too long."); +#endif /* DIAGNOSTIC */ + + if (RF_CREATE_THREAD(raidPtr->engine_thread, DAGExecutionThread, + raidPtr, &raidname[0])) { + RF_ERRORMSG("RAIDFRAME: Unable to create engine thread\n"); + return; + } + LIST_REMOVE(raidPtr->engine_thread, p_hash); + raidPtr->engine_thread->p_pid = RF_ENGINE_PID + raidPtr->raidid; + LIST_INSERT_HEAD(PIDHASH(RF_ENGINE_PID + raidPtr->raidid), + raidPtr->engine_thread, p_hash); + lastpid = oldpid; + if (rf_engineDebug) { + printf("raid%d: Created engine thread\n", raidPtr->raidid); + } + RF_THREADGROUP_STARTED(&raidPtr->engine_tg); +} +#endif /* RAID_AUTOCONFIG */ + +void DAGExecutionThread(RF_ThreadArg_t arg) { RF_DagNode_t *nd, *local_nq, *term_nq, *fire_nq; @@ -714,6 +795,10 @@ DAGExecutionThread(RF_ThreadArg_t arg) raidPtr = (RF_Raid_t *) arg; + while (!(&raidPtr->engine_tg)->created) + (void) tsleep((void*)&(&raidPtr->engine_tg)->created, PWAIT, + "raidinit", 0); + if (rf_engineDebug) { printf("raid%d: Engine thread is running\n", raidPtr->raidid); } diff --git a/sys/dev/raidframe/rf_kintf.h b/sys/dev/raidframe/rf_kintf.h index 65e5c88c07a..9b71fea32dc 100644 --- a/sys/dev/raidframe/rf_kintf.h +++ b/sys/dev/raidframe/rf_kintf.h @@ -1,5 +1,5 @@ -/* $OpenBSD: rf_kintf.h,v 1.6 2000/08/08 16:07:41 peter Exp $ */ -/* $NetBSD: rf_kintf.h,v 1.14 2000/06/04 02:05:13 oster Exp $ */ +/* $OpenBSD: rf_kintf.h,v 1.7 2001/12/29 21:51:18 tdeval Exp $ */ +/* $NetBSD: rf_kintf.h,v 1.15 2000/10/20 02:24:45 oster Exp $ */ /* * rf_kintf.h * @@ -54,4 +54,5 @@ void raid_init_component_label(RF_Raid_t *, RF_ComponentLabel_t *); void rf_print_component_label(RF_ComponentLabel_t *); void rf_UnconfigureVnodes( RF_Raid_t * ); void rf_close_component( RF_Raid_t *, struct vnode *, int); +void rf_disk_unbusy(RF_RaidAccessDesc_t *); #endif /* _RF__RF_KINTF_H_ */ diff --git a/sys/dev/raidframe/rf_openbsdkintf.c b/sys/dev/raidframe/rf_openbsdkintf.c index 8889dc70e96..b1f536952b0 100644 --- a/sys/dev/raidframe/rf_openbsdkintf.c +++ b/sys/dev/raidframe/rf_openbsdkintf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: rf_openbsdkintf.c,v 1.11 2001/12/08 22:10:01 tdeval Exp $ */ -/* $NetBSD: rf_netbsdkintf.c,v 1.93 2000/07/14 15:26:29 oster Exp $ */ +/* $OpenBSD: rf_openbsdkintf.c,v 1.12 2001/12/29 21:51:18 tdeval Exp $ */ +/* $NetBSD: rf_netbsdkintf.c,v 1.109 2001/07/27 03:30:07 oster Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. @@ -117,6 +117,7 @@ #include <sys/errno.h> #include <sys/param.h> +#include <sys/pool.h> #include <sys/malloc.h> #include <sys/queue.h> #include <sys/disk.h> @@ -138,6 +139,7 @@ #include "rf_copyback.h" #include "rf_dag.h" #include "rf_dagflags.h" +#include "rf_desc.h" #include "rf_diskqueue.h" #include "rf_acctrace.h" #include "rf_etimer.h" @@ -174,7 +176,7 @@ void rf_KernelWakeupFunc __P((struct buf *)); void rf_InitBP __P((struct buf *, struct vnode *, unsigned, dev_t, RF_SectorNum_t, RF_SectorCount_t, caddr_t, void (*)(struct buf *), void *, int, struct proc *)); -static void raidinit __P((RF_Raid_t *)); +void raidinit __P((RF_Raid_t *)); void raidattach __P((int)); int raidsize __P((dev_t)); @@ -196,8 +198,8 @@ struct raidbuf { RF_DiskQueueData_t *req;/* the request that this was part of.. */ }; -#define RAIDGETBUF() malloc(sizeof (struct raidbuf), M_RAIDFRAME, M_NOWAIT) -#define RAIDPUTBUF(buf) free(buf, M_RAIDFRAME) +#define RAIDGETBUF(rs) pool_get(&(rs)->sc_cbufpool, PR_NOWAIT) +#define RAIDPUTBUF(rs, cbp) pool_put(&(rs)->sc_cbufpool, cbp) /* * Some port (like i386) use a swapgeneric that wants to snoop around @@ -218,6 +220,7 @@ struct raid_softc { size_t sc_size; /* size of the raid device */ char sc_xname[20]; /* XXX external name */ struct disk sc_dkdev; /* generic disk device info */ + struct pool sc_cbufpool; /* component buffer pool */ struct buf sc_q; /* used for the device queue */ }; @@ -232,6 +235,22 @@ struct raid_softc { int numraid = 0; /* + * Here we define a cfattach structure for inserting any new raid device + * into the device tree. This is needed by some archs that look for + * bootable devices in there. + */ +int rf_probe __P((struct device *, void *, void *)); +void rf_attach __P((struct device *, struct device *, void *)); +int rf_detach __P((struct device *, int)); +int rf_activate __P((struct device *, enum devact)); +void rf_zeroref __P((struct device *)); + +struct cfattach raid_ca = { + sizeof(struct raid_softc), rf_probe, rf_attach, + rf_detach, rf_activate, rf_zeroref +}; + +/* * Allow RAIDOUTSTANDING number of simultaneous IO's to this RAID device. * Be aware that large numbers can allow the driver to consume a lot of * kernel memory, especially on writes, and in degraded mode reads. @@ -257,6 +276,7 @@ int numraid = 0; /* declared here, and made public, for the benefit of KVM stuff.. */ struct raid_softc *raid_softc; +struct raid_softc **raid_scPtrs; void raidgetdefaultlabel __P((RF_Raid_t *, struct raid_softc *, struct disklabel *)); @@ -271,6 +291,9 @@ void rf_mountroot_hook __P((struct device *)); struct device *raidrootdev; +int findblkmajor __P((struct device *dv)); +char *findblkname __P((int)); + void rf_ReconThread __P((struct rf_recon_req *)); /* XXX what I want is: */ /*void rf_ReconThread __P((RF_Raid_t *raidPtr)); */ @@ -279,12 +302,12 @@ void rf_CopybackThread __P((RF_Raid_t *raidPtr)); void rf_ReconstructInPlaceThread __P((struct rf_recon_req *)); #ifdef RAID_AUTOCONFIG void rf_buildroothack __P((void *)); -static int rf_reasonable_label __P((RF_ComponentLabel_t *)); +int rf_reasonable_label __P((RF_ComponentLabel_t *)); #endif RF_AutoConfig_t *rf_find_raid_components __P((void)); RF_ConfigSet_t *rf_create_auto_sets __P((RF_AutoConfig_t *)); -static int rf_does_it_fit __P((RF_ConfigSet_t *,RF_AutoConfig_t *)); +int rf_does_it_fit __P((RF_ConfigSet_t *,RF_AutoConfig_t *)); void rf_create_configuration __P((RF_AutoConfig_t *,RF_Config_t *, RF_Raid_t *)); int rf_set_autoconfig __P((RF_Raid_t *, int)); @@ -302,6 +325,45 @@ static int raidautoconfig = 0; /* Debugging, mostly. Set to 0 to not kernel config file. */ #endif +int +rf_probe(parent, match_, aux) + struct device *parent; + void *match_; + void *aux; +{ + return 0; +} + +void +rf_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + /* struct raid_softc *raid = (void *)self; */ +} + +int +rf_detach(self, flags) + struct device *self; + int flags; +{ + return 0; +} + +int +rf_activate(self, act) + struct device *self; + enum devact act; +{ + return 0; +} + +void +rf_zeroref(self) + struct device *self; +{ +} + void raidattach(num) int num; @@ -362,6 +424,16 @@ raidattach(num) bzero(raid_softc, num * sizeof (struct raid_softc)); + raid_scPtrs = (struct raid_softc **) + malloc(num * sizeof(struct raid_softc *), + M_RAIDFRAME, M_NOWAIT); + if (raid_scPtrs == NULL) { + printf("WARNING: no memory for RAIDframe driver\n"); + return; + } + + bzero(raid_scPtrs, num * sizeof (struct raid_softc *)); + raidrootdev = (struct device *)malloc(num * sizeof(struct device), M_RAIDFRAME, M_NOWAIT); if (raidrootdev == NULL) { @@ -389,13 +461,16 @@ raidattach(num) } } -#if RAID_AUTOCONFIG + raid_cd.cd_devs = (void **) raid_scPtrs; + raid_cd.cd_ndevs = num; + +#ifdef RAID_AUTOCONFIG raidautoconfig = 1; if (raidautoconfig) { /* 1. locate all RAID components on the system */ -#if DEBUG +#ifdef DEBUG printf("Searching for raid components...\n"); #endif ac_list = rf_find_raid_components(); @@ -410,7 +485,7 @@ if (raidautoconfig) { /* schedule the creation of the thread to do the "/ on RAID" stuff */ - kthread_create(rf_buildroothack, config_sets, NULL, "raidauto"); + rf_buildroothack(config_sets); #if 0 mountroothook_establish(rf_mountroot_hook, &raidrootdev[0]); @@ -432,7 +507,9 @@ rf_buildroothack(arg) int raidID; int rootID; int num_root; + int majdev; + rootID = 0; num_root = 0; cset = config_sets; while(cset != NULL ) { @@ -443,11 +520,14 @@ rf_buildroothack(arg) if (!retcode) { if (cset->rootable) { rootID = raidID; +#ifdef DEBUG + printf("eligible root device %d: raid%d\n", num_root, rootID); +#endif /* DEBUG */ num_root++; } } else { /* The autoconfig didn't work :( */ -#if DEBUG +#ifdef DEBUG printf("Autoconfig failed with code %d for raid%d\n", retcode, raidID); #endif rf_release_all_vps(cset); @@ -467,7 +547,13 @@ rf_buildroothack(arg) /* They didn't ask, and we found something bootable... */ if (num_root == 1) { - booted_device = &raidrootdev[rootID]; + majdev = findblkmajor(&raidrootdev[rootID]); + if (majdev < 0) + boothowto |= RB_ASKNAME; + else { + rootdev = MAKEDISKDEV(majdev,rootID,0); + boothowto |= RB_DFLTROOT; + } } else if (num_root > 1) { /* we can't guess.. require the user to answer... */ boothowto |= RB_ASKNAME; @@ -645,6 +731,24 @@ raidclose(dev, flags, fmt, p) #endif rf_update_component_labels(raidPtrs[unit], RF_FINAL_COMPONENT_UPDATE); +#if 0 + if (doing_shutdown) { +/* #endif */ + /* last one, and we're going down, so + lights out for this RAID set too. */ + error = rf_Shutdown(raidPtrs[unit]); + pool_destroy(&rs->sc_cbufpool); + + /* It's no longer initialized... */ + rs->sc_flags &= ~RAIDF_INITED; + + /* config_detach the device. */ + config_detach(device_lookup(&raid_cd, unit), 0); + + disk_detach(&rs->sc_dkdev); +/* #if 0 */ + } +#endif } raidunlock(rs); @@ -665,7 +769,7 @@ raidstrategy(bp) if ((rs->sc_flags & RAIDF_INITED) ==0) { bp->b_error = ENXIO; - bp->b_flags = B_ERROR; + bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; biodone(bp); return; @@ -961,9 +1065,14 @@ raidioctl(dev, cmd, data, flag, p) retcode = rf_Shutdown(raidPtr); + pool_destroy(&rs->sc_cbufpool); + /* It's no longer initialized... */ rs->sc_flags &= ~RAIDF_INITED; + /* config_detach the device. */ + config_detach(device_lookup(&raid_cd, unit), 0); + /* Detach the disk. */ disk_detach(&rs->sc_dkdev); @@ -1068,12 +1177,15 @@ raidioctl(dev, cmd, data, flag, p) ci_label.row = row; for(column=0;column<raidPtr->numCol;column++) { diskPtr = &raidPtr->Disks[row][column]; - ci_label.partitionSize = diskPtr->partitionSize; - ci_label.column = column; - raidwrite_component_label( - raidPtr->Disks[row][column].dev, - raidPtr->raid_cinfo[row][column].ci_vp, - &ci_label ); + if (!RF_DEAD_DISK(diskPtr->status)) { + ci_label.partitionSize = + diskPtr->partitionSize; + ci_label.column = column; + raidwrite_component_label( + raidPtr->Disks[row][column].dev, + raidPtr->raid_cinfo[row][column].ci_vp, + &ci_label ); + } } } @@ -1098,6 +1210,7 @@ raidioctl(dev, cmd, data, flag, p) raidPtr,"raid_parity"); return (retcode); + case RAIDFRAME_SET_AUTOCONFIG: d = rf_set_autoconfig(raidPtr, *(int *) data); printf("New autoconfig value is: %d\n", d); @@ -1212,6 +1325,7 @@ raidioctl(dev, cmd, data, flag, p) case RAIDFRAME_CHECK_PARITY: *(int *) data = raidPtr->parity_good; return (0); + case RAIDFRAME_RESET_ACCTOTALS: bzero(&raidPtr->acc_totals, sizeof(raidPtr->acc_totals)); return (0); @@ -1229,7 +1343,7 @@ raidioctl(dev, cmd, data, flag, p) *(int *) data = raidPtr->totalSectors; return (0); - /* fail a disk & optionally start reconstruction */ + /* fail a disk & optionally start reconstruction */ case RAIDFRAME_FAIL_DISK: rr = (struct rf_recon_req *)data; @@ -1255,10 +1369,10 @@ raidioctl(dev, cmd, data, flag, p) rrcopy,"raid_recon"); return (0); - /* - * Invoke a copyback operation after recon on whatever - * disk needs it, if any. - */ + /* + * Invoke a copyback operation after recon on whatever + * disk needs it, if any. + */ case RAIDFRAME_COPYBACK: if (raidPtr->Layout.map->faultsTolerated == 0) { /* This makes no sense on a RAID 0!! */ @@ -1274,8 +1388,8 @@ raidioctl(dev, cmd, data, flag, p) rf_CopybackThread, raidPtr,"raid_copyback"); return (retcode); - - /* Return the percentage completion of reconstruction */ + + /* Return the percentage completion of reconstruction */ case RAIDFRAME_CHECK_RECON_STATUS: if (raidPtr->Layout.map->faultsTolerated == 0) { /* This makes no sense on a RAID 0, so tell the @@ -1352,7 +1466,8 @@ raidioctl(dev, cmd, data, flag, p) return(0); } if (raidPtr->copyback_in_progress == 1) { - *(int *) data = 100 * raidPtr->copyback_stripes_done / raidPtr->Layout.numStripe; + *(int *) data = 100 * raidPtr->copyback_stripes_done / + raidPtr->Layout.numStripe; } else { *(int *) data = 100; } @@ -1441,8 +1556,8 @@ raidioctl(dev, cmd, data, flag, p) return (retcode); #endif + /* fall through to the os-specific code below */ default: - /* fall through to the os-specific code below */ break; } @@ -1465,13 +1580,17 @@ raidioctl(dev, cmd, data, flag, p) case DIOCWDINFO: case DIOCSDINFO: + { + struct disklabel *lp; + lp = (struct disklabel *)data; + if ((error = raidlock(rs)) != 0) return (error); rs->sc_flags |= RAIDF_LABELLING; error = setdisklabel(rs->sc_dkdev.dk_label, - (struct disklabel *)data, 0, rs->sc_dkdev.dk_cpulabel); + lp, 0, rs->sc_dkdev.dk_cpulabel); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(RAIDLABELDEV(dev), @@ -1486,6 +1605,7 @@ raidioctl(dev, cmd, data, flag, p) if (error) return (error); break; + } case DIOCWLABEL: if (*(int *)data != 0) @@ -1494,18 +1614,14 @@ raidioctl(dev, cmd, data, flag, p) rs->sc_flags &= ~RAIDF_WLABEL; break; -#if 0 - case DIOCGDEFLABEL: -#endif case DIOCGPDINFO: - raidgetdefaultlabel(raidPtr, rs, - (struct disklabel *) data); + raidgetdefaultlabel(raidPtr, rs, (struct disklabel *) data); break; - default: retcode = ENOTTY; } + return (retcode); } @@ -1513,16 +1629,20 @@ raidioctl(dev, cmd, data, flag, p) * raidinit -- complete the rest of the initialization for the * RAIDframe device. */ -static void +void raidinit(raidPtr) RF_Raid_t *raidPtr; { struct raid_softc *rs; - int unit; + struct cfdata *cf; + int unit; unit = raidPtr->raidid; rs = &raid_softc[unit]; + pool_init(&rs->sc_cbufpool, sizeof(struct raidbuf), 0, + 0, 0, "raidpl", 0, NULL, NULL, M_RAIDFRAME); + /* XXX should check return code first... */ rs->sc_flags |= RAIDF_INITED; @@ -1544,6 +1664,24 @@ raidinit(raidPtr) * protectedSectors, as used in RAIDframe. */ rs->sc_size = raidPtr->totalSectors; + + /* + * config_attach the raid device into the device tree. + * For autoconf rootdev selection... + */ + cf = malloc(sizeof(struct cfdata), M_RAIDFRAME, M_NOWAIT); + if (cf == NULL) { + printf("WARNING: no memory for cfdata struct\n"); + return; + } + bzero(cf, sizeof(struct cfdata)); + + cf->cf_attach = &raid_ca; + cf->cf_driver = &raid_cd; + cf->cf_unit = unit; + + config_attach(NULL, cf, NULL, NULL); + printf("\n"); /* pretty up config_attach()'s output. */ } /* @@ -1691,11 +1829,13 @@ raidstart(raidPtr) */ do_async = 1; - /* don't ever condition on bp->b_flags & B_WRITE. - * always condition on B_READ instead */ + disk_busy(&rs->sc_dkdev); /* XXX we're still at splbio() here... do we *really* - need to be? */ + * need to be? */ + + /* don't ever condition on bp->b_flags & B_WRITE. + * always condition on B_READ instead */ retcode = rf_DoAccess(raidPtr, (bp->b_flags & B_READ) ? RF_IO_TYPE_READ : RF_IO_TYPE_WRITE, @@ -1742,9 +1882,6 @@ rf_DispatchKernelIO(queue, req) rs = &raid_softc[unit]; - /* XXX is this the right place? */ - disk_busy(&rs->sc_dkdev); - bp = req->bp; #if 1 @@ -1763,7 +1900,7 @@ rf_DispatchKernelIO(queue, req) } #endif - raidbp = RAIDGETBUF(); + raidbp = RAIDGETBUF(rs); raidbp->rf_flags = 0; /* XXX not really used anywhere... */ @@ -1917,12 +2054,7 @@ rf_KernelWakeupFunc(vbp) } rs = &raid_softc[unit]; - RAIDPUTBUF(raidbp); - - if (bp->b_resid==0) { - /* XXX is this the right place for a disk_unbusy()??!??!?!? */ - disk_unbusy(&rs->sc_dkdev, (bp->b_bcount - bp->b_resid)); - } + RAIDPUTBUF(rs, raidbp); rf_DiskIOComplete(queue, req, (bp->b_flags & B_ERROR) ? 1 : 0); (req->CompleteFunc)(req->argument, (bp->b_flags & B_ERROR) ? 1 : 0); @@ -1979,7 +2111,7 @@ raidgetdefaultlabel(raidPtr, rs, lp) lp->d_secperunit = raidPtr->totalSectors; lp->d_secsize = raidPtr->bytesPerSector; lp->d_nsectors = raidPtr->Layout.dataSectorsPerStripe; - lp->d_ntracks = 1; + lp->d_ntracks = 4 * raidPtr->numCol; lp->d_ncylinders = raidPtr->totalSectors / (lp->d_nsectors * lp->d_ntracks); lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; @@ -2204,6 +2336,12 @@ raidread_component_label(dev, b_vp, clabel) /* XXX should probably ensure that we don't try to do this if someone has changed rf_protected_sectors. */ + if (b_vp == NULL) { + /* For whatever reason, this component is not valid. + Don't try to read a component label from it. */ + return(EINVAL); + } + /* get a block of the appropriate size... */ bp = geteblk((int)RF_COMPONENT_INFO_SIZE); bp->b_dev = dev; @@ -2211,7 +2349,7 @@ raidread_component_label(dev, b_vp, clabel) /* get our ducks in a row for the read */ bp->b_blkno = RF_COMPONENT_INFO_OFFSET / DEV_BSIZE; bp->b_bcount = RF_COMPONENT_INFO_SIZE; - bp->b_flags = B_BUSY | B_READ; + bp->b_flags |= B_READ; bp->b_resid = RF_COMPONENT_INFO_SIZE / DEV_BSIZE; (*bdevsw[major(bp->b_dev)].d_strategy)(bp); @@ -2230,7 +2368,6 @@ raidread_component_label(dev, b_vp, clabel) #endif } - bp->b_flags = B_INVAL | B_AGE; brelse(bp); return(error); } @@ -2251,7 +2388,7 @@ raidwrite_component_label(dev, b_vp, clabel) /* get our ducks in a row for the write */ bp->b_blkno = RF_COMPONENT_INFO_OFFSET / DEV_BSIZE; bp->b_bcount = RF_COMPONENT_INFO_SIZE; - bp->b_flags = B_BUSY | B_WRITE; + bp->b_flags |= B_WRITE; bp->b_resid = RF_COMPONENT_INFO_SIZE / DEV_BSIZE; memset(bp->b_data, 0, RF_COMPONENT_INFO_SIZE ); @@ -2260,7 +2397,6 @@ raidwrite_component_label(dev, b_vp, clabel) (*bdevsw[major(bp->b_dev)].d_strategy)(bp); error = biowait(bp); - bp->b_flags = B_INVAL | B_AGE; brelse(bp); if (error) { #if 1 @@ -2281,7 +2417,9 @@ rf_markalldirty(raidPtr) raidPtr->mod_counter++; for (r = 0; r < raidPtr->numRow; r++) { for (c = 0; c < raidPtr->numCol; c++) { - if (raidPtr->Disks[r][c].status != rf_ds_failed) { + /* we don't want to touch (at all) a disk that has + failed */ + if (!RF_DEAD_DISK(raidPtr->Disks[r][c].status)) { raidread_component_label( raidPtr->Disks[r][c].dev, raidPtr->raid_cinfo[r][c].ci_vp, @@ -2478,12 +2616,13 @@ rf_close_component(raidPtr, vp, auto_configured) { struct proc *p; - p = raidPtr->engine_thread; + if ((p = raidPtr->engine_thread) == NULL) + p = curproc; if (vp != NULL) { if (auto_configured == 1) { - VOP_CLOSE(vp, FREAD, NOCRED, 0); - vput(vp); + VOP_CLOSE(vp, FREAD | FWRITE, NOCRED, 0); + vrele(vp); } else { VOP_UNLOCK(vp, 0, p); @@ -2500,15 +2639,12 @@ rf_UnconfigureVnodes(raidPtr) RF_Raid_t *raidPtr; { int r,c; - struct proc *p; struct vnode *vp; int acd; /* We take this opportunity to close the vnodes like we should.. */ - p = raidPtr->engine_thread; - for (r = 0; r < raidPtr->numRow; r++) { for (c = 0; c < raidPtr->numCol; c++) { printf("Closing vnode for row: %d col: %d\n", r, c); @@ -2634,11 +2770,10 @@ RF_AutoConfig_t * rf_find_raid_components() { #ifdef RAID_AUTOCONFIG - struct devnametobdevmaj *dtobdm; + int major; struct vnode *vp; struct disklabel label; struct device *dv; - char *cd_name; dev_t dev; int error; int i; @@ -2652,9 +2787,7 @@ rf_find_raid_components() /* initialize the AutoConfig list */ ac_list = NULL; -#if RAID_AUTOCONFIG -if (raidautoconfig) { - +#ifdef RAID_AUTOCONFIG /* we begin by trolling through *all* the devices on the system */ for (dv = alldevs.tqh_first; dv != NULL; @@ -2670,15 +2803,11 @@ if (raidautoconfig) { } /* need to find the device_name_to_block_device_major stuff */ - cd_name = dv->dv_cfdata->cf_driver->cd_name; - dtobdm = dev_name2blk; - while (dtobdm->d_name && strcmp(dtobdm->d_name, cd_name)) { - dtobdm++; - } + major = findblkmajor(dv); /* get a vnode for the raw partition of this disk */ - dev = MAKEDISKDEV(dtobdm->d_maj, dv->dv_unit, RAW_PART); + dev = MAKEDISKDEV(major, dv->dv_unit, RAW_PART); if (bdevvp(dev, &vp)) panic("RAID can't alloc vnode"); @@ -2705,15 +2834,24 @@ if (raidautoconfig) { /* don't need this any more. We'll allocate it again a little later if we really do... */ - VOP_CLOSE(vp, FREAD, NOCRED, 0); - vput(vp); + VOP_CLOSE(vp, FREAD | FWRITE, NOCRED, 0); + vrele(vp); for (i=0; i < label.d_npartitions; i++) { - /* We only support partitions marked as RAID */ + /* We only support partitions marked as RAID. */ + /* Aside on sparc/sparc64 where FS_RAID doesn't */ + /* fit in the SUN disklabel and we need to look */ + /* into each and every partition !!! */ +#if !defined(__sparc__) && !defined(__sparc64__) && !defined(__sun3__) if (label.d_partitions[i].p_fstype != FS_RAID) continue; +#else /* !__sparc__ && !__sparc64__ && !__sun3__ */ + if (label.d_partitions[i].p_fstype == FS_SWAP || + label.d_partitions[i].p_fstype == FS_UNUSED) + continue; +#endif /* __sparc__ || __sparc64__ || __sun3__ */ - dev = MAKEDISKDEV(dtobdm->d_maj, dv->dv_unit, i); + dev = MAKEDISKDEV(major, dv->dv_unit, i); if (bdevvp(dev, &vp)) panic("RAID can't alloc vnode"); @@ -2740,7 +2878,7 @@ if (raidautoconfig) { if (rf_reasonable_label(clabel) && (clabel->partitionSize <= label.d_partitions[i].p_size)) { -#if DEBUG +#ifdef DEBUG printf("Component on: %s%c: %d\n", dv->dv_xname, 'a'+i, label.d_partitions[i].p_size); @@ -2770,18 +2908,17 @@ if (raidautoconfig) { if (!good_one) { /* cleanup */ free(clabel, M_RAIDFRAME); - VOP_CLOSE(vp, FREAD, NOCRED, 0); - vput(vp); + VOP_CLOSE(vp, FREAD | FWRITE, NOCRED, 0); + vrele(vp); } } } -} #endif return(ac_list); } #ifdef RAID_AUTOCONFIG -static int +int rf_reasonable_label(clabel) RF_ComponentLabel_t *clabel; { @@ -2899,7 +3036,7 @@ rf_create_auto_sets(ac_list) return(config_sets); } -static int +int rf_does_it_fit(cset, ac) RF_ConfigSet_t *cset; RF_AutoConfig_t *ac; @@ -2987,6 +3124,7 @@ rf_have_enough_components(cset) /* Determine what the mod_counter is supposed to be for this set. */ mod_counter_found = 0; + mod_counter = 0; ac = cset->ac; while(ac!=NULL) { if (mod_counter_found==0) { @@ -3012,7 +3150,7 @@ rf_have_enough_components(cset) (ac->clabel->column == c) && (ac->clabel->mod_counter == mod_counter)) { /* it's this one... */ -#if DEBUG +#ifdef DEBUG printf("Found: %s at %d,%d\n", ac->devname,r,c); #endif @@ -3101,6 +3239,101 @@ rf_create_configuration(ac,config,raidPtr) for(i=0;i<RF_MAXDBGV;i++) { config->debugVars[i][0] = NULL; } + +#ifdef RAID_DEBUG_ALL +#ifdef RF_DBG_OPTION +#undef RF_DBG_OPTION +#endif + +#ifdef __STDC__ +#define RF_DBG_OPTION(_option_,_val_) \ + snprintf(&(config->debugVars[i++][0]), 50, \ + "%s %ld", #_option_, _val_); +#else /* __STDC__ */ +#define RF_DBG_OPTION(_option_,_val_) \ + snprintf(&(config->debugVars[i++][0]), 50, \ + "%s %ld", "/**/_option_/**/", _val_); +#endif /* __STDC__ */ + + i = 0; + +/* RF_DBG_OPTION(accessDebug, 0) */ +/* RF_DBG_OPTION(accessTraceBufSize, 0) */ + RF_DBG_OPTION(cscanDebug, 1) /* debug CSCAN sorting */ + RF_DBG_OPTION(dagDebug, 1) +/* RF_DBG_OPTION(debugPrintUseBuffer, 0) */ + RF_DBG_OPTION(degDagDebug, 1) + RF_DBG_OPTION(disableAsyncAccs, 1) + RF_DBG_OPTION(diskDebug, 1) + RF_DBG_OPTION(enableAtomicRMW, 0) /* this debug var enables + * locking of the disk arm + * during small-write + * operations. Setting this + * variable to anything other + * than 0 will result in + * deadlock. (wvcii) */ + RF_DBG_OPTION(engineDebug, 1) + RF_DBG_OPTION(fifoDebug, 1) /* debug fifo queueing */ +/* RF_DBG_OPTION(floatingRbufDebug, 1) */ +/* RF_DBG_OPTION(forceHeadSepLimit, -1) */ +/* RF_DBG_OPTION(forceNumFloatingReconBufs, -1) */ /* wire down number of + * extra recon buffers + * to use */ +/* RF_DBG_OPTION(keepAccTotals, 1) */ /* turn on keep_acc_totals */ + RF_DBG_OPTION(lockTableSize, RF_DEFAULT_LOCK_TABLE_SIZE) + RF_DBG_OPTION(mapDebug, 1) + RF_DBG_OPTION(maxNumTraces, -1) + +/* RF_DBG_OPTION(memChunkDebug, 1) */ +/* RF_DBG_OPTION(memDebug, 1) */ +/* RF_DBG_OPTION(memDebugAddress, 1) */ +/* RF_DBG_OPTION(numBufsToAccumulate, 1) */ /* number of buffers to + * accumulate before + * doing XOR */ + RF_DBG_OPTION(prReconSched, 0) + RF_DBG_OPTION(printDAGsDebug, 1) + RF_DBG_OPTION(printStatesDebug, 1) + RF_DBG_OPTION(protectedSectors, 64L) /* # of sectors at start + * of disk to exclude + * from RAID address + * space */ + RF_DBG_OPTION(pssDebug, 1) + RF_DBG_OPTION(queueDebug, 1) + RF_DBG_OPTION(quiesceDebug, 1) + RF_DBG_OPTION(raidSectorOffset, 0) /* added to all incoming sectors + * to debug alignment problems */ + RF_DBG_OPTION(reconDebug, 1) + RF_DBG_OPTION(reconbufferDebug, 1) + RF_DBG_OPTION(scanDebug, 1) /* debug SCAN sorting */ + RF_DBG_OPTION(showXorCallCounts, 0) /* show n-way Xor call counts */ + RF_DBG_OPTION(shutdownDebug, 1) /* show shutdown calls */ + RF_DBG_OPTION(sizePercentage, 100) + RF_DBG_OPTION(sstfDebug, 1) /* turn on debugging info for sstf + * queueing */ + RF_DBG_OPTION(stripeLockDebug, 1) + RF_DBG_OPTION(suppressLocksAndLargeWrites, 0) + RF_DBG_OPTION(suppressTraceDelays, 0) + RF_DBG_OPTION(useMemChunks, 1) + RF_DBG_OPTION(validateDAGDebug, 1) + RF_DBG_OPTION(validateVisitedDebug, 1) /* XXX turn to zero by + * default? */ + RF_DBG_OPTION(verifyParityDebug, 1) + RF_DBG_OPTION(debugKernelAccess, 1) /* DoAccessKernel debugging */ + +#if 0 /* RF_INCLUDE_PARITYLOGGING > 0 */ + RF_DBG_OPTION(forceParityLogReint, 0) + RF_DBG_OPTION(numParityRegions, 0) /* number of regions in the + * array */ + RF_DBG_OPTION(numReintegrationThreads, 1) + RF_DBG_OPTION(parityLogDebug, 1) /* if nonzero, enables debugging + * of parity logging */ + RF_DBG_OPTION(totalInCoreLogCapacity, 1024 * 1024) /* target bytes + * available for + * in-core + * logs */ +#endif /* RF_INCLUDE_PARITYLOGGING > 0 */ + +#endif /* RAID_DEBUG_ALL */ } int @@ -3166,7 +3399,7 @@ rf_release_all_vps(cset) /* Close the vp, and give it back */ if (ac->vp) { VOP_CLOSE(ac->vp, FREAD, NOCRED, 0); - vput(ac->vp); + vrele(ac->vp); ac->vp = NULL; } ac = ac->next; @@ -3275,7 +3508,7 @@ rf_auto_config_set(cset,unit) not taken. */ - for(raidID = numraid; raidID >= 0; raidID--) { + for(raidID = numraid - 1; raidID >= 0; raidID--) { if (raidPtrs[raidID]->valid == 0) { /* can use this one! */ break; @@ -3323,3 +3556,14 @@ rf_auto_config_set(cset,unit) *unit = raidID; return(retcode); } + +void +rf_disk_unbusy(desc) + RF_RaidAccessDesc_t *desc; +{ + struct buf *bp; + + bp = (struct buf *)desc->bp; + disk_unbusy(&raid_softc[desc->raidPtr->raidid].sc_dkdev, + (bp->b_bcount - bp->b_resid)); +} diff --git a/sys/dev/raidframe/rf_states.c b/sys/dev/raidframe/rf_states.c index 994902e8067..b7470a8e190 100644 --- a/sys/dev/raidframe/rf_states.c +++ b/sys/dev/raidframe/rf_states.c @@ -1,5 +1,5 @@ -/* $OpenBSD: rf_states.c,v 1.6 2000/01/11 18:02:23 peter Exp $ */ -/* $NetBSD: rf_states.c,v 1.13 2000/01/09 00:00:18 oster Exp $ */ +/* $OpenBSD: rf_states.c,v 1.7 2001/12/29 21:51:18 tdeval Exp $ */ +/* $NetBSD: rf_states.c,v 1.15 2000/10/20 02:24:45 oster Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. @@ -204,6 +204,12 @@ rf_State_LastState(RF_RaidAccessDesc_t * desc) wakeup(desc->bp); /* + * That's all the IO for this one... unbusy the 'disk'. + */ + + rf_disk_unbusy(desc); + + /* * Wakeup any requests waiting to go. */ @@ -216,6 +222,7 @@ rf_State_LastState(RF_RaidAccessDesc_t * desc) /* printf("Calling biodone on 0x%x\n",desc->bp); */ biodone(desc->bp); /* access came through ioctl */ + if (callbackFunc) callbackFunc(callbackArg); rf_FreeRaidAccDesc(desc); @@ -445,7 +452,7 @@ rf_State_CreateDAG(RF_RaidAccessDesc_t * desc) /* failed to create a dag */ /* this happens when there are too many faults or incomplete * dag libraries */ - printf("[Failed to create a DAG\n]"); + printf("[Failed to create a DAG]\n"); RF_PANIC(); } else { /* bind dags to desc */ |