Address a number of issues:

1) Introduce functions to allocate and free the emergency IO buffers.

2) Make sure we free any allocated emergency buffers in the event that
we bail out during configuration, or when we unconfigure an array.

3) if we run out of memory trying to allocate a given type of buffer,
don't continue to try to allocate more of those buffers.
(Partially addresses PR#25787)
This commit is contained in:
oster 2004-06-27 03:15:18 +00:00
parent ca470f56bb
commit 6df1f117b1
1 changed files with 101 additions and 63 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_driver.c,v 1.102 2004/06/02 22:58:28 drochner Exp $ */
/* $NetBSD: rf_driver.c,v 1.103 2004/06/27 03:15:18 oster Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
@ -73,7 +73,7 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.102 2004/06/02 22:58:28 drochner Exp $");
__KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.103 2004/06/27 03:15:18 oster Exp $");
#include "opt_raid_diagnostic.h"
@ -155,6 +155,8 @@ static RF_ShutdownList_t *globalShutdown; /* non array-specific
* stuff */
static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp);
static int rf_AllocEmergBuffers(RF_Raid_t *);
static void rf_FreeEmergBuffers(RF_Raid_t *);
/* called at system boot time */
int
@ -202,7 +204,6 @@ rf_UnconfigureArray()
int
rf_Shutdown(RF_Raid_t *raidPtr)
{
RF_VoidPointerListElem_t *tmp;
if (!raidPtr->valid) {
RF_ERRORMSG("Attempt to shut down unconfigured RAIDframe driver. Aborting shutdown\n");
@ -240,22 +241,8 @@ rf_Shutdown(RF_Raid_t *raidPtr)
rf_UnconfigureVnodes(raidPtr);
/* Free the emergency IO buffers */
while (raidPtr->iobuf != NULL) {
tmp = raidPtr->iobuf;
raidPtr->iobuf = raidPtr->iobuf->next;
free(tmp->p, M_RAIDFRAME);
rf_FreeVPListElem(tmp);
}
rf_FreeEmergBuffers(raidPtr);
/* Free the emergency stripe buffers */
while (raidPtr->stripebuf != NULL) {
tmp = raidPtr->stripebuf;
raidPtr->stripebuf = raidPtr->stripebuf->next;
free(tmp->p, M_RAIDFRAME);
rf_FreeVPListElem(tmp);
}
rf_ShutdownList(&raidPtr->shutdownList);
rf_UnconfigureArray();
@ -277,6 +264,7 @@ rf_Shutdown(RF_Raid_t *raidPtr)
#define DO_RAID_FAIL() { \
rf_UnconfigureVnodes(raidPtr); \
rf_FreeEmergBuffers(raidPtr); \
rf_ShutdownList(&raidPtr->shutdownList); \
rf_UnconfigureArray(); \
}
@ -298,9 +286,7 @@ int
rf_Configure(RF_Raid_t *raidPtr, RF_Config_t *cfgPtr, RF_AutoConfig_t *ac)
{
RF_RowCol_t col;
void *tmpbuf;
RF_VoidPointerListElem_t *vple;
int rc, i;
int rc;
RF_LOCK_LKMGR_MUTEX(configureMutex);
configureCount++;
@ -415,50 +401,15 @@ rf_Configure(RF_Raid_t *raidPtr, RF_Config_t *cfgPtr, RF_AutoConfig_t *ac)
/* Allocate a bunch of buffers to be used in low-memory conditions */
raidPtr->iobuf = NULL;
/* XXX next line needs tuning... */
raidPtr->numEmergencyBuffers = 10 * raidPtr->numCol;
#if DEBUG
printf("raid%d: allocating %d buffers of %d bytes.\n",
raidPtr->raidid,
raidPtr->numEmergencyBuffers,
(int)(raidPtr->Layout.sectorsPerStripeUnit <<
raidPtr->logBytesPerSector));
#endif
for (i = 0; i < raidPtr->numEmergencyBuffers; i++) {
tmpbuf = malloc( raidPtr->Layout.sectorsPerStripeUnit <<
raidPtr->logBytesPerSector,
M_RAIDFRAME, M_NOWAIT);
if (tmpbuf) {
vple = rf_AllocVPListElem();
vple->p= tmpbuf;
vple->next = raidPtr->iobuf;
raidPtr->iobuf = vple;
raidPtr->iobuf_count++;
} else {
printf("raid%d: failed to allocate emergency buffer!\n",
raidPtr->raidid);
}
rc = rf_AllocEmergBuffers(raidPtr);
if (rc) {
printf("raid%d: Unable to allocate emergency buffers.\n",
raidPtr->raidid);
DO_RAID_FAIL();
return(rc);
}
/* XXX next line needs tuning too... */
raidPtr->numEmergencyStripeBuffers = 10;
for (i = 0; i < raidPtr->numEmergencyStripeBuffers; i++) {
tmpbuf = malloc( raidPtr->numCol * (raidPtr->Layout.sectorsPerStripeUnit <<
raidPtr->logBytesPerSector),
M_RAIDFRAME, M_NOWAIT);
if (tmpbuf) {
vple = rf_AllocVPListElem();
vple->p= tmpbuf;
vple->next = raidPtr->stripebuf;
raidPtr->stripebuf = vple;
raidPtr->stripebuf_count++;
} else {
printf("raid%d: failed to allocate emergency stripe buffer!\n",
raidPtr->raidid);
}
}
raidPtr->valid = 1;
printf("raid%d: %s\n", raidPtr->raidid,
@ -481,6 +432,93 @@ rf_Configure(RF_Raid_t *raidPtr, RF_Config_t *cfgPtr, RF_AutoConfig_t *ac)
return (0);
}
/*
Routines to allocate and free the "emergency buffers" for a given
RAID set. These emergency buffers will be used when the kernel runs
out of kernel memory.
*/
static int
rf_AllocEmergBuffers(RF_Raid_t *raidPtr)
{
void *tmpbuf;
RF_VoidPointerListElem_t *vple;
int i;
/* XXX next line needs tuning... */
raidPtr->numEmergencyBuffers = 10 * raidPtr->numCol;
#if DEBUG
printf("raid%d: allocating %d buffers of %d bytes.\n",
raidPtr->raidid,
raidPtr->numEmergencyBuffers,
(int)(raidPtr->Layout.sectorsPerStripeUnit <<
raidPtr->logBytesPerSector));
#endif
for (i = 0; i < raidPtr->numEmergencyBuffers; i++) {
tmpbuf = malloc( raidPtr->Layout.sectorsPerStripeUnit <<
raidPtr->logBytesPerSector,
M_RAIDFRAME, M_NOWAIT);
if (tmpbuf) {
vple = rf_AllocVPListElem();
vple->p= tmpbuf;
vple->next = raidPtr->iobuf;
raidPtr->iobuf = vple;
raidPtr->iobuf_count++;
} else {
printf("raid%d: failed to allocate emergency buffer!\n",
raidPtr->raidid);
break;
}
}
/* XXX next line needs tuning too... */
raidPtr->numEmergencyStripeBuffers = 10;
for (i = 0; i < raidPtr->numEmergencyStripeBuffers; i++) {
tmpbuf = malloc( raidPtr->numCol * (raidPtr->Layout.sectorsPerStripeUnit <<
raidPtr->logBytesPerSector),
M_RAIDFRAME, M_NOWAIT);
if (tmpbuf) {
vple = rf_AllocVPListElem();
vple->p= tmpbuf;
vple->next = raidPtr->stripebuf;
raidPtr->stripebuf = vple;
raidPtr->stripebuf_count++;
} else {
printf("raid%d: failed to allocate emergency stripe buffer!\n",
raidPtr->raidid);
break;
}
}
return (0);
}
static void
rf_FreeEmergBuffers(RF_Raid_t *raidPtr)
{
RF_VoidPointerListElem_t *tmp;
/* Free the emergency IO buffers */
while (raidPtr->iobuf != NULL) {
tmp = raidPtr->iobuf;
raidPtr->iobuf = raidPtr->iobuf->next;
free(tmp->p, M_RAIDFRAME);
rf_FreeVPListElem(tmp);
}
/* Free the emergency stripe buffers */
while (raidPtr->stripebuf != NULL) {
tmp = raidPtr->stripebuf;
raidPtr->stripebuf = raidPtr->stripebuf->next;
free(tmp->p, M_RAIDFRAME);
rf_FreeVPListElem(tmp);
}
}
static void
rf_ShutdownRDFreeList(void *ignored)
{