summaryrefslogtreecommitdiff
path: root/sys/dev/raidframe/rf_reconutil.c
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1999-01-11 14:29:56 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1999-01-11 14:29:56 +0000
commit5a29b52d01b420bb61a3112d2d44740a0fa99601 (patch)
tree7d6238740f53a56f5c76ba8256c785b13caaa24a /sys/dev/raidframe/rf_reconutil.c
parent799a3ea9a9c07e091f5f4e62273c6f105cf86191 (diff)
Import of CMU's RAIDframe via NetBSD.
Diffstat (limited to 'sys/dev/raidframe/rf_reconutil.c')
-rw-r--r--sys/dev/raidframe/rf_reconutil.c408
1 files changed, 408 insertions, 0 deletions
diff --git a/sys/dev/raidframe/rf_reconutil.c b/sys/dev/raidframe/rf_reconutil.c
new file mode 100644
index 00000000000..51267198a7e
--- /dev/null
+++ b/sys/dev/raidframe/rf_reconutil.c
@@ -0,0 +1,408 @@
+/* $OpenBSD: rf_reconutil.c,v 1.1 1999/01/11 14:29:47 niklas Exp $ */
+/* $NetBSD: rf_reconutil.c,v 1.1 1998/11/13 04:20:34 oster Exp $ */
+/*
+ * Copyright (c) 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Mark Holland
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/********************************************
+ * rf_reconutil.c -- reconstruction utilities
+ ********************************************/
+
+/* :
+ * Log: rf_reconutil.c,v
+ * Revision 1.32 1996/07/29 14:05:12 jimz
+ * fix numPUs/numRUs confusion (everything is now numRUs)
+ * clean up some commenting, return values
+ *
+ * Revision 1.31 1996/07/15 05:40:41 jimz
+ * some recon datastructure cleanup
+ * better handling of multiple failures
+ * added undocumented double-recon test
+ *
+ * Revision 1.30 1996/07/13 00:00:59 jimz
+ * sanitized generalized reconstruction architecture
+ * cleaned up head sep, rbuf problems
+ *
+ * Revision 1.29 1996/06/19 17:53:48 jimz
+ * move GetNumSparePUs, InstallSpareTable ops into layout switch
+ *
+ * Revision 1.28 1996/06/07 21:33:04 jimz
+ * begin using consistent types for sector numbers,
+ * stripe numbers, row+col numbers, recon unit numbers
+ *
+ * Revision 1.27 1996/06/05 18:06:02 jimz
+ * Major code cleanup. The Great Renaming is now done.
+ * Better modularity. Better typing. Fixed a bunch of
+ * synchronization bugs. Made a lot of global stuff
+ * per-desc or per-array. Removed dead code.
+ *
+ * Revision 1.26 1996/06/03 23:28:26 jimz
+ * more bugfixes
+ * check in tree to sync for IPDS runs with current bugfixes
+ * there still may be a problem with threads in the script test
+ * getting I/Os stuck- not trivially reproducible (runs ~50 times
+ * in a row without getting stuck)
+ *
+ * Revision 1.25 1996/06/02 17:31:48 jimz
+ * Moved a lot of global stuff into array structure, where it belongs.
+ * Fixed up paritylogging, pss modules in this manner. Some general
+ * code cleanup. Removed lots of dead code, some dead files.
+ *
+ * Revision 1.24 1996/05/31 22:26:54 jimz
+ * fix a lot of mapping problems, memory allocation problems
+ * found some weird lock issues, fixed 'em
+ * more code cleanup
+ *
+ * Revision 1.23 1996/05/30 23:22:16 jimz
+ * bugfixes of serialization, timing problems
+ * more cleanup
+ *
+ * Revision 1.22 1996/05/30 11:29:41 jimz
+ * Numerous bug fixes. Stripe lock release code disagreed with the taking code
+ * about when stripes should be locked (I made it consistent: no parity, no lock)
+ * There was a lot of extra serialization of I/Os which I've removed- a lot of
+ * it was to calculate values for the cache code, which is no longer with us.
+ * More types, function, macro cleanup. Added code to properly quiesce the array
+ * on shutdown. Made a lot of stuff array-specific which was (bogusly) general
+ * before. Fixed memory allocation, freeing bugs.
+ *
+ * Revision 1.21 1996/05/27 18:56:37 jimz
+ * more code cleanup
+ * better typing
+ * compiles in all 3 environments
+ *
+ * Revision 1.20 1996/05/23 00:33:23 jimz
+ * code cleanup: move all debug decls to rf_options.c, all extern
+ * debug decls to rf_options.h, all debug vars preceded by rf_
+ *
+ * Revision 1.19 1996/05/20 16:14:55 jimz
+ * switch to rf_{mutex,cond}_{init,destroy}
+ *
+ * Revision 1.18 1996/05/18 19:51:34 jimz
+ * major code cleanup- fix syntax, make some types consistent,
+ * add prototypes, clean out dead code, et cetera
+ *
+ * Revision 1.17 1995/12/12 18:10:06 jimz
+ * MIN -> RF_MIN, MAX -> RF_MAX, ASSERT -> RF_ASSERT
+ * fix 80-column brain damage in comments
+ *
+ * Revision 1.16 1995/12/06 15:05:31 root
+ * added copyright info
+ *
+ */
+
+#include "rf_types.h"
+#include "rf_raid.h"
+#include "rf_desc.h"
+#include "rf_reconutil.h"
+#include "rf_reconbuffer.h"
+#include "rf_general.h"
+#include "rf_decluster.h"
+#include "rf_raid5_rotatedspare.h"
+#include "rf_interdecluster.h"
+#include "rf_chaindecluster.h"
+
+/*******************************************************************
+ * allocates/frees the reconstruction control information structures
+ *******************************************************************/
+RF_ReconCtrl_t *rf_MakeReconControl(reconDesc, frow, fcol, srow, scol)
+ RF_RaidReconDesc_t *reconDesc;
+ RF_RowCol_t frow; /* failed row and column */
+ RF_RowCol_t fcol;
+ RF_RowCol_t srow; /* identifies which spare we're using */
+ RF_RowCol_t scol;
+{
+ RF_Raid_t *raidPtr = reconDesc->raidPtr;
+ RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
+ RF_ReconUnitCount_t RUsPerPU = layoutPtr->SUsPerPU / layoutPtr->SUsPerRU;
+ RF_ReconUnitCount_t numSpareRUs;
+ RF_ReconCtrl_t *reconCtrlPtr;
+ RF_ReconBuffer_t *rbuf;
+ RF_LayoutSW_t *lp;
+ int retcode, rc;
+ RF_RowCol_t i;
+
+ lp = raidPtr->Layout.map;
+
+ /* make and zero the global reconstruction structure and the per-disk structure */
+ RF_Calloc(reconCtrlPtr, 1, sizeof(RF_ReconCtrl_t), (RF_ReconCtrl_t *));
+ RF_Calloc(reconCtrlPtr->perDiskInfo, raidPtr->numCol, sizeof(RF_PerDiskReconCtrl_t), (RF_PerDiskReconCtrl_t *)); /* this zeros it */
+ reconCtrlPtr->reconDesc = reconDesc;
+ reconCtrlPtr->fcol = fcol;
+ reconCtrlPtr->spareRow = srow;
+ reconCtrlPtr->spareCol = scol;
+ reconCtrlPtr->lastPSID = layoutPtr->numStripe/layoutPtr->SUsPerPU;
+ reconCtrlPtr->percentComplete = 0;
+
+ /* initialize each per-disk recon information structure */
+ for (i=0; i<raidPtr->numCol; i++) {
+ reconCtrlPtr->perDiskInfo[i].reconCtrl = reconCtrlPtr;
+ reconCtrlPtr->perDiskInfo[i].row = frow;
+ reconCtrlPtr->perDiskInfo[i].col = i;
+ reconCtrlPtr->perDiskInfo[i].curPSID = -1; /* make it appear as if we just finished an RU */
+ reconCtrlPtr->perDiskInfo[i].ru_count = RUsPerPU-1;
+ }
+
+ /* Get the number of spare units per disk and the sparemap in case spare is distributed */
+
+ if (lp->GetNumSpareRUs) {
+ numSpareRUs = lp->GetNumSpareRUs(raidPtr);
+ }
+ else {
+ numSpareRUs = 0;
+ }
+
+ /*
+ * Not all distributed sparing archs need dynamic mappings
+ */
+ if (lp->InstallSpareTable) {
+ retcode = rf_InstallSpareTable(raidPtr, frow, fcol);
+ if (retcode) {
+ RF_PANIC(); /* XXX fix this*/
+ }
+ }
+
+ /* make the reconstruction map */
+ reconCtrlPtr->reconMap = rf_MakeReconMap(raidPtr, (int) (layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit),
+ raidPtr->sectorsPerDisk, numSpareRUs);
+
+ /* make the per-disk reconstruction buffers */
+ for (i=0; i<raidPtr->numCol; i++) {
+ reconCtrlPtr->perDiskInfo[i].rbuf = (i==fcol) ? NULL : rf_MakeReconBuffer(raidPtr, frow, i, RF_RBUF_TYPE_EXCLUSIVE);
+ }
+
+ /* initialize the event queue */
+ rc = rf_mutex_init(&reconCtrlPtr->eq_mutex);
+ if (rc) {
+ /* XXX deallocate, cleanup */
+ RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
+ __LINE__, rc);
+ return(NULL);
+ }
+ rc = rf_cond_init(&reconCtrlPtr->eq_cond);
+ if (rc) {
+ /* XXX deallocate, cleanup */
+ RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n", __FILE__,
+ __LINE__, rc);
+ return(NULL);
+ }
+ reconCtrlPtr->eventQueue = NULL;
+ reconCtrlPtr->eq_count = 0;
+
+ /* make the floating recon buffers and append them to the free list */
+ rc = rf_mutex_init(&reconCtrlPtr->rb_mutex);
+ if (rc) {
+ /* XXX deallocate, cleanup */
+ RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
+ __LINE__, rc);
+ return(NULL);
+ }
+ reconCtrlPtr->fullBufferList= NULL;
+ reconCtrlPtr->priorityList = NULL;
+ reconCtrlPtr->floatingRbufs = NULL;
+ reconCtrlPtr->committedRbufs= NULL;
+ for (i=0; i<raidPtr->numFloatingReconBufs; i++) {
+ rbuf = rf_MakeReconBuffer(raidPtr, frow, fcol, RF_RBUF_TYPE_FLOATING);
+ rbuf->next = reconCtrlPtr->floatingRbufs;
+ reconCtrlPtr->floatingRbufs = rbuf;
+ }
+
+ /* create the parity stripe status table */
+ reconCtrlPtr->pssTable = rf_MakeParityStripeStatusTable(raidPtr);
+
+ /* set the initial min head sep counter val */
+ reconCtrlPtr->minHeadSepCounter = 0;
+
+ return(reconCtrlPtr);
+}
+
+void rf_FreeReconControl(raidPtr, row)
+ RF_Raid_t *raidPtr;
+ RF_RowCol_t row;
+{
+ RF_ReconCtrl_t *reconCtrlPtr = raidPtr->reconControl[row];
+ RF_ReconBuffer_t *t;
+ RF_ReconUnitNum_t i;
+
+ RF_ASSERT(reconCtrlPtr);
+ for (i=0; i<raidPtr->numCol; i++) if (reconCtrlPtr->perDiskInfo[i].rbuf) rf_FreeReconBuffer(reconCtrlPtr->perDiskInfo[i].rbuf);
+ for (i=0; i<raidPtr->numFloatingReconBufs; i++) {
+ t = reconCtrlPtr->floatingRbufs;
+ RF_ASSERT(t);
+ reconCtrlPtr->floatingRbufs = t->next;
+ rf_FreeReconBuffer(t);
+ }
+ rf_mutex_destroy(&reconCtrlPtr->rb_mutex);
+ rf_mutex_destroy(&reconCtrlPtr->eq_mutex);
+ rf_cond_destroy(&reconCtrlPtr->eq_cond);
+ rf_FreeReconMap(reconCtrlPtr->reconMap);
+ rf_FreeParityStripeStatusTable(raidPtr, reconCtrlPtr->pssTable);
+ RF_Free(reconCtrlPtr->perDiskInfo, raidPtr->numCol * sizeof(RF_PerDiskReconCtrl_t));
+ RF_Free(reconCtrlPtr, sizeof(*reconCtrlPtr));
+}
+
+
+/******************************************************************************
+ * computes the default head separation limit
+ *****************************************************************************/
+RF_HeadSepLimit_t rf_GetDefaultHeadSepLimit(raidPtr)
+ RF_Raid_t *raidPtr;
+{
+ RF_HeadSepLimit_t hsl;
+ RF_LayoutSW_t *lp;
+
+ lp = raidPtr->Layout.map;
+ if (lp->GetDefaultHeadSepLimit == NULL)
+ return(-1);
+ hsl = lp->GetDefaultHeadSepLimit(raidPtr);
+ return(hsl);
+}
+
+
+/******************************************************************************
+ * computes the default number of floating recon buffers
+ *****************************************************************************/
+int rf_GetDefaultNumFloatingReconBuffers(raidPtr)
+ RF_Raid_t *raidPtr;
+{
+ RF_LayoutSW_t *lp;
+ int nrb;
+
+ lp = raidPtr->Layout.map;
+ if (lp->GetDefaultNumFloatingReconBuffers == NULL)
+ return(3 * raidPtr->numCol);
+ nrb = lp->GetDefaultNumFloatingReconBuffers(raidPtr);
+ return(nrb);
+}
+
+
+/******************************************************************************
+ * creates and initializes a reconstruction buffer
+ *****************************************************************************/
+RF_ReconBuffer_t *rf_MakeReconBuffer(
+ RF_Raid_t *raidPtr,
+ RF_RowCol_t row,
+ RF_RowCol_t col,
+ RF_RbufType_t type)
+{
+ RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
+ RF_ReconBuffer_t *t;
+ u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr, layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit);
+
+ RF_Malloc(t, sizeof(RF_ReconBuffer_t), (RF_ReconBuffer_t *));
+ RF_Malloc(t->buffer, recon_buffer_size, (caddr_t));
+ RF_Malloc(t->arrived, raidPtr->numCol * sizeof(char), (char *));
+ t->raidPtr = raidPtr;
+ t->row = row; t->col = col;
+ t->priority = RF_IO_RECON_PRIORITY;
+ t->type = type;
+ t->pssPtr = NULL;
+ t->next = NULL;
+ return(t);
+}
+
+/******************************************************************************
+ * frees a reconstruction buffer
+ *****************************************************************************/
+void rf_FreeReconBuffer(rbuf)
+ RF_ReconBuffer_t *rbuf;
+{
+ RF_Raid_t *raidPtr = rbuf->raidPtr;
+ u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr, raidPtr->Layout.SUsPerRU * raidPtr->Layout.sectorsPerStripeUnit);
+
+ RF_Free(rbuf->arrived, raidPtr->numCol * sizeof(char));
+ RF_Free(rbuf->buffer, recon_buffer_size);
+ RF_Free(rbuf, sizeof(*rbuf));
+}
+
+
+/******************************************************************************
+ * debug only: sanity check the number of floating recon bufs in use
+ *****************************************************************************/
+void rf_CheckFloatingRbufCount(raidPtr, dolock)
+ RF_Raid_t *raidPtr;
+ int dolock;
+{
+ RF_ReconParityStripeStatus_t *p;
+ RF_PSStatusHeader_t *pssTable;
+ RF_ReconBuffer_t *rbuf;
+ int i, j, sum = 0;
+ RF_RowCol_t frow=0;
+
+ for (i=0; i<raidPtr->numRow; i++)
+ if (raidPtr->reconControl[i]) {
+ frow = i;
+ break;
+ }
+ RF_ASSERT(frow >= 0);
+
+ if (dolock)
+ RF_LOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex);
+ pssTable = raidPtr->reconControl[frow]->pssTable;
+
+ for (i=0; i<raidPtr->pssTableSize; i++) {
+ RF_LOCK_MUTEX(pssTable[i].mutex);
+ for (p = pssTable[i].chain; p; p=p->next) {
+ rbuf = (RF_ReconBuffer_t *) p->rbuf;
+ if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING)
+ sum++;
+
+ rbuf = (RF_ReconBuffer_t *) p->writeRbuf;
+ if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING)
+ sum++;
+
+ for (j=0; j<p->xorBufCount; j++) {
+ rbuf = (RF_ReconBuffer_t *) p->rbufsForXor[j];
+ RF_ASSERT(rbuf);
+ if (rbuf->type == RF_RBUF_TYPE_FLOATING)
+ sum++;
+ }
+ }
+ RF_UNLOCK_MUTEX(pssTable[i].mutex);
+ }
+
+ for (rbuf = raidPtr->reconControl[frow]->floatingRbufs; rbuf; rbuf = rbuf->next) {
+ if (rbuf->type == RF_RBUF_TYPE_FLOATING)
+ sum++;
+ }
+ for (rbuf = raidPtr->reconControl[frow]->committedRbufs; rbuf; rbuf = rbuf->next) {
+ if (rbuf->type == RF_RBUF_TYPE_FLOATING)
+ sum++;
+ }
+ for (rbuf = raidPtr->reconControl[frow]->fullBufferList; rbuf; rbuf = rbuf->next) {
+ if (rbuf->type == RF_RBUF_TYPE_FLOATING)
+ sum++;
+ }
+ for (rbuf = raidPtr->reconControl[frow]->priorityList; rbuf; rbuf = rbuf->next) {
+ if (rbuf->type == RF_RBUF_TYPE_FLOATING)
+ sum++;
+ }
+
+ RF_ASSERT(sum == raidPtr->numFloatingReconBufs);
+
+ if (dolock)
+ RF_UNLOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex);
+}