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

Cache object: b63c10228e093880559710a50977a616


[ 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.