root/dev/raidframe/rf_evenodd.c

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

DEFINITIONS

This source file includes following definitions.
  1. RF_EvenOddConfigInfo_t
  2. rf_ConfigureEvenOdd
  3. rf_GetDefaultNumFloatingReconBuffersEvenOdd
  4. rf_GetDefaultHeadSepLimitEvenOdd
  5. rf_IdentifyStripeEvenOdd
  6. rf_MapParityEvenOdd
  7. rf_MapEEvenOdd
  8. rf_EODagSelect
  9. rf_VerifyParityEvenOdd

    1 /*      $OpenBSD: rf_evenodd.c,v 1.5 2002/12/16 07:01:03 tdeval Exp $   */
    2 /*      $NetBSD: rf_evenodd.c,v 1.4 2000/01/07 03:40:59 oster Exp $     */
    3 
    4 /*
    5  * Copyright (c) 1995 Carnegie-Mellon University.
    6  * All rights reserved.
    7  *
    8  * Author: Chang-Ming Wu
    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  *
   33  * rf_evenodd.c -- implements EVENODD array architecture
   34  *
   35  *****************************************************************************/
   36 
   37 #include "rf_archs.h"
   38 
   39 #if     RF_INCLUDE_EVENODD > 0
   40 
   41 #include "rf_types.h"
   42 #include "rf_raid.h"
   43 #include "rf_dag.h"
   44 #include "rf_dagffrd.h"
   45 #include "rf_dagffwr.h"
   46 #include "rf_dagdegrd.h"
   47 #include "rf_dagdegwr.h"
   48 #include "rf_dagutils.h"
   49 #include "rf_dagfuncs.h"
   50 #include "rf_etimer.h"
   51 #include "rf_general.h"
   52 #include "rf_evenodd.h"
   53 #include "rf_configure.h"
   54 #include "rf_parityscan.h"
   55 #include "rf_utils.h"
   56 #include "rf_map.h"
   57 #include "rf_pq.h"
   58 #include "rf_mcpair.h"
   59 #include "rf_evenodd.h"
   60 #include "rf_evenodd_dagfuncs.h"
   61 #include "rf_evenodd_dags.h"
   62 #include "rf_engine.h"
   63 
   64 typedef struct RF_EvenOddConfigInfo_s {
   65         RF_RowCol_t **stripeIdentifier; /*
   66                                          * Filled in at config time & used by
   67                                          * IdentifyStripe.
   68                                          */
   69 }       RF_EvenOddConfigInfo_t;
   70 
   71 int
   72 rf_ConfigureEvenOdd(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
   73     RF_Config_t *cfgPtr)
   74 {
   75         RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
   76         RF_EvenOddConfigInfo_t *info;
   77         RF_RowCol_t i, j, startdisk;
   78 
   79         RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t),
   80             (RF_EvenOddConfigInfo_t *), raidPtr->cleanupList);
   81         layoutPtr->layoutSpecificInfo = (void *) info;
   82 
   83         RF_ASSERT(raidPtr->numRow == 1);
   84 
   85         info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol,
   86             raidPtr->numCol, raidPtr->cleanupList);
   87         startdisk = 0;
   88         for (i = 0; i < raidPtr->numCol; i++) {
   89                 for (j = 0; j < raidPtr->numCol; j++) {
   90                         info->stripeIdentifier[i][j] = (startdisk + j) %
   91                             raidPtr->numCol;
   92                 }
   93                 if ((startdisk -= 2) < 0)
   94                         startdisk += raidPtr->numCol;
   95         }
   96 
   97         /* Fill in the remaining layout parameters. */
   98         layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
   99         layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
  100             raidPtr->logBytesPerSector;
  101         layoutPtr->numDataCol = raidPtr->numCol - 2;    /*
  102                                                          * ORIG:
  103                                                          * layoutPtr->numDataCol
  104                                                          * = raidPtr->numCol-1;
  105                                                          */
  106 #if     RF_EO_MATRIX_DIM > 17
  107         if (raidPtr->numCol <= 17) {
  108                 printf("Number of stripe units in a parity stripe is smaller"
  109                     " than 17. Please\ndefine the macro RF_EO_MATRIX_DIM in"
  110                     " file rf_evenodd_dagfuncs.h to\nbe 17 to increase"
  111                     " performance.\n");
  112                 return (EINVAL);
  113         }
  114 #elif   RF_EO_MATRIX_DIM == 17
  115         if (raidPtr->numCol > 17) {
  116                 printf("Number of stripe units in a parity stripe is bigger"
  117                     " than 17. Please\ndefine the macro RF_EO_MATRIX_DIM in"
  118                     " file rf_evenodd_dagfuncs.h to\nbe 257 for encoding and"
  119                     " decoding functions to work.\n");
  120                 return (EINVAL);
  121         }
  122 #endif
  123         layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
  124             layoutPtr->sectorsPerStripeUnit;
  125         layoutPtr->numParityCol = 2;
  126         layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
  127         raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
  128             layoutPtr->sectorsPerStripeUnit;
  129 
  130         raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
  131             layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
  132 
  133         return (0);
  134 }
  135 
  136 int
  137 rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t *raidPtr)
  138 {
  139         return (20);
  140 }
  141 
  142 RF_HeadSepLimit_t
  143 rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t *raidPtr)
  144 {
  145         return (10);
  146 }
  147 
  148 void
  149 rf_IdentifyStripeEvenOdd(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
  150     RF_RowCol_t **diskids, RF_RowCol_t *outRow)
  151 {
  152         RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
  153             addr);
  154         RF_EvenOddConfigInfo_t *info =
  155             (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
  156 
  157         *outRow = 0;
  158         *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
  159 }
  160 
  161 
  162 /*
  163  * The layout of stripe unit on the disks are:  c0 c1 c2 c3 c4
  164  *
  165  *                                               0  1  2  E  P
  166  *                                               5  E  P  3  4
  167  *                                               P  6  7  8  E
  168  *                                              10 11  E  P  9
  169  *                                               E  P 12 13 14
  170  *                                              ....
  171  *
  172  * We use the MapSectorRAID5 to map data information because the routine can
  173  * be shown to map exactly the layout of data stripe unit as shown above,
  174  * although we have 2 redundant information now.
  175  * But for E and P, we use rf_MapEEvenOdd and rf_MapParityEvenOdd which are
  176  * different method from raid-5.
  177  */
  178 
  179 
  180 void
  181 rf_MapParityEvenOdd(
  182     RF_Raid_t           *raidPtr,
  183     RF_RaidAddr_t        raidSector,
  184     RF_RowCol_t         *row,
  185     RF_RowCol_t         *col,
  186     RF_SectorNum_t      *diskSector,
  187     int                  remap
  188 )
  189 {
  190         RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
  191         RF_StripeNum_t endSUIDofthisStrip =
  192             (SUID / raidPtr->Layout.numDataCol + 1) *
  193             raidPtr->Layout.numDataCol - 1;
  194 
  195         *row = 0;
  196         *col = (endSUIDofthisStrip + 2) % raidPtr->numCol;
  197         *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
  198             raidPtr->Layout.sectorsPerStripeUnit +
  199             (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
  200 }
  201 
  202 void
  203 rf_MapEEvenOdd(
  204     RF_Raid_t           *raidPtr,
  205     RF_RaidAddr_t        raidSector,
  206     RF_RowCol_t         *row,
  207     RF_RowCol_t         *col,
  208     RF_SectorNum_t      *diskSector,
  209     int                  remap
  210 )
  211 {
  212         RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
  213         RF_StripeNum_t endSUIDofthisStrip =
  214             (SUID / raidPtr->Layout.numDataCol + 1) *
  215             raidPtr->Layout.numDataCol - 1;
  216 
  217         *row = 0;
  218         *col = (endSUIDofthisStrip + 1) % raidPtr->numCol;
  219         *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
  220             raidPtr->Layout.sectorsPerStripeUnit +
  221             (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
  222 }
  223 
  224 void
  225 rf_EODagSelect(
  226     RF_Raid_t           *raidPtr,
  227     RF_IoType_t          type,
  228     RF_AccessStripeMap_t *asmap,
  229     RF_VoidFuncPtr      *createFunc
  230 )
  231 {
  232         RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
  233         unsigned ndfail = asmap->numDataFailed;
  234         unsigned npfail = asmap->numParityFailed + asmap->numQFailed;
  235         unsigned ntfail = npfail + ndfail;
  236 
  237         RF_ASSERT(RF_IO_IS_R_OR_W(type));
  238         if (ntfail > 2) {
  239                 RF_ERRORMSG("more than two disks failed in a single group !"
  240                     "  Aborting I/O operation.\n");
  241                  /* *infoFunc = */ *createFunc = NULL;
  242                 return;
  243         }
  244         /* Ok, we can do this I/O. */
  245         if (type == RF_IO_TYPE_READ) {
  246                 switch (ndfail) {
  247                 case 0:
  248                         /* Fault free read. */
  249                         *createFunc = (RF_VoidFuncPtr)
  250                             rf_CreateFaultFreeReadDAG;  /* Same as raid 5. */
  251                         break;
  252                 case 1:
  253                         /* Lost a single data unit. */
  254                         /*
  255                          * Two cases:
  256                          * (1) Parity is not lost. Do a normal raid 5
  257                          * reconstruct read.
  258                          * (2) Parity is lost. Do a reconstruct read using "e".
  259                          */
  260                         if (ntfail == 2) {      /* Also lost redundancy. */
  261                                 if (asmap->failedPDAs[1]->type ==
  262                                     RF_PDA_TYPE_PARITY)
  263                                         *createFunc = (RF_VoidFuncPtr)
  264                                             rf_EO_110_CreateReadDAG;
  265                                 else
  266                                         *createFunc = (RF_VoidFuncPtr)
  267                                             rf_EO_101_CreateReadDAG;
  268                         } else {
  269                                 /*
  270                                  * P and E are ok. But is there a failure in
  271                                  * some unaccessed data unit ?
  272                                  */
  273                                 if (rf_NumFailedDataUnitsInStripe(raidPtr,
  274                                     asmap) == 2)
  275                                         *createFunc = (RF_VoidFuncPtr)
  276                                             rf_EO_200_CreateReadDAG;
  277                                 else
  278                                         *createFunc = (RF_VoidFuncPtr)
  279                                             rf_EO_100_CreateReadDAG;
  280                         }
  281                         break;
  282                 case 2:
  283                         /* *createFunc = rf_EO_200_CreateReadDAG; */
  284                         *createFunc = NULL;
  285                         break;
  286                 }
  287                 return;
  288         }
  289         /* A write. */
  290         switch (ntfail) {
  291         case 0:         /* Fault free. */
  292                 if (rf_suppressLocksAndLargeWrites ||
  293                     (((asmap->numStripeUnitsAccessed <=
  294                        (layoutPtr->numDataCol / 2)) &&
  295                       (layoutPtr->numDataCol != 1)) ||
  296                      (asmap->parityInfo->next != NULL) ||
  297                      (asmap->qInfo->next != NULL) ||
  298                      rf_CheckStripeForFailures(raidPtr, asmap))) {
  299 
  300                         *createFunc = (RF_VoidFuncPtr) rf_EOCreateSmallWriteDAG;
  301                 } else {
  302                         *createFunc = (RF_VoidFuncPtr) rf_EOCreateLargeWriteDAG;
  303                 }
  304                 break;
  305 
  306         case 1:         /* Single disk fault. */
  307                 if (npfail == 1) {
  308                         RF_ASSERT((asmap->failedPDAs[0]->type ==
  309                             RF_PDA_TYPE_PARITY) ||
  310                             (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q));
  311                         if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) {
  312                                 /*
  313                                  * q died, treat like normal mode raid5
  314                                  * write.
  315                                  */
  316                                 if (((asmap->numStripeUnitsAccessed <=
  317                                       (layoutPtr->numDataCol / 2)) ||
  318                                      (asmap->numStripeUnitsAccessed == 1)) ||
  319                                     (asmap->parityInfo->next != NULL) ||
  320                                     rf_NumFailedDataUnitsInStripe(raidPtr,
  321                                      asmap))
  322                                         *createFunc = (RF_VoidFuncPtr)
  323                                             rf_EO_001_CreateSmallWriteDAG;
  324                                 else
  325                                         *createFunc = (RF_VoidFuncPtr)
  326                                             rf_EO_001_CreateLargeWriteDAG;
  327                         } else {
  328                                 /* Parity died, small write only updating Q. */
  329                                 if (((asmap->numStripeUnitsAccessed <=
  330                                       (layoutPtr->numDataCol / 2)) ||
  331                                      (asmap->numStripeUnitsAccessed == 1)) ||
  332                                     (asmap->qInfo->next != NULL) ||
  333                                     rf_NumFailedDataUnitsInStripe(raidPtr,
  334                                      asmap))
  335                                         *createFunc = (RF_VoidFuncPtr)
  336                                             rf_EO_010_CreateSmallWriteDAG;
  337                                 else
  338                                         *createFunc = (RF_VoidFuncPtr)
  339                                             rf_EO_010_CreateLargeWriteDAG;
  340                         }
  341                 } else {        /*
  342                                  * Data missing. Do a P reconstruct write if
  343                                  * only a single data unit is lost in the
  344                                  * stripe, otherwise a reconstruct write which
  345                                  * is employing both P and E units.
  346                                  */
  347                         if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
  348                         {
  349                                 if (asmap->numStripeUnitsAccessed == 1)
  350                                         *createFunc = (RF_VoidFuncPtr)
  351                                             rf_EO_200_CreateWriteDAG;
  352                                 else
  353                                         /*
  354                                          * No direct support for this case now,
  355                                          * like that in Raid-5.
  356                                          */
  357                                         *createFunc = NULL;
  358                         } else {
  359                                 if (asmap->numStripeUnitsAccessed != 1 &&
  360                                     asmap->failedPDAs[0]->numSector !=
  361                                     layoutPtr->sectorsPerStripeUnit)
  362                                         /*
  363                                          * No direct support for this case now,
  364                                          * like that in Raid-5.
  365                                          */
  366                                         *createFunc = NULL;
  367                                 else
  368                                         *createFunc = (RF_VoidFuncPtr)
  369                                             rf_EO_100_CreateWriteDAG;
  370                         }
  371                 }
  372                 break;
  373 
  374         case 2:         /* Two disk faults. */
  375                 switch (npfail) {
  376                 case 2: /* Both p and q dead. */
  377                         *createFunc = (RF_VoidFuncPtr) rf_EO_011_CreateWriteDAG;
  378                         break;
  379                 case 1: /* Either p or q and dead data. */
  380                         RF_ASSERT(asmap->failedPDAs[0]->type ==
  381                             RF_PDA_TYPE_DATA);
  382                         RF_ASSERT((asmap->failedPDAs[1]->type ==
  383                             RF_PDA_TYPE_PARITY) ||
  384                             (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q));
  385                         if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) {
  386                                 if (asmap->numStripeUnitsAccessed != 1 &&
  387                                     asmap->failedPDAs[0]->numSector !=
  388                                     layoutPtr->sectorsPerStripeUnit)
  389                                         /*
  390                                          * In both PQ and EvenOdd, no direct
  391                                          * support for this case now, like that
  392                                          * in Raid-5.
  393                                          */
  394                                         *createFunc = NULL;
  395                                 else
  396                                         *createFunc = (RF_VoidFuncPtr)
  397                                             rf_EO_101_CreateWriteDAG;
  398                         } else {
  399                                 if (asmap->numStripeUnitsAccessed != 1 &&
  400                                     asmap->failedPDAs[0]->numSector !=
  401                                     layoutPtr->sectorsPerStripeUnit)
  402                                         /*
  403                                          * No direct support for this case,
  404                                          * like that in Raid-5.
  405                                          */
  406                                         *createFunc = NULL;
  407                                 else
  408                                         *createFunc = (RF_VoidFuncPtr)
  409                                             rf_EO_110_CreateWriteDAG;
  410                         }
  411                         break;
  412                 case 0: /* Double data loss. */
  413                         /*
  414                          * if(asmap->failedPDAs[0]->numSector +
  415                          * asmap->failedPDAs[1]->numSector == 2 *
  416                          * layoutPtr->sectorsPerStripeUnit ) createFunc =
  417                          * rf_EOCreateLargeWriteDAG; else
  418                          */
  419                         *createFunc = NULL;     /*
  420                                                  * Currently, in Evenodd, no
  421                                                  * support for simultaneous
  422                                                  * access of both failed SUs.
  423                                                  */
  424                         break;
  425                 }
  426                 break;
  427 
  428         default:        /* More than 2 disk faults. */
  429                 *createFunc = NULL;
  430                 RF_PANIC();
  431         }
  432         return;
  433 }
  434 
  435 
  436 int
  437 rf_VerifyParityEvenOdd(
  438         RF_Raid_t               *raidPtr,
  439         RF_RaidAddr_t            raidAddr,
  440         RF_PhysDiskAddr_t       *parityPDA,
  441         int                      correct_it,
  442         RF_RaidAccessFlags_t     flags
  443 )
  444 {
  445         RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
  446         RF_RaidAddr_t startAddr =
  447             rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
  448         RF_SectorCount_t numsector = parityPDA->numSector;
  449         int numbytes = rf_RaidAddressToByte(raidPtr, numsector);
  450         int bytesPerStripe = numbytes * layoutPtr->numDataCol;
  451         RF_DagHeader_t *rd_dag_h, *wr_dag_h;    /* Read, write dag. */
  452         RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
  453         RF_AccessStripeMapHeader_t *asm_h;
  454         RF_AccessStripeMap_t *asmap;
  455         RF_AllocListElem_t *alloclist;
  456         RF_PhysDiskAddr_t *pda;
  457         char *pbuf, *buf, *end_p, *p;
  458         char *redundantbuf2;
  459         int redundantTwoErr = 0, redundantOneErr = 0;
  460         int parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE,
  461             parity_corrected = RF_FALSE, red2_corrected = RF_FALSE;
  462         int i, retcode;
  463         RF_ReconUnitNum_t which_ru;
  464         RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr,
  465             raidAddr, &which_ru);
  466         int stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
  467         RF_AccTraceEntry_t tracerec;
  468         RF_MCPair_t *mcpair;
  469 
  470         retcode = RF_PARITY_OKAY;
  471 
  472         mcpair = rf_AllocMCPair();
  473         rf_MakeAllocList(alloclist);
  474         RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol +
  475             layoutPtr->numParityCol), (char *), alloclist);
  476         /* Use calloc to make sure buffer is zeroed. */
  477         RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);
  478         end_p = buf + bytesPerStripe;
  479         /* Use calloc to make sure buffer is zeroed. */
  480         RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist);
  481 
  482         rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf,
  483             rf_DiskReadFunc, rf_DiskReadUndoFunc, "Rod", alloclist, flags,
  484             RF_IO_NORMAL_PRIORITY);
  485         blockNode = rd_dag_h->succedents[0];
  486         unblockNode = blockNode->succedents[0]->succedents[0];
  487 
  488         /* Map the stripe and fill in the PDAs in the dag. */
  489         asm_h = rf_MapAccess(raidPtr, startAddr,
  490             layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
  491         asmap = asm_h->stripeMap;
  492 
  493         for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol;
  494              i++, pda = pda->next) {
  495                 RF_ASSERT(pda);
  496                 rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
  497                 RF_ASSERT(pda->numSector != 0);
  498                 if (rf_TryToRedirectPDA(raidPtr, pda, 0))
  499                         /*
  500                          * No way to verify parity if disk is dead.
  501                          * Return w/ good status.
  502                          */
  503                         goto out;
  504                 blockNode->succedents[i]->params[0].p = pda;
  505                 blockNode->succedents[i]->params[2].v = psID;
  506                 blockNode->succedents[i]->params[3].v =
  507                     RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
  508         }
  509 
  510         RF_ASSERT(!asmap->parityInfo->next);
  511         rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
  512         RF_ASSERT(asmap->parityInfo->numSector != 0);
  513         if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
  514                 goto out;
  515         blockNode->succedents[layoutPtr->numDataCol]->params[0].p =
  516             asmap->parityInfo;
  517 
  518         RF_ASSERT(!asmap->qInfo->next);
  519         rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1);
  520         RF_ASSERT(asmap->qInfo->numSector != 0);
  521         if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1))
  522                 goto out;
  523         /*
  524          * If disk is dead, b/c no reconstruction is implemented right now,
  525          * the function "rf_TryToRedirectPDA" always return one, which causes
  526          * go to out and return w/ good status.
  527          */
  528         blockNode->succedents[layoutPtr->numDataCol + 1]->params[0].p =
  529             asmap->qInfo;
  530 
  531         /* Fire off the DAG. */
  532         bzero((char *) &tracerec, sizeof(tracerec));
  533         rd_dag_h->tracerec = &tracerec;
  534 
  535         if (rf_verifyParityDebug) {
  536                 printf("Parity verify read dag:\n");
  537                 rf_PrintDAGList(rd_dag_h);
  538         }
  539         RF_LOCK_MUTEX(mcpair->mutex);
  540         mcpair->flag = 0;
  541         rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
  542             (void *) mcpair);
  543         while (!mcpair->flag)
  544                 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
  545         RF_UNLOCK_MUTEX(mcpair->mutex);
  546         if (rd_dag_h->status != rf_enable) {
  547                 RF_ERRORMSG("Unable to verify parity:  can't read"
  548                     " the stripe\n");
  549                 retcode = RF_PARITY_COULD_NOT_VERIFY;
  550                 goto out;
  551         }
  552         for (p = buf, i = 0; p < end_p; p += numbytes, i++) {
  553                 rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2,
  554                     redundantbuf2, numsector);
  555                 /*
  556                  * The corresponding columns in EvenOdd encoding Matrix for
  557                  * these p pointers that point to the databuffer in a full
  558                  * stripe are sequential from 0 to layoutPtr->numDataCol-1.
  559                  */
  560                 rf_bxor(p, pbuf, numbytes, NULL);
  561         }
  562         RF_ASSERT(i == layoutPtr->numDataCol);
  563 
  564         for (i = 0; i < numbytes; i++) {
  565                 if (pbuf[i] != buf[bytesPerStripe + i]) {
  566                         if (!correct_it) {
  567                                 RF_ERRORMSG3("Parity verify error: byte %d of"
  568                                     " parity is 0x%x should be 0x%x\n", i,
  569                                     (u_char) buf[bytesPerStripe + i],
  570                                     (u_char) pbuf[i]);
  571                         }
  572                 }
  573                 redundantOneErr = 1;
  574                 break;
  575         }
  576 
  577         for (i = 0; i < numbytes; i++) {
  578                 if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) {
  579                         if (!correct_it) {
  580                                 RF_ERRORMSG3("Parity verify error: byte %d of"
  581                                     " second redundant information is 0x%x"
  582                                     " should be 0x%x\n", i,
  583                                     (u_char) buf[bytesPerStripe + numbytes + i],
  584                                     (u_char) redundantbuf2[i]);
  585                         }
  586                         redundantTwoErr = 1;
  587                         break;
  588                 }
  589         }
  590         if (redundantOneErr || redundantTwoErr)
  591                 retcode = RF_PARITY_BAD;
  592 
  593         /* Correct the first redundant disk, ie parity if it is error. */
  594         if (redundantOneErr && correct_it) {
  595                 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf,
  596                     rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wnp", alloclist,
  597                     flags, RF_IO_NORMAL_PRIORITY);
  598                 wrBlock = wr_dag_h->succedents[0];
  599                 wrUnblock = wrBlock->succedents[0]->succedents[0];
  600                 wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
  601                 wrBlock->succedents[0]->params[2].v = psID;
  602                 wrBlock->succedents[0]->params[3].v =
  603                     RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
  604                 bzero((char *) &tracerec, sizeof(tracerec));
  605                 wr_dag_h->tracerec = &tracerec;
  606                 if (rf_verifyParityDebug) {
  607                         printf("Parity verify write dag:\n");
  608                         rf_PrintDAGList(wr_dag_h);
  609                 }
  610                 RF_LOCK_MUTEX(mcpair->mutex);
  611                 mcpair->flag = 0;
  612                 rf_DispatchDAG(wr_dag_h,
  613                     (void (*) (void *)) rf_MCPairWakeupFunc, (void *) mcpair);
  614                 while (!mcpair->flag)
  615                         RF_WAIT_COND(mcpair->cond, mcpair->mutex);
  616                 RF_UNLOCK_MUTEX(mcpair->mutex);
  617                 if (wr_dag_h->status != rf_enable) {
  618                         RF_ERRORMSG("Unable to correct parity in VerifyParity:"
  619                             " can't write the stripe\n");
  620                         parity_cant_correct = RF_TRUE;
  621                 } else {
  622                         parity_corrected = RF_TRUE;
  623                 }
  624                 rf_FreeDAG(wr_dag_h);
  625         }
  626         if (redundantTwoErr && correct_it) {
  627                 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes,
  628                     redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
  629                     "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
  630                 wrBlock = wr_dag_h->succedents[0];
  631                 wrUnblock = wrBlock->succedents[0]->succedents[0];
  632                 wrBlock->succedents[0]->params[0].p = asmap->qInfo;
  633                 wrBlock->succedents[0]->params[2].v = psID;
  634                 wrBlock->succedents[0]->params[3].v =
  635                     RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
  636                 bzero((char *) &tracerec, sizeof(tracerec));
  637                 wr_dag_h->tracerec = &tracerec;
  638                 if (rf_verifyParityDebug) {
  639                         printf("Dag of write new second redundant information"
  640                             " in parity verify :\n");
  641                         rf_PrintDAGList(wr_dag_h);
  642                 }
  643                 RF_LOCK_MUTEX(mcpair->mutex);
  644                 mcpair->flag = 0;
  645                 rf_DispatchDAG(wr_dag_h,
  646                     (void (*) (void *)) rf_MCPairWakeupFunc, (void *) mcpair);
  647                 while (!mcpair->flag)
  648                         RF_WAIT_COND(mcpair->cond, mcpair->mutex);
  649                 RF_UNLOCK_MUTEX(mcpair->mutex);
  650                 if (wr_dag_h->status != rf_enable) {
  651                         RF_ERRORMSG("Unable to correct second redundant"
  652                             " information in VerifyParity: can't write the"
  653                             " stripe\n");
  654                         red2_cant_correct = RF_TRUE;
  655                 } else {
  656                         red2_corrected = RF_TRUE;
  657                 }
  658                 rf_FreeDAG(wr_dag_h);
  659         }
  660         if ((redundantOneErr && parity_cant_correct) ||
  661             (redundantTwoErr && red2_cant_correct))
  662                 retcode = RF_PARITY_COULD_NOT_CORRECT;
  663         if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
  664                 retcode = RF_PARITY_CORRECTED;
  665 
  666 
  667 out:
  668         rf_FreeAccessStripeMap(asm_h);
  669         rf_FreeAllocList(alloclist);
  670         rf_FreeDAG(rd_dag_h);
  671         rf_FreeMCPair(mcpair);
  672         return (retcode);
  673 }
  674 #endif  /* RF_INCLUDE_EVENODD > 0 */

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