As part of the effort to get RAIDframe playing nicely with LOCKDEBUG,

rework how completed requests are handled.  In particular, instead of
doing all sorts of work and locking in interrupt context, completed
requests are now queued.  A new kernel thread (rf_RaidIOThread) now
handles calling rf_DiskIOComplete() and (req->CompleteFunc)() for each
completed request.  There is still work to be done to make RAIDframe
LOCKDEBUG friendly, but this change is a huge step forward.

Reviewed by (and many thanks to): thorpej
This commit is contained in:
oster 2002-10-04 20:05:14 +00:00
parent 2a1b344158
commit 8bdc70d040
5 changed files with 116 additions and 14 deletions

View File

@ -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. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -38,14 +38,14 @@
#ifndef _RF__RF_DISKQUEUE_H_ #ifndef _RF__RF_DISKQUEUE_H_
#define _RF__RF_DISKQUEUE_H_ #define _RF__RF_DISKQUEUE_H_
#include <sys/queue.h>
#include <dev/raidframe/raidframevar.h> #include <dev/raidframe/raidframevar.h>
#include "rf_threadstuff.h" #include "rf_threadstuff.h"
#include "rf_acctrace.h" #include "rf_acctrace.h"
#include "rf_alloclist.h" #include "rf_alloclist.h"
#include "rf_etimer.h" #include "rf_etimer.h"
#include "rf_netbsd.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 struct proc *b_proc; /* the b_proc from the original bp passed into
* the driver for this I/O */ * the driver for this I/O */
struct buf *bp; /* a bp to use to get this I/O done */ 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_LOCK_DISK_QUEUE 0x01
#define RF_UNLOCK_DISK_QUEUE 0x02 #define RF_UNLOCK_DISK_QUEUE 0x02

View File

@ -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. * Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
@ -73,7 +73,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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 <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -402,6 +402,9 @@ rf_Configure(raidPtr, cfgPtr, ac)
raidPtr->reconControl[i] = NULL; 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_ConfigureEngine);
DO_RAID_INIT_CONFIGURE(rf_ConfigureStripeLocks); DO_RAID_INIT_CONFIGURE(rf_ConfigureStripeLocks);

View File

@ -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. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -55,7 +55,7 @@
****************************************************************************/ ****************************************************************************/
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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" #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" #include "rf_raid.h"
static void DAGExecutionThread(RF_ThreadArg_t arg); static void DAGExecutionThread(RF_ThreadArg_t arg);
static void rf_RaidIOThread(RF_ThreadArg_t arg);
#define DO_INIT(_l_,_r_) { \ #define DO_INIT(_l_,_r_) { \
int _rc; \ int _rc; \
@ -110,10 +111,29 @@ rf_ShutdownEngine(arg)
void *arg; void *arg;
{ {
RF_Raid_t *raidPtr; RF_Raid_t *raidPtr;
int ks;
raidPtr = (RF_Raid_t *) arg; 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 int
@ -143,6 +163,13 @@ rf_ConfigureEngine(
RF_ERRORMSG("RAIDFRAME: Unable to create engine thread\n"); RF_ERRORMSG("RAIDFRAME: Unable to create engine thread\n");
return (ENOMEM); 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) { if (rf_engineDebug) {
printf("raid%d: Created engine thread\n", raidPtr->raidid); printf("raid%d: Created engine thread\n", raidPtr->raidid);
} }
@ -811,3 +838,49 @@ DAGExecutionThread(RF_ThreadArg_t arg)
splx(s); splx(s);
kthread_exit(0); 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);
}

View File

@ -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. * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
@ -114,7 +114,7 @@
***********************************************************/ ***********************************************************/
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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 <sys/param.h> #include <sys/param.h>
#include <sys/errno.h> #include <sys/errno.h>
@ -1931,8 +1931,19 @@ KernelWakeupFunc(vbp)
pool_put(&raidframe_cbufpool, raidbp); pool_put(&raidframe_cbufpool, raidbp);
rf_DiskIOComplete(queue, req, (bp->b_flags & B_ERROR) ? 1 : 0); /* Fill in the error value */
(req->CompleteFunc) (req->argument, (bp->b_flags & B_ERROR) ? 1 : 0);
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); splx(s);
} }

View File

@ -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. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -42,6 +42,7 @@
#include <sys/disklabel.h> #include <sys/disklabel.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/queue.h>
#include "rf_alloclist.h" #include "rf_alloclist.h"
#include "rf_stripelocks.h" #include "rf_stripelocks.h"
@ -51,6 +52,7 @@
#include "rf_diskqueue.h" #include "rf_diskqueue.h"
#include "rf_reconstruct.h" #include "rf_reconstruct.h"
#include "rf_acctrace.h" #include "rf_acctrace.h"
#include "rf_fifo.h"
#if RF_INCLUDE_PARITYLOGGING > 0 #if RF_INCLUDE_PARITYLOGGING > 0
#include "rf_paritylog.h" #include "rf_paritylog.h"
@ -157,6 +159,13 @@ struct RF_Raid_s {
This may be in conflict with last_unit!!?! */ This may be in conflict with last_unit!!?! */
/* Not currently used. */ /* 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 * Cleanup stuff
*/ */
@ -210,9 +219,11 @@ struct RF_Raid_s {
RF_Thread_t parity_rewrite_thread; RF_Thread_t parity_rewrite_thread;
RF_Thread_t copyback_thread; RF_Thread_t copyback_thread;
RF_Thread_t engine_thread; RF_Thread_t engine_thread;
RF_Thread_t engine_helper_thread;
RF_Thread_t recon_thread; RF_Thread_t recon_thread;
RF_ThreadGroup_t engine_tg; RF_ThreadGroup_t engine_tg;
int shutdown_engine; int shutdown_engine;
int shutdown_raidio;
int dags_in_flight; /* debug */ int dags_in_flight; /* debug */
/* /*