root/dev/raidframe/rf_reconutil.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rf_MakeReconControl
  2. rf_FreeReconControl
  3. rf_GetDefaultHeadSepLimit
  4. rf_GetDefaultNumFloatingReconBuffers
  5. rf_MakeReconBuffer
  6. rf_FreeReconBuffer
  7. rf_CheckFloatingRbufCount

    1 /*      $OpenBSD: rf_reconutil.c,v 1.3 2002/12/16 07:01:05 tdeval Exp $ */
    2 /*      $NetBSD: rf_reconutil.c,v 1.3 1999/02/05 00:06:17 oster Exp $   */
    3 
    4 /*
    5  * Copyright (c) 1995 Carnegie-Mellon University.
    6  * All rights reserved.
    7  *
    8  * Author: Mark Holland
    9  *
   10  * Permission to use, copy, modify and distribute this software and
   11  * its documentation is hereby granted, provided that both the copyright
   12  * notice and this permission notice appear in all copies of the
   13  * software, derivative works or modified versions, and any portions
   14  * thereof, and that both notices appear in supporting documentation.
   15  *
   16  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   17  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
   18  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   19  *
   20  * Carnegie Mellon requests users of this software to return to
   21  *
   22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   23  *  School of Computer Science
   24  *  Carnegie Mellon University
   25  *  Pittsburgh PA 15213-3890
   26  *
   27  * any improvements or extensions that they make and grant Carnegie the
   28  * rights to redistribute these changes.
   29  */
   30 
   31 /**********************************************
   32  * rf_reconutil.c -- Reconstruction utilities.
   33  **********************************************/
   34 
   35 #include "rf_types.h"
   36 #include "rf_raid.h"
   37 #include "rf_desc.h"
   38 #include "rf_reconutil.h"
   39 #include "rf_reconbuffer.h"
   40 #include "rf_general.h"
   41 #include "rf_decluster.h"
   42 #include "rf_raid5_rotatedspare.h"
   43 #include "rf_interdecluster.h"
   44 #include "rf_chaindecluster.h"
   45 
   46 
   47 /*********************************************************************
   48  * Allocates/frees the reconstruction control information structures.
   49  *********************************************************************/
   50 RF_ReconCtrl_t *
   51 rf_MakeReconControl(
   52     RF_RaidReconDesc_t  *reconDesc,
   53     RF_RowCol_t          frow,  /* Failed row and column. */
   54     RF_RowCol_t          fcol,
   55     RF_RowCol_t          srow,  /* Identifies which spare we're using. */
   56     RF_RowCol_t          scol
   57 )
   58 {
   59         RF_Raid_t *raidPtr = reconDesc->raidPtr;
   60         RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
   61         RF_ReconUnitCount_t RUsPerPU = layoutPtr->SUsPerPU /
   62             layoutPtr->SUsPerRU;
   63         RF_ReconUnitCount_t numSpareRUs;
   64         RF_ReconCtrl_t *reconCtrlPtr;
   65         RF_ReconBuffer_t *rbuf;
   66         RF_LayoutSW_t *lp;
   67         int retcode, rc;
   68         RF_RowCol_t i;
   69 
   70         lp = raidPtr->Layout.map;
   71 
   72         /*
   73          * Make and zero the global reconstruction structure and the per-disk
   74          * structure.
   75          */
   76         RF_Calloc(reconCtrlPtr, 1, sizeof(RF_ReconCtrl_t), (RF_ReconCtrl_t *));
   77         /* This zeros it. */
   78         RF_Calloc(reconCtrlPtr->perDiskInfo, raidPtr->numCol,
   79             sizeof(RF_PerDiskReconCtrl_t), (RF_PerDiskReconCtrl_t *));
   80         reconCtrlPtr->reconDesc = reconDesc;
   81         reconCtrlPtr->fcol = fcol;
   82         reconCtrlPtr->spareRow = srow;
   83         reconCtrlPtr->spareCol = scol;
   84         reconCtrlPtr->lastPSID = layoutPtr->numStripe / layoutPtr->SUsPerPU;
   85         reconCtrlPtr->percentComplete = 0;
   86 
   87         /* Initialize each per-disk recon information structure. */
   88         for (i = 0; i < raidPtr->numCol; i++) {
   89                 reconCtrlPtr->perDiskInfo[i].reconCtrl = reconCtrlPtr;
   90                 reconCtrlPtr->perDiskInfo[i].row = frow;
   91                 reconCtrlPtr->perDiskInfo[i].col = i;
   92                 /* Make it appear as if we just finished an RU. */
   93                 reconCtrlPtr->perDiskInfo[i].curPSID = -1;
   94                 reconCtrlPtr->perDiskInfo[i].ru_count = RUsPerPU - 1;
   95         }
   96 
   97         /*
   98          * Get the number of spare units per disk and the sparemap in case
   99          * spare is distributed.
  100          */
  101 
  102         if (lp->GetNumSpareRUs) {
  103                 numSpareRUs = lp->GetNumSpareRUs(raidPtr);
  104         } else {
  105                 numSpareRUs = 0;
  106         }
  107 
  108         /*
  109          * Not all distributed sparing archs need dynamic mappings.
  110          */
  111         if (lp->InstallSpareTable) {
  112                 retcode = rf_InstallSpareTable(raidPtr, frow, fcol);
  113                 if (retcode) {
  114                         RF_PANIC();     /* XXX Fix this. */
  115                 }
  116         }
  117         /* Make the reconstruction map. */
  118         reconCtrlPtr->reconMap = rf_MakeReconMap(raidPtr,
  119             (int) (layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit),
  120             raidPtr->sectorsPerDisk, numSpareRUs);
  121 
  122         /* Make the per-disk reconstruction buffers. */
  123         for (i = 0; i < raidPtr->numCol; i++) {
  124                 reconCtrlPtr->perDiskInfo[i].rbuf = (i == fcol) ? NULL :
  125                     rf_MakeReconBuffer(raidPtr, frow, i,
  126                      RF_RBUF_TYPE_EXCLUSIVE);
  127         }
  128 
  129         /* Initialize the event queue. */
  130         rc = rf_mutex_init(&reconCtrlPtr->eq_mutex);
  131         if (rc) {
  132                 /* XXX Deallocate, cleanup. */
  133                 RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d.\n",
  134                     __FILE__, __LINE__, rc);
  135                 return (NULL);
  136         }
  137         rc = rf_cond_init(&reconCtrlPtr->eq_cond);
  138         if (rc) {
  139                 /* XXX Deallocate, cleanup. */
  140                 RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d.\n",
  141                     __FILE__, __LINE__, rc);
  142                 return (NULL);
  143         }
  144         reconCtrlPtr->eventQueue = NULL;
  145         reconCtrlPtr->eq_count = 0;
  146 
  147         /* Make the floating recon buffers and append them to the free list. */
  148         rc = rf_mutex_init(&reconCtrlPtr->rb_mutex);
  149         if (rc) {
  150                 /* XXX Deallocate, cleanup. */
  151                 RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d.\n",
  152                     __FILE__, __LINE__, rc);
  153                 return (NULL);
  154         }
  155         reconCtrlPtr->fullBufferList = NULL;
  156         reconCtrlPtr->priorityList = NULL;
  157         reconCtrlPtr->floatingRbufs = NULL;
  158         reconCtrlPtr->committedRbufs = NULL;
  159         for (i = 0; i < raidPtr->numFloatingReconBufs; i++) {
  160                 rbuf = rf_MakeReconBuffer(raidPtr, frow, fcol,
  161                     RF_RBUF_TYPE_FLOATING);
  162                 rbuf->next = reconCtrlPtr->floatingRbufs;
  163                 reconCtrlPtr->floatingRbufs = rbuf;
  164         }
  165 
  166         /* Create the parity stripe status table. */
  167         reconCtrlPtr->pssTable = rf_MakeParityStripeStatusTable(raidPtr);
  168 
  169         /* Set the initial min head sep counter val. */
  170         reconCtrlPtr->minHeadSepCounter = 0;
  171 
  172         return (reconCtrlPtr);
  173 }
  174 
  175 void
  176 rf_FreeReconControl(RF_Raid_t *raidPtr, RF_RowCol_t row)
  177 {
  178         RF_ReconCtrl_t *reconCtrlPtr = raidPtr->reconControl[row];
  179         RF_ReconBuffer_t *t;
  180         RF_ReconUnitNum_t i;
  181 
  182         RF_ASSERT(reconCtrlPtr);
  183         for (i = 0; i < raidPtr->numCol; i++)
  184                 if (reconCtrlPtr->perDiskInfo[i].rbuf)
  185                         rf_FreeReconBuffer(reconCtrlPtr->perDiskInfo[i].rbuf);
  186         for (i = 0; i < raidPtr->numFloatingReconBufs; i++) {
  187                 t = reconCtrlPtr->floatingRbufs;
  188                 RF_ASSERT(t);
  189                 reconCtrlPtr->floatingRbufs = t->next;
  190                 rf_FreeReconBuffer(t);
  191         }
  192         rf_mutex_destroy(&reconCtrlPtr->rb_mutex);
  193         rf_mutex_destroy(&reconCtrlPtr->eq_mutex);
  194         rf_cond_destroy(&reconCtrlPtr->eq_cond);
  195         rf_FreeReconMap(reconCtrlPtr->reconMap);
  196         rf_FreeParityStripeStatusTable(raidPtr, reconCtrlPtr->pssTable);
  197         RF_Free(reconCtrlPtr->perDiskInfo, raidPtr->numCol *
  198             sizeof(RF_PerDiskReconCtrl_t));
  199         RF_Free(reconCtrlPtr, sizeof(*reconCtrlPtr));
  200 }
  201 
  202 
  203 /*****************************************************************************
  204  * Computes the default head separation limit.
  205  *****************************************************************************/
  206 RF_HeadSepLimit_t
  207 rf_GetDefaultHeadSepLimit(RF_Raid_t *raidPtr)
  208 {
  209         RF_HeadSepLimit_t hsl;
  210         RF_LayoutSW_t *lp;
  211 
  212         lp = raidPtr->Layout.map;
  213         if (lp->GetDefaultHeadSepLimit == NULL)
  214                 return (-1);
  215         hsl = lp->GetDefaultHeadSepLimit(raidPtr);
  216         return (hsl);
  217 }
  218 
  219 
  220 /*****************************************************************************
  221  * Computes the default number of floating recon buffers.
  222  *****************************************************************************/
  223 int
  224 rf_GetDefaultNumFloatingReconBuffers(RF_Raid_t *raidPtr)
  225 {
  226         RF_LayoutSW_t *lp;
  227         int nrb;
  228 
  229         lp = raidPtr->Layout.map;
  230         if (lp->GetDefaultNumFloatingReconBuffers == NULL)
  231                 return (3 * raidPtr->numCol);
  232         nrb = lp->GetDefaultNumFloatingReconBuffers(raidPtr);
  233         return (nrb);
  234 }
  235 
  236 
  237 /*****************************************************************************
  238  * Creates and initializes a reconstruction buffer.
  239  *****************************************************************************/
  240 RF_ReconBuffer_t *
  241 rf_MakeReconBuffer(RF_Raid_t *raidPtr, RF_RowCol_t row, RF_RowCol_t col,
  242     RF_RbufType_t type)
  243 {
  244         RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
  245         RF_ReconBuffer_t *t;
  246         u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr,
  247             layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit);
  248 
  249         RF_Malloc(t, sizeof(RF_ReconBuffer_t), (RF_ReconBuffer_t *));
  250         RF_Malloc(t->buffer, recon_buffer_size, (caddr_t));
  251         RF_Malloc(t->arrived, raidPtr->numCol * sizeof(char), (char *));
  252         t->raidPtr = raidPtr;
  253         t->row = row;
  254         t->col = col;
  255         t->priority = RF_IO_RECON_PRIORITY;
  256         t->type = type;
  257         t->pssPtr = NULL;
  258         t->next = NULL;
  259         return (t);
  260 }
  261 
  262 
  263 /*****************************************************************************
  264  * Frees a reconstruction buffer.
  265  *****************************************************************************/
  266 void
  267 rf_FreeReconBuffer(RF_ReconBuffer_t *rbuf)
  268 {
  269         RF_Raid_t *raidPtr = rbuf->raidPtr;
  270         u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr,
  271             raidPtr->Layout.SUsPerRU * raidPtr->Layout.sectorsPerStripeUnit);
  272 
  273         RF_Free(rbuf->arrived, raidPtr->numCol * sizeof(char));
  274         RF_Free(rbuf->buffer, recon_buffer_size);
  275         RF_Free(rbuf, sizeof(*rbuf));
  276 }
  277 
  278 
  279 /*****************************************************************************
  280  * Debug only:  Sanity check the number of floating recon bufs in use.
  281  *****************************************************************************/
  282 void
  283 rf_CheckFloatingRbufCount(RF_Raid_t *raidPtr, int dolock)
  284 {
  285         RF_ReconParityStripeStatus_t *p;
  286         RF_PSStatusHeader_t *pssTable;
  287         RF_ReconBuffer_t *rbuf;
  288         int i, j, sum = 0;
  289         RF_RowCol_t frow = 0;
  290 
  291         for (i = 0; i < raidPtr->numRow; i++)
  292                 if (raidPtr->reconControl[i]) {
  293                         frow = i;
  294                         break;
  295                 }
  296         RF_ASSERT(frow >= 0);
  297 
  298         if (dolock)
  299                 RF_LOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex);
  300         pssTable = raidPtr->reconControl[frow]->pssTable;
  301 
  302         for (i = 0; i < raidPtr->pssTableSize; i++) {
  303                 RF_LOCK_MUTEX(pssTable[i].mutex);
  304                 for (p = pssTable[i].chain; p; p = p->next) {
  305                         rbuf = (RF_ReconBuffer_t *) p->rbuf;
  306                         if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING)
  307                                 sum++;
  308 
  309                         rbuf = (RF_ReconBuffer_t *) p->writeRbuf;
  310                         if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING)
  311                                 sum++;
  312 
  313                         for (j = 0; j < p->xorBufCount; j++) {
  314                                 rbuf = (RF_ReconBuffer_t *) p->rbufsForXor[j];
  315                                 RF_ASSERT(rbuf);
  316                                 if (rbuf->type == RF_RBUF_TYPE_FLOATING)
  317                                         sum++;
  318                         }
  319                 }
  320                 RF_UNLOCK_MUTEX(pssTable[i].mutex);
  321         }
  322 
  323         for (rbuf = raidPtr->reconControl[frow]->floatingRbufs; rbuf;
  324              rbuf = rbuf->next) {
  325                 if (rbuf->type == RF_RBUF_TYPE_FLOATING)
  326                         sum++;
  327         }
  328         for (rbuf = raidPtr->reconControl[frow]->committedRbufs; rbuf;
  329              rbuf = rbuf->next) {
  330                 if (rbuf->type == RF_RBUF_TYPE_FLOATING)
  331                         sum++;
  332         }
  333         for (rbuf = raidPtr->reconControl[frow]->fullBufferList; rbuf;
  334              rbuf = rbuf->next) {
  335                 if (rbuf->type == RF_RBUF_TYPE_FLOATING)
  336                         sum++;
  337         }
  338         for (rbuf = raidPtr->reconControl[frow]->priorityList; rbuf;
  339              rbuf = rbuf->next) {
  340                 if (rbuf->type == RF_RBUF_TYPE_FLOATING)
  341                         sum++;
  342         }
  343 
  344         RF_ASSERT(sum == raidPtr->numFloatingReconBufs);
  345 
  346         if (dolock)
  347                 RF_UNLOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex);
  348 }

/* [<][>][^][v][top][bottom][index][help] */