📄 rf_map.c
字号:
int count;{ RF_FREELIST_FREE_N(rf_asm_freelist,l_start,next,(RF_AccessStripeMap_t *),count);}void rf_FreeAccessStripeMap(hdr) RF_AccessStripeMapHeader_t *hdr;{ RF_AccessStripeMap_t *p, *pt; RF_PhysDiskAddr_t *pdp, *trailer, *pdaList = NULL, *pdaEnd; int count = 0, t, asm_count = 0; for (p = hdr->stripeMap; p; p=p->next) { /* link the 3 pda lists into the accumulating pda list */ if (!pdaList) pdaList = p->qInfo; else pdaEnd->next = p->qInfo; for (trailer=NULL,pdp=p->qInfo; pdp; ) {trailer = pdp; pdp=pdp->next; count++;} if (trailer) pdaEnd = trailer; if (!pdaList) pdaList = p->parityInfo; else pdaEnd->next = p->parityInfo; for (trailer=NULL,pdp=p->parityInfo; pdp; ) {trailer = pdp; pdp=pdp->next; count++;} if (trailer) pdaEnd = trailer; if (!pdaList) pdaList = p->physInfo; else pdaEnd->next = p->physInfo; for (trailer=NULL,pdp=p->physInfo; pdp; ) {trailer = pdp; pdp=pdp->next; count++;} if (trailer) pdaEnd = trailer; pt = p; asm_count++; } /* debug only */ for (t=0,pdp=pdaList; pdp; pdp=pdp->next) t++; RF_ASSERT(t == count); if (pdaList) rf_FreePDAList(pdaList, pdaEnd, count); rf_FreeASMList(hdr->stripeMap, pt, asm_count); rf_FreeAccessStripeMapHeader(hdr);}/* We can't use the large write optimization if there are any failures in the stripe. * In the declustered layout, there is no way to immediately determine what disks * constitute a stripe, so we actually have to hunt through the stripe looking for failures. * The reason we map the parity instead of just using asm->parityInfo->col is because * the latter may have been already redirected to a spare drive, which would * mess up the computation of the stripe offset. * * ASSUMES AT MOST ONE FAILURE IN THE STRIPE. */int rf_CheckStripeForFailures(raidPtr, asmap) RF_Raid_t *raidPtr; RF_AccessStripeMap_t *asmap;{ RF_RowCol_t trow, tcol, prow, pcol, *diskids, row, i; RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; RF_StripeCount_t stripeOffset; int numFailures; RF_RaidAddr_t sosAddr; RF_SectorNum_t diskOffset, poffset; RF_RowCol_t testrow; /* quick out in the fault-free case. */ RF_LOCK_MUTEX(raidPtr->mutex); numFailures = raidPtr->numFailures; RF_UNLOCK_MUTEX(raidPtr->mutex); if (numFailures == 0) return(0); sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, asmap->raidAddress); row = asmap->physInfo->row; (layoutPtr->map->IdentifyStripe)(raidPtr, asmap->raidAddress, &diskids, &testrow); (layoutPtr->map->MapParity)(raidPtr, asmap->raidAddress, &prow, &pcol, &poffset, 0); /* get pcol */ /* this need not be true if we've redirected the access to a spare in another row RF_ASSERT(row == testrow); */ stripeOffset = 0; for (i=0; i<layoutPtr->numDataCol+layoutPtr->numParityCol; i++) { if (diskids[i] != pcol) { if (RF_DEAD_DISK(raidPtr->Disks[testrow][diskids[i]].status)) { if (raidPtr->status[testrow] != rf_rs_reconstructing) return(1); RF_ASSERT(raidPtr->reconControl[testrow]->fcol == diskids[i]); layoutPtr->map->MapSector(raidPtr, sosAddr + stripeOffset * layoutPtr->sectorsPerStripeUnit, &trow, &tcol, &diskOffset, 0); RF_ASSERT( (trow == testrow) && (tcol == diskids[i]) ); if (!rf_CheckRUReconstructed(raidPtr->reconControl[testrow]->reconMap, diskOffset)) return(1); asmap->flags |= RF_ASM_REDIR_LARGE_WRITE; return(0); } stripeOffset++; } } return(0);}/* return the number of failed data units in the stripe.*/int rf_NumFailedDataUnitsInStripe(raidPtr, asmap) RF_Raid_t *raidPtr; RF_AccessStripeMap_t *asmap;{ RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; RF_RowCol_t trow, tcol, row, i; RF_SectorNum_t diskOffset; RF_RaidAddr_t sosAddr; int numFailures; /* quick out in the fault-free case. */ RF_LOCK_MUTEX(raidPtr->mutex); numFailures = raidPtr->numFailures; RF_UNLOCK_MUTEX(raidPtr->mutex); if (numFailures == 0) return(0); numFailures = 0; sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, asmap->raidAddress); row = asmap->physInfo->row; for (i=0; i<layoutPtr->numDataCol; i++) { (layoutPtr->map->MapSector)(raidPtr, sosAddr + i * layoutPtr->sectorsPerStripeUnit, &trow, &tcol, &diskOffset, 0); if (RF_DEAD_DISK(raidPtr->Disks[trow][tcol].status)) numFailures++; } return numFailures;}/***************************************************************************************** * * debug routines * ****************************************************************************************/void rf_PrintAccessStripeMap(asm_h) RF_AccessStripeMapHeader_t *asm_h;{ rf_PrintFullAccessStripeMap(asm_h, 0);}void rf_PrintFullAccessStripeMap(asm_h, prbuf) RF_AccessStripeMapHeader_t *asm_h; int prbuf; /* flag to print buffer pointers */{ int i; RF_AccessStripeMap_t *asmap = asm_h->stripeMap; RF_PhysDiskAddr_t *p; printf("%d stripes total\n", asm_h->numStripes); for (; asmap; asmap = asmap->next) { printf("Stripe %ld (%d sectors), failures: %d data, %d parity: ", asmap->stripeID,asmap->totalSectorsAccessed,asmap->numDataFailed,asmap->numParityFailed); if (asmap->parityInfo) { printf("Parity [r%d c%d s%d-%d", asmap->parityInfo->row, asmap->parityInfo->col, asmap->parityInfo->startSector, asmap->parityInfo->startSector + asmap->parityInfo->numSector - 1); if (prbuf) printf(" b0x%lx",(unsigned long) asmap->parityInfo->bufPtr); if (asmap->parityInfo->next) { printf(", r%d c%d s%d-%d", asmap->parityInfo->next->row, asmap->parityInfo->next->col, asmap->parityInfo->next->startSector, asmap->parityInfo->next->startSector + asmap->parityInfo->next->numSector - 1); if (prbuf) printf(" b0x%lx",(unsigned long) asmap->parityInfo->next->bufPtr); RF_ASSERT(asmap->parityInfo->next->next == NULL); } printf("]\n\t"); } for (i=0,p=asmap->physInfo; p; p=p->next,i++) { printf("SU r%d c%d s%d-%d ", p->row, p->col, p->startSector, p->startSector + p->numSector - 1); if (prbuf) printf("b0x%lx ", (unsigned long) p->bufPtr); if (i && !(i&1)) printf("\n\t"); } printf("\n"); p = asm_h->stripeMap->failedPDA; if (asm_h->stripeMap->numDataFailed + asm_h->stripeMap->numParityFailed > 1) printf("[multiple failures]\n"); else if (asm_h->stripeMap->numDataFailed + asm_h->stripeMap->numParityFailed > 0) printf("\t[Failed PDA: r%d c%d s%d-%d]\n",p->row, p->col, p->startSector, p->startSector + p->numSector-1); }}void rf_PrintRaidAddressInfo(raidPtr, raidAddr, numBlocks) RF_Raid_t *raidPtr; RF_RaidAddr_t raidAddr; RF_SectorCount_t numBlocks;{ RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; RF_RaidAddr_t ra, sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr); printf("Raid addrs of SU boundaries from start of stripe to end of access:\n\t"); for (ra = sosAddr; ra <= raidAddr + numBlocks; ra += layoutPtr->sectorsPerStripeUnit) { printf("%ld (0x%lx), ",ra, ra); } printf("\n"); printf("Offset into stripe unit: %ld (0x%lx)\n", raidAddr % layoutPtr->sectorsPerStripeUnit,raidAddr % layoutPtr->sectorsPerStripeUnit);}/* given a parity descriptor and the starting address within a stripe, range restrict the parity descriptor to touch only the correct stuff.*/void rf_ASMParityAdjust( RF_PhysDiskAddr_t *toAdjust, RF_StripeNum_t startAddrWithinStripe, RF_SectorNum_t endAddress, RF_RaidLayout_t *layoutPtr, RF_AccessStripeMap_t *asm_p){ RF_PhysDiskAddr_t *new_pda; /* when we're accessing only a portion of one stripe unit, we want the parity descriptor * to identify only the chunk of parity associated with the data. When the access spans * exactly one stripe unit boundary and is less than a stripe unit in size, it uses two disjoint * regions of the parity unit. When an access spans more than one stripe unit boundary, it * uses all of the parity unit. * * To better handle the case where stripe units are small, we may eventually want to change * the 2nd case so that if the SU size is below some threshold, we just read/write the whole * thing instead of breaking it up into two accesses. */ if (asm_p->numStripeUnitsAccessed == 1) { int x = (startAddrWithinStripe % layoutPtr->sectorsPerStripeUnit); toAdjust->startSector += x; toAdjust->raidAddress += x; toAdjust->numSector = asm_p->physInfo->numSector; RF_ASSERT(toAdjust->numSector != 0); } else if (asm_p->numStripeUnitsAccessed == 2 && asm_p->totalSectorsAccessed < layoutPtr->sectorsPerStripeUnit) { int x = (startAddrWithinStripe % layoutPtr->sectorsPerStripeUnit); /* create a second pda and copy the parity map info into it */ RF_ASSERT(toAdjust->next == NULL); new_pda = toAdjust->next = rf_AllocPhysDiskAddr(); *new_pda = *toAdjust; /* structure assignment */ new_pda->next = NULL; /* adjust the start sector & number of blocks for the first parity pda */ toAdjust->startSector += x; toAdjust->raidAddress += x; toAdjust->numSector = rf_RaidAddressOfNextStripeUnitBoundary(layoutPtr, startAddrWithinStripe) - startAddrWithinStripe; RF_ASSERT(toAdjust->numSector != 0); /* adjust the second pda */ new_pda->numSector = endAddress - rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr, endAddress); /*new_pda->raidAddress = rf_RaidAddressOfNextStripeUnitBoundary(layoutPtr, toAdjust->raidAddress);*/ RF_ASSERT(new_pda->numSector != 0); }}/* Check if a disk has been spared or failed. If spared, redirect the I/O. If it has been failed, record it in the asm pointer. Fourth arg is whether data or parity.*/void rf_ASMCheckStatus( RF_Raid_t *raidPtr, RF_PhysDiskAddr_t *pda_p, RF_AccessStripeMap_t *asm_p, RF_RaidDisk_t **disks, int parity){ RF_DiskStatus_t dstatus; RF_RowCol_t frow, fcol; dstatus = disks[pda_p->row][pda_p->col].status; if (dstatus == rf_ds_spared) { /* if the disk has been spared, redirect access to the spare */ frow = pda_p->row; fcol = pda_p->col; pda_p->row = disks[frow][fcol].spareRow; pda_p->col = disks[frow][fcol].spareCol; } else if (dstatus == rf_ds_dist_spared) { /* ditto if disk has been spared to dist spare space */ RF_RowCol_t or = pda_p->row, oc=pda_p->col; RF_SectorNum_t oo = pda_p->startSector; if (pda_p -> type == RF_PDA_TYPE_DATA) raidPtr->Layout.map->MapSector(raidPtr, pda_p->raidAddress, &pda_p->row, &pda_p->col, &pda_p->startSector, RF_REMAP); else raidPtr->Layout.map->MapParity(raidPtr, pda_p->raidAddress, &pda_p->row, &pda_p->col, &pda_p->startSector, RF_REMAP); if (rf_mapDebug) printf("Redirected r %d c %d o %ld -> r%d c %d o %ld\n",or,oc,oo, pda_p->row,pda_p->col,pda_p->startSector); } else if (RF_DEAD_DISK(dstatus)) { /* if the disk is inaccessible, mark the failure */ if (parity) asm_p->numParityFailed++; else asm_p->numDataFailed++; switch (asm_p->numParityFailed + asm_p->numDataFailed) { case 1: asm_p->failedPDA = pda_p; break; case 2: asm_p->failedPDAtwo = pda_p; default: break; } } /* the redirected access should never span a stripe unit boundary */ RF_ASSERT(rf_RaidAddressToStripeUnitID(&raidPtr->Layout,pda_p->raidAddress) == rf_RaidAddressToStripeUnitID(&raidPtr->Layout,pda_p->raidAddress + pda_p->numSector -1)); RF_ASSERT(pda_p->col != -1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -