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