diff options
| author | oster <oster@NetBSD.org> | 2004-03-20 04:22:05 +0000 |
|---|---|---|
| committer | oster <oster@NetBSD.org> | 2004-03-20 04:22:05 +0000 |
| commit | 0ff214564803add4a3a9ef738c0dd02b41f2ff38 (patch) | |
| tree | 5b812f74f0b9cee4b4fa44dae5b864947345022c /sys/dev/raidframe/rf_dagutils.c | |
| parent | 068442743911ba78048d0658f611997a42661a9c (diff) | |
For each RAID set, pre-allocate a number of "emergency buffers" to be
used in the event that we can't malloc a buffer of the appropriate
size in the traditional way. rf_AllocIOBuffer() and rf_FreeIOBuffer()
deal with allocating/freeing these structures. These buffers are
stored in a list on the 'iobuf' list. iobuf_count keeps track of how
many buffers are available, and numEmergencyBuffers is the effective
"high-water" mark for the freelist. The buffers allocated by
rf_AllocIOBuffer() are stripe-unit sized, which is the maximum
size requested by any of the callers.
Add an iobufs entry to RF_DagHeader_s. Use it for keeping track of
buffers that get allocated from the free-list.
Add a "generic list" pool (VoidPointerListElement Pool) for elements
used to maintain a list of allocated memory. [It is somewhat less
than ideal to add another little pool to handle this...]
Teach rf_AllocBuffer() to use the new rf_AllocIOBuffer(). Modify
other Mallocs to use rf_AllocIOBuffer(), and to update dag_h->iobufs as
appropriate.
Update rf_FreeDAG() to handle cleanup of dag_h->iobufs.
While here, add some missing pool_destroy() calls for a number of pools.
With these changes, it should (in theory) be possible to swap on
RAID 5 sets again. That said, I've not had any success there yet --
but the last issue I saw at least wasn't in RAIDframe. :-}
[There is room for this code to become a bit more consise, but I
wanted to do a checkpoint here with something known to work :) ]
Diffstat (limited to 'sys/dev/raidframe/rf_dagutils.c')
| -rw-r--r-- | sys/dev/raidframe/rf_dagutils.c | 85 |
1 files changed, 78 insertions, 7 deletions
diff --git a/sys/dev/raidframe/rf_dagutils.c b/sys/dev/raidframe/rf_dagutils.c index 5a0c4a5cd70..b33eafcc25a 100644 --- a/sys/dev/raidframe/rf_dagutils.c +++ b/sys/dev/raidframe/rf_dagutils.c @@ -1,4 +1,4 @@ -/* $NetBSD: rf_dagutils.c,v 1.40 2004/03/19 17:01:26 oster Exp $ */ +/* $NetBSD: rf_dagutils.c,v 1.41 2004/03/20 04:22:05 oster Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. @@ -33,7 +33,7 @@ *****************************************************************************/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rf_dagutils.c,v 1.40 2004/03/19 17:01:26 oster Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rf_dagutils.c,v 1.41 2004/03/20 04:22:05 oster Exp $"); #include <dev/raidframe/raidframevar.h> @@ -66,7 +66,6 @@ static void rf_ValidateBranchVisitedBits(RF_DagNode_t *, int, int); static void rf_ValidateVisitedBits(RF_DagHeader_t *); #endif /* RF_DEBUG_VALIDATE_DAG */ - /* The maximum number of nodes in a DAG is bounded by (2 * raidPtr->Layout->numDataCol) + (1 * layoutPtr->numParityCol) + @@ -181,6 +180,7 @@ rf_FreeDAG(RF_DagHeader_t *dag_h) RF_AccessStripeMapHeader_t *asmap, *t_asmap; RF_PhysDiskAddr_t *pda; RF_DagNode_t *tmpnode; + RF_VoidPointerListElem_t *tmpiobuf; RF_DagHeader_t *nextDag; while (dag_h) { @@ -196,6 +196,13 @@ rf_FreeDAG(RF_DagHeader_t *dag_h) dag_h->pda_cleanup_list = dag_h->pda_cleanup_list->next; rf_FreePhysDiskAddr(pda); } + while (dag_h->iobufs) { + tmpiobuf = dag_h->iobufs; + dag_h->iobufs = dag_h->iobufs->next; + if (tmpiobuf->p) + rf_FreeIOBuffer(dag_h->raidPtr, tmpiobuf->p); + rf_FreeVPListElem(tmpiobuf); + } while (dag_h->nodes) { tmpnode = dag_h->nodes; dag_h->nodes = dag_h->nodes->list_next; @@ -221,6 +228,9 @@ rf_FreeDAG(RF_DagHeader_t *dag_h) #define RF_MAX_FREE_FUNCLIST 128 #define RF_MIN_FREE_FUNCLIST 32 +#define RF_MAX_FREE_BUFFERS 128 +#define RF_MIN_FREE_BUFFERS 32 + static void rf_ShutdownDAGs(void *); static void rf_ShutdownDAGs(void *ignored) @@ -347,11 +357,63 @@ rf_AllocBuffer(RF_Raid_t *raidPtr, RF_PhysDiskAddr_t *pda, RF_AllocListElem_t *allocList) { char *p; + p = rf_AllocIOBuffer(raidPtr, pda->numSector << raidPtr->logBytesPerSector); - RF_MallocAndAdd(p, pda->numSector << raidPtr->logBytesPerSector, - (char *), allocList); + if (allocList) + rf_AddToAllocList(allocList, p, pda->numSector << raidPtr->logBytesPerSector); return ((void *) p); } + +void * +rf_AllocIOBuffer(RF_Raid_t *raidPtr, int size) +{ + void *p; + + RF_ASSERT(size <= (raidPtr->Layout.sectorsPerStripeUnit << + raidPtr->logBytesPerSector)); + + p = malloc( raidPtr->Layout.sectorsPerStripeUnit << + raidPtr->logBytesPerSector, + M_RAIDFRAME, M_NOWAIT); + if (!p) { + RF_LOCK_MUTEX(raidPtr->mutex); + if (raidPtr->iobuf_count > 0) { + p = raidPtr->iobuf; + raidPtr->iobuf = raidPtr->iobuf->next; + raidPtr->iobuf_count--; + } else { +#ifdef DIAGNOSTIC + printf("raid%d: Help! Out of emergency buffers!\n", raidPtr->raidid); +#endif + } + RF_UNLOCK_MUTEX(raidPtr->mutex); + if (!p) { + /* We didn't get a buffer... not much we can do other than wait, + and hope that someone frees up memory for us.. */ + p = malloc( raidPtr->Layout.sectorsPerStripeUnit << + raidPtr->logBytesPerSector, + M_RAIDFRAME, M_WAITOK); + } + } + return (p); +} + +void +rf_FreeIOBuffer(RF_Raid_t *raidPtr, void *p) +{ + RF_LOCK_MUTEX(raidPtr->mutex); + if (raidPtr->iobuf_count < raidPtr->numEmergencyBuffers) { + ((RF_IOBufHeader_t *)p)->next = raidPtr->iobuf; + raidPtr->iobuf = p; + raidPtr->iobuf_count++; + } else { + free(p, M_RAIDFRAME); + } + RF_UNLOCK_MUTEX(raidPtr->mutex); +} + + + #if RF_DEBUG_VALIDATE_DAG /****************************************************************************** * @@ -877,6 +939,7 @@ rf_MapUnaccessedPortionOfStripe(RF_Raid_t *raidPtr, { RF_RaidAddr_t sosRaidAddress, eosRaidAddress; RF_SectorNum_t sosNumSector, eosNumSector; + RF_VoidPointerListElem_t *vple; RF_ASSERT(asmap->numStripeUnitsAccessed > (layoutPtr->numDataCol / 2)); /* generate an access map for the region of the array from start of @@ -886,7 +949,11 @@ rf_MapUnaccessedPortionOfStripe(RF_Raid_t *raidPtr, if (!rf_RaidAddressStripeAligned(layoutPtr, asmap->raidAddress)) { sosRaidAddress = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, asmap->raidAddress); sosNumSector = asmap->raidAddress - sosRaidAddress; - RF_MallocAndAdd(*sosBuffer, rf_RaidAddressToByte(raidPtr, sosNumSector), (char *), allocList); + *sosBuffer = rf_AllocIOBuffer(raidPtr, rf_RaidAddressToByte(raidPtr, sosNumSector)); + vple = rf_AllocVPListElem(); + vple->p = *sosBuffer; + vple->next = dag_h->iobufs; + dag_h->iobufs = vple; new_asm_h[0] = rf_MapAccess(raidPtr, sosRaidAddress, sosNumSector, *sosBuffer, RF_DONT_REMAP); new_asm_h[0]->next = dag_h->asmList; dag_h->asmList = new_asm_h[0]; @@ -902,7 +969,11 @@ rf_MapUnaccessedPortionOfStripe(RF_Raid_t *raidPtr, if (!rf_RaidAddressStripeAligned(layoutPtr, asmap->endRaidAddress)) { eosRaidAddress = asmap->endRaidAddress; eosNumSector = rf_RaidAddressOfNextStripeBoundary(layoutPtr, eosRaidAddress) - eosRaidAddress; - RF_MallocAndAdd(*eosBuffer, rf_RaidAddressToByte(raidPtr, eosNumSector), (char *), allocList); + *eosBuffer = rf_AllocIOBuffer(raidPtr, rf_RaidAddressToByte(raidPtr, eosNumSector)); + vple = rf_AllocVPListElem(); + vple->p = *eosBuffer; + vple->next = dag_h->iobufs; + dag_h->iobufs = vple; new_asm_h[1] = rf_MapAccess(raidPtr, eosRaidAddress, eosNumSector, *eosBuffer, RF_DONT_REMAP); new_asm_h[1]->next = dag_h->asmList; dag_h->asmList = new_asm_h[1]; |
