summaryrefslogtreecommitdiff
path: root/sys/dev/raidframe/rf_dagutils.c
diff options
context:
space:
mode:
authoroster <oster@NetBSD.org>2004-03-20 04:22:05 +0000
committeroster <oster@NetBSD.org>2004-03-20 04:22:05 +0000
commit0ff214564803add4a3a9ef738c0dd02b41f2ff38 (patch)
tree5b812f74f0b9cee4b4fa44dae5b864947345022c /sys/dev/raidframe/rf_dagutils.c
parent068442743911ba78048d0658f611997a42661a9c (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.c85
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];