diff --git a/sys/dev/raidframe/rf_diskqueue.h b/sys/dev/raidframe/rf_diskqueue.h index d568a8f9d1b9..c53ba480d8ef 100644 --- a/sys/dev/raidframe/rf_diskqueue.h +++ b/sys/dev/raidframe/rf_diskqueue.h @@ -1,4 +1,4 @@ -/* $NetBSD: rf_diskqueue.h,v 1.10 2002/09/15 21:34:03 oster Exp $ */ +/* $NetBSD: rf_diskqueue.h,v 1.11 2002/10/04 20:05:14 oster Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. @@ -38,14 +38,14 @@ #ifndef _RF__RF_DISKQUEUE_H_ #define _RF__RF_DISKQUEUE_H_ +#include + #include #include "rf_threadstuff.h" #include "rf_acctrace.h" #include "rf_alloclist.h" #include "rf_etimer.h" - - #include "rf_netbsd.h" @@ -77,6 +77,10 @@ struct RF_DiskQueueData_s { struct proc *b_proc; /* the b_proc from the original bp passed into * the driver for this I/O */ struct buf *bp; /* a bp to use to get this I/O done */ + /* TAILQ bits for a queue for completed I/O requests */ + TAILQ_ENTRY(RF_DiskQueueData_s) iodone_entries; + int error; /* Indicate if an error occured + on this I/O (1=yes, 0=no) */ }; #define RF_LOCK_DISK_QUEUE 0x01 #define RF_UNLOCK_DISK_QUEUE 0x02 diff --git a/sys/dev/raidframe/rf_driver.c b/sys/dev/raidframe/rf_driver.c index c39f12e10386..a2fa06f83040 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.63 2002/09/23 04:14:20 oster Exp $ */ +/* $NetBSD: rf_driver.c,v 1.64 2002/10/04 20:05:14 oster Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. @@ -73,7 +73,7 @@ #include -__KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.63 2002/09/23 04:14:20 oster Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.64 2002/10/04 20:05:14 oster Exp $"); #include #include @@ -402,6 +402,9 @@ rf_Configure(raidPtr, cfgPtr, ac) raidPtr->reconControl[i] = NULL; } + TAILQ_INIT(&(raidPtr->iodone)); + simple_lock_init(&(raidPtr->iodone_lock)); + DO_RAID_INIT_CONFIGURE(rf_ConfigureEngine); DO_RAID_INIT_CONFIGURE(rf_ConfigureStripeLocks); diff --git a/sys/dev/raidframe/rf_engine.c b/sys/dev/raidframe/rf_engine.c index 828dc7148ffc..b635b0fcfdb6 100644 --- a/sys/dev/raidframe/rf_engine.c +++ b/sys/dev/raidframe/rf_engine.c @@ -1,4 +1,4 @@ -/* $NetBSD: rf_engine.c,v 1.21 2002/10/02 21:48:00 oster Exp $ */ +/* $NetBSD: rf_engine.c,v 1.22 2002/10/04 20:05:15 oster Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. @@ -55,7 +55,7 @@ ****************************************************************************/ #include -__KERNEL_RCSID(0, "$NetBSD: rf_engine.c,v 1.21 2002/10/02 21:48:00 oster Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rf_engine.c,v 1.22 2002/10/04 20:05:15 oster Exp $"); #include "rf_threadstuff.h" @@ -70,6 +70,7 @@ __KERNEL_RCSID(0, "$NetBSD: rf_engine.c,v 1.21 2002/10/02 21:48:00 oster Exp $") #include "rf_raid.h" static void DAGExecutionThread(RF_ThreadArg_t arg); +static void rf_RaidIOThread(RF_ThreadArg_t arg); #define DO_INIT(_l_,_r_) { \ int _rc; \ @@ -110,10 +111,29 @@ rf_ShutdownEngine(arg) void *arg; { RF_Raid_t *raidPtr; + int ks; raidPtr = (RF_Raid_t *) arg; - raidPtr->shutdown_engine = 1; - DO_SIGNAL(raidPtr); + + /* Tell the rf_RaidIOThread to shutdown */ + simple_lock(&(raidPtr->iodone_lock)); + + raidPtr->shutdown_raidio = 1; + wakeup(&(raidPtr->iodone)); + + /* ...and wait for it to tell us it has finished */ + while (raidPtr->shutdown_raidio) + ltsleep(&(raidPtr->shutdown_raidio), PRIBIO, "raidshutdown", 0, + &(raidPtr->iodone_lock)); + + simple_unlock(&(raidPtr->iodone_lock)); + + /* Now shut down the DAG execution engine. */ + DO_LOCK(raidPtr); + raidPtr->shutdown_engine = 1; + DO_SIGNAL(raidPtr); + DO_UNLOCK(raidPtr); + } int @@ -143,6 +163,13 @@ rf_ConfigureEngine( RF_ERRORMSG("RAIDFRAME: Unable to create engine thread\n"); return (ENOMEM); } + if (RF_CREATE_ENGINE_THREAD(raidPtr->engine_helper_thread, + rf_RaidIOThread, raidPtr, + "raidio%d", raidPtr->raidid)) { + printf("raid%d: Unable to create raidio thread\n", + raidPtr->raidid); + return (ENOMEM); + } if (rf_engineDebug) { printf("raid%d: Created engine thread\n", raidPtr->raidid); } @@ -811,3 +838,49 @@ DAGExecutionThread(RF_ThreadArg_t arg) splx(s); kthread_exit(0); } + +/* + rf_RaidIOThread() -- When I/O to a component completes, KernelWakeupFunc() + puts the completed request onto raidPtr->iodone TAILQ. This function + looks after requests on that queue by calling rf_DiskIOComplete() for + the request, and by calling any required CompleteFunc for the request. +*/ + +static void +rf_RaidIOThread(RF_ThreadArg_t arg) +{ + RF_Raid_t *raidPtr; + RF_DiskQueueData_t *req; + int s; + + raidPtr = (RF_Raid_t *) arg; + + s = splbio(); + simple_lock(&(raidPtr->iodone_lock)); + + while (!raidPtr->shutdown_raidio) { + /* if there is nothing to do, then snooze. */ + if (TAILQ_EMPTY(&(raidPtr->iodone))) { + ltsleep(&(raidPtr->iodone), PRIBIO, "raidiow", 0, + &(raidPtr->iodone_lock)); + } + + /* See what I/Os, if any, have arrived */ + while ((req = TAILQ_FIRST(&(raidPtr->iodone))) != NULL) { + TAILQ_REMOVE(&(raidPtr->iodone), req, iodone_entries); + simple_unlock(&(raidPtr->iodone_lock)); + rf_DiskIOComplete(req->queue, req, req->error); + (req->CompleteFunc) (req->argument, req->error); + simple_lock(&(raidPtr->iodone_lock)); + } + } + + /* Let rf_ShutdownEngine know that we're done... */ + raidPtr->shutdown_raidio = 0; + wakeup(&(raidPtr->shutdown_raidio)); + + simple_unlock(&(raidPtr->iodone_lock)); + splx(s); + + kthread_exit(0); +} diff --git a/sys/dev/raidframe/rf_netbsdkintf.c b/sys/dev/raidframe/rf_netbsdkintf.c index fc78cd3a0479..b713566eb4d6 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.142 2002/10/01 18:11:57 thorpej Exp $ */ +/* $NetBSD: rf_netbsdkintf.c,v 1.143 2002/10/04 20:05:14 oster Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. @@ -114,7 +114,7 @@ ***********************************************************/ #include -__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.142 2002/10/01 18:11:57 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.143 2002/10/04 20:05:14 oster Exp $"); #include #include @@ -1931,8 +1931,19 @@ KernelWakeupFunc(vbp) pool_put(&raidframe_cbufpool, raidbp); - rf_DiskIOComplete(queue, req, (bp->b_flags & B_ERROR) ? 1 : 0); - (req->CompleteFunc) (req->argument, (bp->b_flags & B_ERROR) ? 1 : 0); + /* Fill in the error value */ + + req->error = (bp->b_flags & B_ERROR) ? bp->b_error : 0; + + simple_lock(&queue->raidPtr->iodone_lock); + + /* Drop this one on the "finished" queue... */ + TAILQ_INSERT_TAIL(&(queue->raidPtr->iodone), req, iodone_entries); + + /* Let the raidio thread know there is work to be done. */ + wakeup(&(queue->raidPtr->iodone)); + + simple_unlock(&queue->raidPtr->iodone_lock); splx(s); } diff --git a/sys/dev/raidframe/rf_raid.h b/sys/dev/raidframe/rf_raid.h index 997e11f7a08e..473aca767b17 100644 --- a/sys/dev/raidframe/rf_raid.h +++ b/sys/dev/raidframe/rf_raid.h @@ -1,4 +1,4 @@ -/* $NetBSD: rf_raid.h,v 1.14 2001/10/04 15:58:55 oster Exp $ */ +/* $NetBSD: rf_raid.h,v 1.15 2002/10/04 20:05:14 oster Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. @@ -42,6 +42,7 @@ #include #include +#include #include "rf_alloclist.h" #include "rf_stripelocks.h" @@ -51,6 +52,7 @@ #include "rf_diskqueue.h" #include "rf_reconstruct.h" #include "rf_acctrace.h" +#include "rf_fifo.h" #if RF_INCLUDE_PARITYLOGGING > 0 #include "rf_paritylog.h" @@ -157,6 +159,13 @@ struct RF_Raid_s { This may be in conflict with last_unit!!?! */ /* Not currently used. */ + /* queue to gather up requests from KernelWakeupFunc() and let + a kernel thread deal with calling rf_DiskIOComplete and any + callback functions. */ + TAILQ_HEAD(iodone_q,RF_DiskQueueData_s) iodone; + /* and a lock to protect it */ + struct simplelock iodone_lock; + /* * Cleanup stuff */ @@ -210,9 +219,11 @@ struct RF_Raid_s { RF_Thread_t parity_rewrite_thread; RF_Thread_t copyback_thread; RF_Thread_t engine_thread; + RF_Thread_t engine_helper_thread; RF_Thread_t recon_thread; RF_ThreadGroup_t engine_tg; int shutdown_engine; + int shutdown_raidio; int dags_in_flight; /* debug */ /*