📄 rf_evenodd_dagfuncs.c
字号:
{ int ndataParam = 0; int np = node->numParams; RF_AccessStripeMap_t *asmap = (RF_AccessStripeMap_t *) node->params[np-1].p; RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[np-2].p; RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) &(raidPtr->Layout); int d, i, prm, sector, nresults = node->numResults; RF_SectorCount_t secPerSU = layoutPtr->sectorsPerStripeUnit; unsigned suoffset, len, sosAddr; int two = 0, mallc_one= 0, mallc_two = 0; /* flags to indicate if memory is allocated */ int bytesPerSector = rf_RaidAddressToByte(raidPtr, 1 ); RF_PhysDiskAddr_t *ppda,*ppda2,*epda,*epda2,*pda, *pda0, *pda1, npda; RF_RowCol_t fcol[2], fsuoff[2], fsuend[2], numDataCol = layoutPtr->numDataCol; char **buf, *ebuf, *pbuf, *dest[2]; long *suoff, *suend, *prmToCol, psuoff, esuoff; RF_SectorNum_t startSector, endSector; RF_Etimer_t timer; RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec; RF_ETIMER_START(timer); /* Find out the number of parameters which are pdas for data information */ for (i = 0; i<= np; i++) if( ((RF_PhysDiskAddr_t *)node->params[i].p)->type != RF_PDA_TYPE_DATA) {ndataParam = i ; break; } RF_Malloc(buf, numDataCol*sizeof(char *), (char **)); if (ndataParam != 0 ){ RF_Malloc(suoff, ndataParam*sizeof(long), (long *) ); RF_Malloc(suend, ndataParam*sizeof(long), (long *) ); RF_Malloc(prmToCol, ndataParam*sizeof(long), (long *) ); } if (asmap->failedPDAtwo && (asmap->failedPDAtwo->numSector + asmap->failedPDA->numSector < secPerSU)) { RF_ASSERT(0); /* currently, no support for this situation */ ppda = node->params[np-6].p; ppda2 = node->params[np-5].p; RF_ASSERT( ppda2->type == RF_PDA_TYPE_PARITY ); epda = node->params[np-4].p; epda2 = node->params[np-3].p; RF_ASSERT( epda2->type == RF_PDA_TYPE_Q ); two = 1; } else { ppda = node->params[np-4].p; epda = node->params[np-3].p; psuoff = rf_StripeUnitOffset(layoutPtr, ppda->startSector); esuoff = rf_StripeUnitOffset(layoutPtr, epda->startSector); RF_ASSERT( psuoff == esuoff ); } /* the followings have three goals: 1. determine the startSector to begin decoding and endSector to end decoding. 2. determine the colume numbers of the two failed disks. 3. determine the offset and end offset of the access within each failed stripe unit. */ if( nresults == 1 ) { /* find the startSector to begin decoding */ pda = node->results[0]; bzero(pda->bufPtr, bytesPerSector*pda->numSector ); fsuoff[0] = rf_StripeUnitOffset(layoutPtr, pda->startSector ); fsuend[0] = fsuoff[0] + pda->numSector; startSector = fsuoff[0]; endSector = fsuend[0]; /* find out the the column of failed disk being accessed */ fcol[0] = rf_EUCol(layoutPtr, pda->raidAddress ); /* find out the other failed colume not accessed */ sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, asmap->raidAddress); for (i=0; i < numDataCol; i++) { npda.raidAddress = sosAddr + (i * secPerSU); (raidPtr->Layout.map->MapSector)(raidPtr, npda.raidAddress, &(npda.row), &(npda.col), &(npda.startSector), 0); /* skip over dead disks */ if (RF_DEAD_DISK(raidPtr->Disks[npda.row][npda.col].status)) if (i != fcol[0]) break; } RF_ASSERT (i < numDataCol); fcol[1] = i; } else { RF_ASSERT ( nresults == 2 ); pda0 = node->results[0]; bzero(pda0->bufPtr, bytesPerSector*pda0->numSector ); pda1 = node->results[1]; bzero(pda1->bufPtr, bytesPerSector*pda1->numSector ); /* determine the failed colume numbers of the two failed disks. */ fcol[0] = rf_EUCol(layoutPtr, pda0->raidAddress ); fcol[1] = rf_EUCol(layoutPtr, pda1->raidAddress ); /* determine the offset and end offset of the access within each failed stripe unit. */ fsuoff[0] = rf_StripeUnitOffset(layoutPtr, pda0->startSector ); fsuend[0] = fsuoff[0] + pda0->numSector; fsuoff[1] = rf_StripeUnitOffset(layoutPtr, pda1->startSector ); fsuend[1] = fsuoff[1] + pda1->numSector; /* determine the startSector to begin decoding */ startSector = RF_MIN( pda0->startSector, pda1->startSector ); /* determine the endSector to end decoding */ endSector = RF_MAX( fsuend[0], fsuend[1] ); } /* assign the beginning sector and the end sector for each parameter find out the corresponding colume # for each parameter */ for( prm=0; prm < ndataParam; prm++ ) { pda = node->params[prm].p; suoff[prm] = rf_StripeUnitOffset(layoutPtr, pda->startSector); suend[prm] = suoff[prm] + pda->numSector; prmToCol[prm] = rf_EUCol(layoutPtr, pda->raidAddress ); } /* 'sector' is the sector for the current decoding algorithm. For each sector in the failed SU, find out the corresponding parameters that cover the current sector and that are needed for decoding of this sector in failed SU. 2. Find out if sector is in the shadow of any accessed failed SU. If not, malloc a temporary space of a sector in size. */ for( sector = startSector; sector < endSector; sector++ ){ if ( nresults == 2 ) if( !(fsuoff[0]<=sector && sector<fsuend[0]) && !(fsuoff[1]<=sector && sector<fsuend[1]) )continue; for( prm=0; prm < ndataParam; prm++ ) if( suoff[prm] <= sector && sector < suend[prm] ) buf[(prmToCol[prm])] = ((RF_PhysDiskAddr_t *)node->params[prm].p)->bufPtr + rf_RaidAddressToByte(raidPtr, sector-suoff[prm]); /* find out if sector is in the shadow of any accessed failed SU. If yes, assign dest[0], dest[1] to point at suitable position of the buffer corresponding to failed SUs. if no, malloc a temporary space of a sector in size for destination of decoding. */ RF_ASSERT( nresults == 1 || nresults == 2 ); if ( nresults == 1) { dest[0] = ((RF_PhysDiskAddr_t *)node->results[0])->bufPtr + rf_RaidAddressToByte(raidPtr, sector-fsuoff[0]); /* Always malloc temp buffer to dest[1] */ RF_Malloc( dest[1], bytesPerSector, (char *) ); bzero(dest[1],bytesPerSector); mallc_two = 1; } else { if( fsuoff[0] <= sector && sector < fsuend[0] ) dest[0] = ((RF_PhysDiskAddr_t *)node->results[0])->bufPtr + rf_RaidAddressToByte(raidPtr, sector-fsuoff[0]); else { RF_Malloc( dest[0], bytesPerSector, (char *) ); bzero(dest[0],bytesPerSector); mallc_one = 1; } if( fsuoff[1] <= sector && sector < fsuend[1] ) dest[1] = ((RF_PhysDiskAddr_t *)node->results[1])->bufPtr + rf_RaidAddressToByte(raidPtr, sector-fsuoff[1]); else { RF_Malloc( dest[1], bytesPerSector, (char *) ); bzero(dest[1],bytesPerSector); mallc_two = 1; } RF_ASSERT( mallc_one == 0 || mallc_two == 0 ); } pbuf = ppda->bufPtr + rf_RaidAddressToByte(raidPtr, sector-psuoff ); ebuf = epda->bufPtr + rf_RaidAddressToByte(raidPtr, sector-esuoff ); /* * After finish finding all needed sectors, call doubleEOdecode function for decoding * one sector to destination. */ rf_doubleEOdecode(raidPtr, buf, dest, fcol, pbuf, ebuf ); /* free all allocated memory, and mark flag to indicate no memory is being allocated */ if( mallc_one == 1) RF_Free( dest[0], bytesPerSector ); if( mallc_two == 1) RF_Free( dest[1], bytesPerSector ); mallc_one = mallc_two = 0; } RF_Free(buf, numDataCol*sizeof(char *)); if (ndataParam != 0){ RF_Free(suoff, ndataParam*sizeof(long)); RF_Free(suend, ndataParam*sizeof(long)); RF_Free(prmToCol, ndataParam*sizeof(long)); } RF_ETIMER_STOP(timer); RF_ETIMER_EVAL(timer); if (tracerec) { tracerec->q_us += RF_ETIMER_VAL_US(timer); } rf_GenericWakeupFunc(node,0);}/* currently, only access of one of the two failed SU is allowed in this function. * also, asmap->numStripeUnitsAccessed is limited to be one, the RaidFrame will break large access into * many accesses of single stripe unit. */int rf_EOWriteDoubleRecoveryFunc(node) RF_DagNode_t *node;{ int np = node->numParams; RF_AccessStripeMap_t *asmap = (RF_AccessStripeMap_t *) node->params[np-1].p; RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[np-2].p; RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) &(raidPtr->Layout); RF_SectorNum_t sector; RF_RowCol_t col, scol; int prm, i, j, nresults = node->numResults; RF_SectorCount_t secPerSU = layoutPtr->sectorsPerStripeUnit; unsigned bufoffset, suoffset, len, sosAddr; unsigned bytesPerSector = rf_RaidAddressToByte(raidPtr, 1 ); RF_int64 numbytes; RF_SectorNum_t startSector, endSector; RF_PhysDiskAddr_t *ppda,*ppda2,*epda,*epda2,*pda, *fpda, npda; RF_RowCol_t fcol[2], numDataCol = layoutPtr->numDataCol; char **buf; /* buf[0], buf[1], buf[2], ...etc. point to buffer storing data read from col0, col1, col2 */ char *ebuf, *pbuf, *dest[2], *olddata[2]; RF_Etimer_t timer; RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec; RF_ASSERT( asmap->numDataFailed == 1 ); /* currently only support this case, the other failed SU is not being accessed */ RF_ETIMER_START(timer); RF_Malloc(buf, numDataCol*sizeof(char *), (char **)); ppda = node->results[0]; /* Instead of being buffers, node->results[0] and [1] are Ppda and Epda */ epda = node->results[1]; fpda = asmap->failedPDA; /* First, recovery the failed old SU using EvenOdd double decoding */ /* determine the startSector and endSector for decoding */ startSector = rf_StripeUnitOffset(layoutPtr, fpda->startSector ); endSector = startSector + fpda->numSector; /* Assign buf[col] pointers to point to each non-failed colume and initialize the pbuf and ebuf to point at the beginning of each source buffers and destination buffers */ for( prm=0; prm < numDataCol-2; prm++ ) { pda = (RF_PhysDiskAddr_t *)node->params[prm].p; col = rf_EUCol(layoutPtr, pda->raidAddress ); buf[col] = pda->bufPtr; } /* pbuf and ebuf: they will change values as double recovery decoding goes on */ pbuf = ppda->bufPtr; ebuf = epda->bufPtr; /* find out the logical colume numbers in the encoding matrix of the two failed columes */ fcol[0] = rf_EUCol(layoutPtr, fpda->raidAddress ); /* find out the other failed colume not accessed this time */ sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, asmap->raidAddress); for (i=0; i < numDataCol; i++) { npda.raidAddress = sosAddr + (i * secPerSU); (raidPtr->Layout.map->MapSector)(raidPtr, npda.raidAddress, &(npda.row), &(npda.col), &(npda.startSector), 0); /* skip over dead disks */ if (RF_DEAD_DISK(raidPtr->Disks[npda.row][npda.col].status)) if (i != fcol[0]) break; } RF_ASSERT (i < numDataCol); fcol[1] = i; /* assign temporary space to put recovered failed SU */ numbytes = fpda->numSector * bytesPerSector; RF_Malloc(olddata[0], numbytes, (char *) ); RF_Malloc(olddata[1], numbytes, (char *) ); dest[0] = olddata[0]; dest[1] = olddata[1]; bzero(olddata[0], numbytes); bzero(olddata[1], numbytes); /* Begin the recovery decoding, initially buf[j], ebuf, pbuf, dest[j] have already pointed at the beginning of each source buffers and destination buffers */ for( sector = startSector, i=0; sector < endSector; sector++ , i++){ rf_doubleEOdecode(raidPtr, buf, dest, fcol, pbuf, ebuf ); for (j=0; j < numDataCol; j++) if( ( j != fcol[0]) && ( j != fcol[1] ) ) buf[j] += bytesPerSector; dest[0] += bytesPerSector; dest[1] += bytesPerSector; ebuf += bytesPerSector; pbuf += bytesPerSector; } /* after recovery, the buffer pointed by olddata[0] is the old failed data. With new writing data and this old data, use small write to calculate the new redundant informations */ /* node->params[ 0, ... PDAPerDisk * (numDataCol - 2)-1 ] are Pdas of Rrd; params[ PDAPerDisk*(numDataCol - 2), ... PDAPerDisk*numDataCol -1 ] are Pdas of Rp, ( Rp2 ), Re, ( Re2 ) ; params[ PDAPerDisk*numDataCol, ... PDAPerDisk*numDataCol +asmap->numStripeUnitsAccessed -asmap->numDataFailed-1] are Pdas of wudNodes; For current implementation, we assume the simplest case: asmap->numStripeUnitsAccessed == 1 and asmap->numDataFailed == 1 ie. PDAPerDisk = 1 then node->params[numDataCol] must be the new data to be writen to the failed disk. We first bxor the new data into the old recovered data, then do the same things as small write. */ rf_bxor( ((RF_PhysDiskAddr_t *)node->params[numDataCol].p)->bufPtr, olddata[0], numbytes, node->dagHdr->bp); /* do new 'E' calculation */ /* find out the corresponding colume in encoding matrix for write colume to be encoded into redundant disk 'E' */ scol = rf_EUCol(layoutPtr, fpda->raidAddress ); /* olddata[0] now is source buffer pointer; epda->bufPtr is the dest buffer pointer */ rf_e_encToBuf(raidPtr, scol, olddata[0], RF_EO_MATRIX_DIM - 2, epda->bufPtr, fpda->numSector); /* do new 'P' calculation */ rf_bxor( olddata[0], ppda->bufPtr, numbytes, node->dagHdr->bp); /* Free the allocated buffer */ RF_Free( olddata[0], numbytes ); RF_Free( olddata[1], numbytes ); RF_Free( buf, numDataCol*sizeof(char *)); RF_ETIMER_STOP(timer); RF_ETIMER_EVAL(timer); if (tracerec) { tracerec->q_us += RF_ETIMER_VAL_US(timer); } rf_GenericWakeupFunc(node,0); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -