The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/raidframe/rf_raid1.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: rf_raid1.c,v 1.24 2004/03/18 16:54:54 oster Exp $      */
    2 /*
    3  * Copyright (c) 1995 Carnegie-Mellon University.
    4  * All rights reserved.
    5  *
    6  * Author: William V. Courtright II
    7  *
    8  * Permission to use, copy, modify and distribute this software and
    9  * its documentation is hereby granted, provided that both the copyright
   10  * notice and this permission notice appear in all copies of the
   11  * software, derivative works or modified versions, and any portions
   12  * thereof, and that both notices appear in supporting documentation.
   13  *
   14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
   16  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  *
   18  * Carnegie Mellon requests users of this software to return to
   19  *
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  *
   25  * any improvements or extensions that they make and grant Carnegie the
   26  * rights to redistribute these changes.
   27  */
   28 
   29 /*****************************************************************************
   30  *
   31  * rf_raid1.c -- implements RAID Level 1
   32  *
   33  *****************************************************************************/
   34 
   35 #include <sys/cdefs.h>
   36 __KERNEL_RCSID(0, "$NetBSD: rf_raid1.c,v 1.24 2004/03/18 16:54:54 oster Exp $");
   37 
   38 #include "rf_raid.h"
   39 #include "rf_raid1.h"
   40 #include "rf_dag.h"
   41 #include "rf_dagffrd.h"
   42 #include "rf_dagffwr.h"
   43 #include "rf_dagdegrd.h"
   44 #include "rf_dagutils.h"
   45 #include "rf_dagfuncs.h"
   46 #include "rf_diskqueue.h"
   47 #include "rf_general.h"
   48 #include "rf_utils.h"
   49 #include "rf_parityscan.h"
   50 #include "rf_mcpair.h"
   51 #include "rf_layout.h"
   52 #include "rf_map.h"
   53 #include "rf_engine.h"
   54 #include "rf_reconbuffer.h"
   55 
   56 typedef struct RF_Raid1ConfigInfo_s {
   57         RF_RowCol_t **stripeIdentifier;
   58 }       RF_Raid1ConfigInfo_t;
   59 /* start of day code specific to RAID level 1 */
   60 int 
   61 rf_ConfigureRAID1(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
   62                   RF_Config_t *cfgPtr)
   63 {
   64         RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
   65         RF_Raid1ConfigInfo_t *info;
   66         RF_RowCol_t i;
   67 
   68         /* create a RAID level 1 configuration structure */
   69         RF_MallocAndAdd(info, sizeof(RF_Raid1ConfigInfo_t), (RF_Raid1ConfigInfo_t *), raidPtr->cleanupList);
   70         if (info == NULL)
   71                 return (ENOMEM);
   72         layoutPtr->layoutSpecificInfo = (void *) info;
   73 
   74         /* ... and fill it in. */
   75         info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol / 2, 2, raidPtr->cleanupList);
   76         if (info->stripeIdentifier == NULL)
   77                 return (ENOMEM);
   78         for (i = 0; i < (raidPtr->numCol / 2); i++) {
   79                 info->stripeIdentifier[i][0] = (2 * i);
   80                 info->stripeIdentifier[i][1] = (2 * i) + 1;
   81         }
   82 
   83         /* this implementation of RAID level 1 uses one row of numCol disks
   84          * and allows multiple (numCol / 2) stripes per row.  A stripe
   85          * consists of a single data unit and a single parity (mirror) unit.
   86          * stripe id = raidAddr / stripeUnitSize */
   87         raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * (raidPtr->numCol / 2) * layoutPtr->sectorsPerStripeUnit;
   88         layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk * (raidPtr->numCol / 2);
   89         layoutPtr->dataSectorsPerStripe = layoutPtr->sectorsPerStripeUnit;
   90         layoutPtr->numDataCol = 1;
   91         layoutPtr->numParityCol = 1;
   92         return (0);
   93 }
   94 
   95 
   96 /* returns the physical disk location of the primary copy in the mirror pair */
   97 void 
   98 rf_MapSectorRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
   99                   RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
  100 {
  101         RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
  102         RF_RowCol_t mirrorPair = SUID % (raidPtr->numCol / 2);
  103 
  104         *col = 2 * mirrorPair;
  105         *diskSector = ((SUID / (raidPtr->numCol / 2)) * raidPtr->Layout.sectorsPerStripeUnit) + (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
  106 }
  107 
  108 
  109 /* Map Parity
  110  *
  111  * returns the physical disk location of the secondary copy in the mirror
  112  * pair
  113  */
  114 void 
  115 rf_MapParityRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
  116                   RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
  117 {
  118         RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
  119         RF_RowCol_t mirrorPair = SUID % (raidPtr->numCol / 2);
  120 
  121         *col = (2 * mirrorPair) + 1;
  122 
  123         *diskSector = ((SUID / (raidPtr->numCol / 2)) * raidPtr->Layout.sectorsPerStripeUnit) + (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
  124 }
  125 
  126 
  127 /* IdentifyStripeRAID1
  128  *
  129  * returns a list of disks for a given redundancy group
  130  */
  131 void 
  132 rf_IdentifyStripeRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
  133                        RF_RowCol_t **diskids)
  134 {
  135         RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr);
  136         RF_Raid1ConfigInfo_t *info = raidPtr->Layout.layoutSpecificInfo;
  137         RF_ASSERT(stripeID >= 0);
  138         RF_ASSERT(addr >= 0);
  139         *diskids = info->stripeIdentifier[stripeID % (raidPtr->numCol / 2)];
  140         RF_ASSERT(*diskids);
  141 }
  142 
  143 
  144 /* MapSIDToPSIDRAID1
  145  *
  146  * maps a logical stripe to a stripe in the redundant array
  147  */
  148 void 
  149 rf_MapSIDToPSIDRAID1(RF_RaidLayout_t *layoutPtr, RF_StripeNum_t stripeID,
  150                      RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
  151 {
  152         *which_ru = 0;
  153         *psID = stripeID;
  154 }
  155 
  156 
  157 
  158 /******************************************************************************
  159  * select a graph to perform a single-stripe access
  160  *
  161  * Parameters:  raidPtr    - description of the physical array
  162  *              type       - type of operation (read or write) requested
  163  *              asmap      - logical & physical addresses for this access
  164  *              createFunc - name of function to use to create the graph
  165  *****************************************************************************/
  166 
  167 void 
  168 rf_RAID1DagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
  169                   RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
  170 {
  171         RF_RowCol_t fcol, oc;
  172         RF_PhysDiskAddr_t *failedPDA;
  173         int     prior_recon;
  174         RF_RowStatus_t rstat;
  175         RF_SectorNum_t oo;
  176 
  177 
  178         RF_ASSERT(RF_IO_IS_R_OR_W(type));
  179 
  180         if (asmap->numDataFailed + asmap->numParityFailed > 1) {
  181 #if RF_DEBUG_DAG
  182                 if (rf_dagDebug) 
  183                         RF_ERRORMSG("Multiple disks failed in a single group!  Aborting I/O operation.\n");
  184 #endif
  185                 *createFunc = NULL;
  186                 return;
  187         }
  188         if (asmap->numDataFailed + asmap->numParityFailed) {
  189                 /*
  190                  * We've got a fault. Re-map to spare space, iff applicable.
  191                  * Shouldn't the arch-independent code do this for us?
  192                  * Anyway, it turns out if we don't do this here, then when
  193                  * we're reconstructing, writes go only to the surviving
  194                  * original disk, and aren't reflected on the reconstructed
  195                  * spare. Oops. --jimz
  196                  */
  197                 failedPDA = asmap->failedPDAs[0];
  198                 fcol = failedPDA->col;
  199                 rstat = raidPtr->status;
  200                 prior_recon = (rstat == rf_rs_reconfigured) || (
  201                     (rstat == rf_rs_reconstructing) ?
  202                     rf_CheckRUReconstructed(raidPtr->reconControl->reconMap, failedPDA->startSector) : 0
  203                     );
  204                 if (prior_recon) {
  205                         oc = fcol;
  206                         oo = failedPDA->startSector;
  207                         /*
  208                          * If we did distributed sparing, we'd monkey with that here.
  209                          * But we don't, so we'll
  210                          */
  211                         failedPDA->col = raidPtr->Disks[fcol].spareCol;
  212                         /*
  213                          * Redirect other components, iff necessary. This looks
  214                          * pretty suspicious to me, but it's what the raid5
  215                          * DAG select does.
  216                          */
  217                         if (asmap->parityInfo->next) {
  218                                 if (failedPDA == asmap->parityInfo) {
  219                                         failedPDA->next->col = failedPDA->col;
  220                                 } else {
  221                                         if (failedPDA == asmap->parityInfo->next) {
  222                                                 asmap->parityInfo->col = failedPDA->col;
  223                                         }
  224                                 }
  225                         }
  226 #if RF_DEBUG_DAG > 0 || RF_DEBUG_MAP > 0
  227                         if (rf_dagDebug || rf_mapDebug) {
  228                                 printf("raid%d: Redirected type '%c' c %d o %ld -> c %d o %ld\n",
  229                                        raidPtr->raidid, type, oc, 
  230                                        (long) oo, 
  231                                        failedPDA->col,
  232                                        (long) failedPDA->startSector);
  233                         }
  234 #endif
  235                         asmap->numDataFailed = asmap->numParityFailed = 0;
  236                 }
  237         }
  238         if (type == RF_IO_TYPE_READ) {
  239                 if (asmap->numDataFailed == 0)
  240                         *createFunc = (RF_VoidFuncPtr) rf_CreateMirrorIdleReadDAG;
  241                 else
  242                         *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneDegradedReadDAG;
  243         } else {
  244                 *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
  245         }
  246 }
  247 
  248 int 
  249 rf_VerifyParityRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidAddr,
  250                      RF_PhysDiskAddr_t *parityPDA, int correct_it,
  251                      RF_RaidAccessFlags_t flags)
  252 {
  253         int     nbytes, bcount, stripeWidth, ret, i, j, nbad, *bbufs;
  254         RF_DagNode_t *blockNode, *wrBlock;
  255         RF_DagHeader_t *rd_dag_h, *wr_dag_h;
  256         RF_AccessStripeMapHeader_t *asm_h;
  257         RF_AllocListElem_t *allocList;
  258 #if RF_ACC_TRACE > 0
  259         RF_AccTraceEntry_t tracerec;
  260 #endif
  261         RF_ReconUnitNum_t which_ru;
  262         RF_RaidLayout_t *layoutPtr;
  263         RF_AccessStripeMap_t *aasm;
  264         RF_SectorCount_t nsector;
  265         RF_RaidAddr_t startAddr;
  266         char   *buf, *buf1, *buf2;
  267         RF_PhysDiskAddr_t *pda;
  268         RF_StripeNum_t psID;
  269         RF_MCPair_t *mcpair;
  270 
  271         layoutPtr = &raidPtr->Layout;
  272         startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
  273         nsector = parityPDA->numSector;
  274         nbytes = rf_RaidAddressToByte(raidPtr, nsector);
  275         psID = rf_RaidAddressToParityStripeID(layoutPtr, raidAddr, &which_ru);
  276 
  277         asm_h = NULL;
  278         rd_dag_h = wr_dag_h = NULL;
  279         mcpair = NULL;
  280 
  281         ret = RF_PARITY_COULD_NOT_VERIFY;
  282 
  283         rf_MakeAllocList(allocList);
  284         if (allocList == NULL)
  285                 return (RF_PARITY_COULD_NOT_VERIFY);
  286         mcpair = rf_AllocMCPair();
  287         if (mcpair == NULL)
  288                 goto done;
  289         RF_ASSERT(layoutPtr->numDataCol == layoutPtr->numParityCol);
  290         stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
  291         bcount = nbytes * (layoutPtr->numDataCol + layoutPtr->numParityCol);
  292         RF_MallocAndAdd(buf, bcount, (char *), allocList);
  293         if (buf == NULL)
  294                 goto done;
  295 #if RF_DEBUG_VERIFYPARITY
  296         if (rf_verifyParityDebug) {
  297                 printf("raid%d: RAID1 parity verify: buf=%lx bcount=%d (%lx - %lx)\n",
  298                        raidPtr->raidid, (long) buf, bcount, (long) buf, 
  299                        (long) buf + bcount);
  300         }
  301 #endif
  302         /*
  303          * Generate a DAG which will read the entire stripe- then we can
  304          * just compare data chunks versus "parity" chunks.
  305          */
  306 
  307         rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, nbytes, buf,
  308             rf_DiskReadFunc, rf_DiskReadUndoFunc, "Rod", allocList, flags,
  309             RF_IO_NORMAL_PRIORITY);
  310         if (rd_dag_h == NULL)
  311                 goto done;
  312         blockNode = rd_dag_h->succedents[0];
  313 
  314         /*
  315          * Map the access to physical disk addresses (PDAs)- this will
  316          * get us both a list of data addresses, and "parity" addresses
  317          * (which are really mirror copies).
  318          */
  319         asm_h = rf_MapAccess(raidPtr, startAddr, layoutPtr->dataSectorsPerStripe,
  320             buf, RF_DONT_REMAP);
  321         aasm = asm_h->stripeMap;
  322 
  323         buf1 = buf;
  324         /*
  325          * Loop through the data blocks, setting up read nodes for each.
  326          */
  327         for (pda = aasm->physInfo, i = 0; i < layoutPtr->numDataCol; i++, pda = pda->next) {
  328                 RF_ASSERT(pda);
  329 
  330                 rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
  331 
  332                 RF_ASSERT(pda->numSector != 0);
  333                 if (rf_TryToRedirectPDA(raidPtr, pda, 0)) {
  334                         /* cannot verify parity with dead disk */
  335                         goto done;
  336                 }
  337                 pda->bufPtr = buf1;
  338                 blockNode->succedents[i]->params[0].p = pda;
  339                 blockNode->succedents[i]->params[1].p = buf1;
  340                 blockNode->succedents[i]->params[2].v = psID;
  341                 blockNode->succedents[i]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, which_ru);
  342                 buf1 += nbytes;
  343         }
  344         RF_ASSERT(pda == NULL);
  345         /*
  346          * keep i, buf1 running
  347          *
  348          * Loop through parity blocks, setting up read nodes for each.
  349          */
  350         for (pda = aasm->parityInfo; i < layoutPtr->numDataCol + layoutPtr->numParityCol; i++, pda = pda->next) {
  351                 RF_ASSERT(pda);
  352                 rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
  353                 RF_ASSERT(pda->numSector != 0);
  354                 if (rf_TryToRedirectPDA(raidPtr, pda, 0)) {
  355                         /* cannot verify parity with dead disk */
  356                         goto done;
  357                 }
  358                 pda->bufPtr = buf1;
  359                 blockNode->succedents[i]->params[0].p = pda;
  360                 blockNode->succedents[i]->params[1].p = buf1;
  361                 blockNode->succedents[i]->params[2].v = psID;
  362                 blockNode->succedents[i]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, which_ru);
  363                 buf1 += nbytes;
  364         }
  365         RF_ASSERT(pda == NULL);
  366 
  367 #if RF_ACC_TRACE > 0
  368         memset((char *) &tracerec, 0, sizeof(tracerec));
  369         rd_dag_h->tracerec = &tracerec;
  370 #endif
  371 #if 0
  372         if (rf_verifyParityDebug > 1) {
  373                 printf("raid%d: RAID1 parity verify read dag:\n", 
  374                        raidPtr->raidid);
  375                 rf_PrintDAGList(rd_dag_h);
  376         }
  377 #endif
  378         RF_LOCK_MUTEX(mcpair->mutex);
  379         mcpair->flag = 0;
  380         RF_UNLOCK_MUTEX(mcpair->mutex);
  381 
  382         rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
  383             (void *) mcpair);
  384 
  385         RF_LOCK_MUTEX(mcpair->mutex);
  386         while (mcpair->flag == 0) {
  387                 RF_WAIT_MCPAIR(mcpair);
  388         }
  389         RF_UNLOCK_MUTEX(mcpair->mutex);
  390 
  391         if (rd_dag_h->status != rf_enable) {
  392                 RF_ERRORMSG("Unable to verify raid1 parity: can't read stripe\n");
  393                 ret = RF_PARITY_COULD_NOT_VERIFY;
  394                 goto done;
  395         }
  396         /*
  397          * buf1 is the beginning of the data blocks chunk
  398          * buf2 is the beginning of the parity blocks chunk
  399          */
  400         buf1 = buf;
  401         buf2 = buf + (nbytes * layoutPtr->numDataCol);
  402         ret = RF_PARITY_OKAY;
  403         /*
  404          * bbufs is "bad bufs"- an array whose entries are the data
  405          * column numbers where we had miscompares. (That is, column 0
  406          * and column 1 of the array are mirror copies, and are considered
  407          * "data column 0" for this purpose).
  408          */
  409         RF_MallocAndAdd(bbufs, layoutPtr->numParityCol * sizeof(int), (int *),
  410             allocList);
  411         nbad = 0;
  412         /*
  413          * Check data vs "parity" (mirror copy).
  414          */
  415         for (i = 0; i < layoutPtr->numDataCol; i++) {
  416 #if RF_DEBUG_VERIFYPARITY
  417                 if (rf_verifyParityDebug) {
  418                         printf("raid%d: RAID1 parity verify %d bytes: i=%d buf1=%lx buf2=%lx buf=%lx\n",
  419                                raidPtr->raidid, nbytes, i, (long) buf1, 
  420                                (long) buf2, (long) buf);
  421                 }
  422 #endif
  423                 ret = memcmp(buf1, buf2, nbytes);
  424                 if (ret) {
  425 #if RF_DEBUG_VERIFYPARITY
  426                         if (rf_verifyParityDebug > 1) {
  427                                 for (j = 0; j < nbytes; j++) {
  428                                         if (buf1[j] != buf2[j])
  429                                                 break;
  430                                 }
  431                                 printf("psid=%ld j=%d\n", (long) psID, j);
  432                                 printf("buf1 %02x %02x %02x %02x %02x\n", buf1[0] & 0xff,
  433                                     buf1[1] & 0xff, buf1[2] & 0xff, buf1[3] & 0xff, buf1[4] & 0xff);
  434                                 printf("buf2 %02x %02x %02x %02x %02x\n", buf2[0] & 0xff,
  435                                     buf2[1] & 0xff, buf2[2] & 0xff, buf2[3] & 0xff, buf2[4] & 0xff);
  436                         }
  437                         if (rf_verifyParityDebug) {
  438                                 printf("raid%d: RAID1: found bad parity, i=%d\n", raidPtr->raidid, i);
  439                         }
  440 #endif
  441                         /*
  442                          * Parity is bad. Keep track of which columns were bad.
  443                          */
  444                         if (bbufs)
  445                                 bbufs[nbad] = i;
  446                         nbad++;
  447                         ret = RF_PARITY_BAD;
  448                 }
  449                 buf1 += nbytes;
  450                 buf2 += nbytes;
  451         }
  452 
  453         if ((ret != RF_PARITY_OKAY) && correct_it) {
  454                 ret = RF_PARITY_COULD_NOT_CORRECT;
  455 #if RF_DEBUG_VERIFYPARITY
  456                 if (rf_verifyParityDebug) {
  457                         printf("raid%d: RAID1 parity verify: parity not correct\n", raidPtr->raidid);
  458                 }
  459 #endif
  460                 if (bbufs == NULL)
  461                         goto done;
  462                 /*
  463                  * Make a DAG with one write node for each bad unit. We'll simply
  464                  * write the contents of the data unit onto the parity unit for
  465                  * correction. (It's possible that the mirror copy was the correct
  466                  * copy, and that we're spooging good data by writing bad over it,
  467                  * but there's no way we can know that.
  468                  */
  469                 wr_dag_h = rf_MakeSimpleDAG(raidPtr, nbad, nbytes, buf,
  470                     rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wnp", allocList, flags,
  471                     RF_IO_NORMAL_PRIORITY);
  472                 if (wr_dag_h == NULL)
  473                         goto done;
  474                 wrBlock = wr_dag_h->succedents[0];
  475                 /*
  476                  * Fill in a write node for each bad compare.
  477                  */
  478                 for (i = 0; i < nbad; i++) {
  479                         j = i + layoutPtr->numDataCol;
  480                         pda = blockNode->succedents[j]->params[0].p;
  481                         pda->bufPtr = blockNode->succedents[i]->params[1].p;
  482                         wrBlock->succedents[i]->params[0].p = pda;
  483                         wrBlock->succedents[i]->params[1].p = pda->bufPtr;
  484                         wrBlock->succedents[i]->params[2].v = psID;
  485                         wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, which_ru);
  486                 }
  487 #if RF_ACC_TRACE > 0
  488                 memset((char *) &tracerec, 0, sizeof(tracerec));
  489                 wr_dag_h->tracerec = &tracerec;
  490 #endif
  491 #if 0
  492                 if (rf_verifyParityDebug > 1) {
  493                         printf("Parity verify write dag:\n");
  494                         rf_PrintDAGList(wr_dag_h);
  495                 }
  496 #endif
  497                 RF_LOCK_MUTEX(mcpair->mutex);
  498                 mcpair->flag = 0;
  499                 RF_UNLOCK_MUTEX(mcpair->mutex);
  500 
  501                 /* fire off the write DAG */
  502                 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
  503                     (void *) mcpair);
  504 
  505                 RF_LOCK_MUTEX(mcpair->mutex);
  506                 while (!mcpair->flag) {
  507                         RF_WAIT_COND(mcpair->cond, mcpair->mutex);
  508                 }
  509                 RF_UNLOCK_MUTEX(mcpair->mutex);
  510                 if (wr_dag_h->status != rf_enable) {
  511                         RF_ERRORMSG("Unable to correct RAID1 parity in VerifyParity\n");
  512                         goto done;
  513                 }
  514                 ret = RF_PARITY_CORRECTED;
  515         }
  516 done:
  517         /*
  518          * All done. We might've gotten here without doing part of the function,
  519          * so cleanup what we have to and return our running status.
  520          */
  521         if (asm_h)
  522                 rf_FreeAccessStripeMap(asm_h);
  523         if (rd_dag_h)
  524                 rf_FreeDAG(rd_dag_h);
  525         if (wr_dag_h)
  526                 rf_FreeDAG(wr_dag_h);
  527         if (mcpair)
  528                 rf_FreeMCPair(mcpair);
  529         rf_FreeAllocList(allocList);
  530 #if RF_DEBUG_VERIFYPARITY
  531         if (rf_verifyParityDebug) {
  532                 printf("raid%d: RAID1 parity verify, returning %d\n", 
  533                        raidPtr->raidid, ret);
  534         }
  535 #endif
  536         return (ret);
  537 }
  538 
  539 /* rbuf          - the recon buffer to submit 
  540  * keep_it       - whether we can keep this buffer or we have to return it
  541  * use_committed - whether to use a committed or an available recon buffer
  542  */
  543 
  544 int 
  545 rf_SubmitReconBufferRAID1(RF_ReconBuffer_t *rbuf, int keep_it,
  546                           int use_committed)
  547 {
  548         RF_ReconParityStripeStatus_t *pssPtr;
  549         RF_ReconCtrl_t *reconCtrlPtr;
  550         int     retcode;
  551         RF_CallbackDesc_t *cb, *p;
  552         RF_ReconBuffer_t *t;
  553         RF_Raid_t *raidPtr;
  554         caddr_t ta;
  555 
  556         retcode = 0;
  557 
  558         raidPtr = rbuf->raidPtr;
  559         reconCtrlPtr = raidPtr->reconControl;
  560 
  561         RF_ASSERT(rbuf);
  562         RF_ASSERT(rbuf->col != reconCtrlPtr->fcol);
  563 
  564 #if RF_DEBUG_RECON
  565         if (rf_reconbufferDebug) {
  566                 printf("raid%d: RAID1 reconbuffer submission c%d psid %ld ru%d (failed offset %ld)\n",
  567                        raidPtr->raidid, rbuf->col, 
  568                        (long) rbuf->parityStripeID, rbuf->which_ru,
  569                        (long) rbuf->failedDiskSectorOffset);
  570         }
  571 #endif
  572         if (rf_reconDebug) {
  573                 printf("RAID1 reconbuffer submit psid %ld buf %lx\n",
  574                     (long) rbuf->parityStripeID, (long) rbuf->buffer);
  575                 printf("RAID1 psid %ld   %02x %02x %02x %02x %02x\n",
  576                     (long) rbuf->parityStripeID,
  577                     rbuf->buffer[0], rbuf->buffer[1], rbuf->buffer[2], rbuf->buffer[3],
  578                     rbuf->buffer[4]);
  579         }
  580         RF_LOCK_PSS_MUTEX(raidPtr, rbuf->parityStripeID);
  581 
  582         RF_LOCK_MUTEX(reconCtrlPtr->rb_mutex);
  583         while(reconCtrlPtr->rb_lock) {
  584                 ltsleep(&reconCtrlPtr->rb_lock, PRIBIO, "reconctlcnmhs", 0, &reconCtrlPtr->rb_mutex);
  585         }
  586         reconCtrlPtr->rb_lock = 1;
  587         RF_UNLOCK_MUTEX(reconCtrlPtr->rb_mutex);
  588 
  589         pssPtr = rf_LookupRUStatus(raidPtr, reconCtrlPtr->pssTable,
  590             rbuf->parityStripeID, rbuf->which_ru, RF_PSS_NONE, NULL);
  591         RF_ASSERT(pssPtr);      /* if it didn't exist, we wouldn't have gotten
  592                                  * an rbuf for it */
  593 
  594         /*
  595          * Since this is simple mirroring, the first submission for a stripe is also
  596          * treated as the last.
  597          */
  598 
  599         t = NULL;
  600         if (keep_it) {
  601 #if RF_DEBUG_RECON
  602                 if (rf_reconbufferDebug) {
  603                         printf("raid%d: RAID1 rbuf submission: keeping rbuf\n", 
  604                                raidPtr->raidid);
  605                 }
  606 #endif
  607                 t = rbuf;
  608         } else {
  609                 if (use_committed) {
  610 #if RF_DEBUG_RECON
  611                         if (rf_reconbufferDebug) {
  612                                 printf("raid%d: RAID1 rbuf submission: using committed rbuf\n", raidPtr->raidid);
  613                         }
  614 #endif
  615                         t = reconCtrlPtr->committedRbufs;
  616                         RF_ASSERT(t);
  617                         reconCtrlPtr->committedRbufs = t->next;
  618                         t->next = NULL;
  619                 } else
  620                         if (reconCtrlPtr->floatingRbufs) {
  621 #if RF_DEBUG_RECON
  622                                 if (rf_reconbufferDebug) {
  623                                         printf("raid%d: RAID1 rbuf submission: using floating rbuf\n", raidPtr->raidid);
  624                                 }
  625 #endif
  626                                 t = reconCtrlPtr->floatingRbufs;
  627                                 reconCtrlPtr->floatingRbufs = t->next;
  628                                 t->next = NULL;
  629                         }
  630         }
  631         if (t == NULL) {
  632 #if RF_DEBUG_RECON
  633                 if (rf_reconbufferDebug) {
  634                         printf("raid%d: RAID1 rbuf submission: waiting for rbuf\n", raidPtr->raidid);
  635                 }
  636 #endif
  637                 RF_ASSERT((keep_it == 0) && (use_committed == 0));
  638                 raidPtr->procsInBufWait++;
  639                 if ((raidPtr->procsInBufWait == (raidPtr->numCol - 1))
  640                     && (raidPtr->numFullReconBuffers == 0)) {
  641                         /* ruh-ro */
  642                         RF_ERRORMSG("Buffer wait deadlock\n");
  643                         rf_PrintPSStatusTable(raidPtr);
  644                         RF_PANIC();
  645                 }
  646                 pssPtr->flags |= RF_PSS_BUFFERWAIT;
  647                 cb = rf_AllocCallbackDesc();
  648                 cb->col = rbuf->col;
  649                 cb->callbackArg.v = rbuf->parityStripeID;
  650                 cb->next = NULL;
  651                 if (reconCtrlPtr->bufferWaitList == NULL) {
  652                         /* we are the wait list- lucky us */
  653                         reconCtrlPtr->bufferWaitList = cb;
  654                 } else {
  655                         /* append to wait list */
  656                         for (p = reconCtrlPtr->bufferWaitList; p->next; p = p->next);
  657                         p->next = cb;
  658                 }
  659                 retcode = 1;
  660                 goto out;
  661         }
  662         if (t != rbuf) {
  663                 t->col = reconCtrlPtr->fcol;
  664                 t->parityStripeID = rbuf->parityStripeID;
  665                 t->which_ru = rbuf->which_ru;
  666                 t->failedDiskSectorOffset = rbuf->failedDiskSectorOffset;
  667                 t->spCol = rbuf->spCol;
  668                 t->spOffset = rbuf->spOffset;
  669                 /* Swap buffers. DANCE! */
  670                 ta = t->buffer;
  671                 t->buffer = rbuf->buffer;
  672                 rbuf->buffer = ta;
  673         }
  674         /*
  675          * Use the rbuf we've been given as the target.
  676          */
  677         RF_ASSERT(pssPtr->rbuf == NULL);
  678         pssPtr->rbuf = t;
  679 
  680         t->count = 1;
  681         /*
  682          * Below, we use 1 for numDataCol (which is equal to the count in the
  683          * previous line), so we'll always be done.
  684          */
  685         rf_CheckForFullRbuf(raidPtr, reconCtrlPtr, pssPtr, 1);
  686 
  687 out:
  688         RF_UNLOCK_PSS_MUTEX(raidPtr, rbuf->parityStripeID);
  689         RF_LOCK_MUTEX(reconCtrlPtr->rb_mutex);
  690         reconCtrlPtr->rb_lock = 0;
  691         wakeup(&reconCtrlPtr->rb_lock);
  692         RF_UNLOCK_MUTEX(reconCtrlPtr->rb_mutex);
  693 #if RF_DEBUG_RECON
  694         if (rf_reconbufferDebug) {
  695                 printf("raid%d: RAID1 rbuf submission: returning %d\n", 
  696                        raidPtr->raidid, retcode);
  697         }
  698 #endif
  699         return (retcode);
  700 }

Cache object: 4e9c80ea045f26c19a95cc9febcaac94


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.