From 8409d98998d503a0d110b23d81f5616105431bec Mon Sep 17 00:00:00 2001 From: Greg Lehey Date: Wed, 13 Oct 1999 03:16:05 +0000 Subject: [PATCH] Add some private storage so that we can queue requests in an interrupt environment even if malloc fails. --- sys/dev/vinum/request.h | 2 ++ sys/dev/vinum/vinumdaemon.c | 38 +++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/sys/dev/vinum/request.h b/sys/dev/vinum/request.h index 017a1ce5493b..af8fe56966ab 100644 --- a/sys/dev/vinum/request.h +++ b/sys/dev/vinum/request.h @@ -33,6 +33,7 @@ * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * + * $Id: request.h,v 1.16 1999/10/12 04:33:24 grog Exp grog $ * $FreeBSD$ */ @@ -234,6 +235,7 @@ union daemoninfo { /* and the request information */ struct daemonq { struct daemonq *next; /* pointer to next element in queue */ enum daemonrq type; /* type of request */ + int privateinuse; /* private element, being used */ union daemoninfo info; /* and the request information */ }; diff --git a/sys/dev/vinum/vinumdaemon.c b/sys/dev/vinum/vinumdaemon.c index 8f39f7da9f13..8da125408226 100644 --- a/sys/dev/vinum/vinumdaemon.c +++ b/sys/dev/vinum/vinumdaemon.c @@ -34,6 +34,7 @@ * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * + * $Id: vinumdaemon.c,v 1.7 1999/10/12 09:39:48 grog Exp grog $ * $FreeBSD$ */ @@ -47,16 +48,26 @@ /* declarations */ void recover_io(struct request *rq); -struct daemonq *daemonq; /* daemon's work queue */ -struct daemonq *dqend; /* and the end of the queue */ int daemon_options = 0; /* options */ int daemonpid; /* PID of daemon */ +struct daemonq *daemonq; /* daemon's work queue */ +struct daemonq *dqend; /* and the end of the queue */ + +/* + * We normally call Malloc to get a queue element. In interrupt + * context, we can't guarantee that we'll get one, since we're not + * allowed to wait. If malloc fails, use one of these elements. + */ + +#define INTQSIZE 4 +struct daemonq intq[INTQSIZE]; /* queue elements for interrupt context */ +struct daemonq *intqp; /* and pointer in it */ void vinum_daemon(void) { - struct daemonq *request; int s; + struct daemonq *request; daemon_save_config(); /* start by saving the configuration */ daemonpid = curproc->p_pid; /* mark our territory */ @@ -160,7 +171,10 @@ vinum_daemon(void) log(LOG_WARNING, "Invalid request\n"); break; } - Free(request); /* done with the request */ + if (request->privateinuse) /* one of ours, */ + request->privateinuse = 0; /* no longer in use */ + else + Free(request); /* return it */ } } } @@ -202,6 +216,22 @@ queue_daemon_request(enum daemonrq type, union daemoninfo info) int s; struct daemonq *qelt = (struct daemonq *) Malloc(sizeof(struct daemonq)); + + if (qelt == NULL) { /* malloc failed, we're prepared for that */ + /* + * Take one of our spares. Give up if it's still in use; the only + * message we're likely to get here is a 'drive failed' message, + * and that'll come by again if we miss it. + */ + if (intqp->privateinuse) /* still in use? */ + return; /* yes, give up */ + qelt = intqp++; + if (intqp == &intq[INTQSIZE]) /* got to the end, */ + intqp = intq; /* wrap around */ + qelt->privateinuse = 1; /* it's ours, and it's in use */ + } else + qelt->privateinuse = 0; + qelt->next = NULL; /* end of the chain */ qelt->type = type; qelt->info = info;