📄 rf_decluster.c
字号:
RF_ASSERT( *col != -1 );}/* returns an array of ints identifying the disks that comprise the stripe containing the indicated address. * the caller must _never_ attempt to modify this array. */void rf_IdentifyStripeDeclustered( RF_Raid_t *raidPtr, RF_RaidAddr_t addr, RF_RowCol_t **diskids, RF_RowCol_t *outRow){ RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo; RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable; RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs * layoutPtr->SUsPerPU; RF_StripeNum_t base_suid = 0; RF_StripeNum_t SUID = rf_RaidAddressToStripeUnitID(layoutPtr, addr); RF_StripeNum_t stripeID, FullTableID; int tableOffset; rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid); FullTableID = SUID / sus_per_fulltable; /* fulltable ID within array (across rows) */ *outRow = FullTableID % raidPtr->numRow; stripeID = rf_StripeUnitIDToStripeID(layoutPtr, SUID); /* find stripe offset into array */ tableOffset = (stripeID % info->BlocksPerTable); /* find offset into block design table */ *diskids = info->LayoutTable[tableOffset];}/* This returns the default head-separation limit, which is measured * in "required units for reconstruction". Each time a disk fetches * a unit, it bumps a counter. The head-sep code prohibits any disk * from getting more than headSepLimit counter values ahead of any * other. * * We assume here that the number of floating recon buffers is already * set. There are r stripes to be reconstructed in each table, and so * if we have a total of B buffers, we can have at most B/r tables * under recon at any one time. In each table, lambda units are required * from each disk, so given B buffers, the head sep limit has to be * (lambda*B)/r units. We subtract one to avoid weird boundary cases. * * for example, suppose were given 50 buffers, r=19, and lambda=4 as in * the 20.5 design. There are 19 stripes/table to be reconstructed, so * we can have 50/19 tables concurrently under reconstruction, which means * we can allow the fastest disk to get 50/19 tables ahead of the slower * disk. There are lambda "required units" for each disk, so the fastest * disk can get 4*50/19 = 10 counter values ahead of the slowest. * * If numBufsToAccumulate is not 1, we need to limit the head sep further * because multiple bufs will be required for each stripe under recon. */RF_HeadSepLimit_t rf_GetDefaultHeadSepLimitDeclustered( RF_Raid_t *raidPtr){ RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; return(info->Lambda * raidPtr->numFloatingReconBufs / info->TableDepthInPUs / rf_numBufsToAccumulate);}/* returns the default number of recon buffers to use. The value * is somewhat arbitrary...it's intended to be large enough to allow * for a reasonably large head-sep limit, but small enough that you * don't use up all your system memory with buffers. */int rf_GetDefaultNumFloatingReconBuffersDeclustered(RF_Raid_t *raidPtr){ return(100 * rf_numBufsToAccumulate);}/* sectors in the last fulltable of the array need to be handled * specially since this fulltable can be incomplete. this function * changes the values of certain params to handle this. * * the idea here is that MapSector et. al. figure out which disk the * addressed unit lives on by computing the modulos of the unit number * with the number of units per fulltable, table, etc. In the last * fulltable, there are fewer units per fulltable, so we need to adjust * the number of user data units per fulltable to reflect this. * * so, we (1) convert the fulltable size and depth parameters to * the size of the partial fulltable at the end, (2) compute the * disk sector offset where this fulltable starts, and (3) convert * the users stripe unit number from an offset into the array to * an offset into the last fulltable. */void rf_decluster_adjust_params( RF_RaidLayout_t *layoutPtr, RF_StripeNum_t *SUID, RF_StripeCount_t *sus_per_fulltable, RF_StripeCount_t *fulltable_depth, RF_StripeNum_t *base_suid){ RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo; char pc = layoutPtr->map->parityConfig; if (*SUID >= info->FullTableLimitSUID) { /* new full table size is size of last full table on disk */ *sus_per_fulltable = info->ExtraTablesPerDisk * info->SUsPerTable; /* new full table depth is corresponding depth */ *fulltable_depth = info->ExtraTablesPerDisk * info->TableDepthInPUs * layoutPtr->SUsPerPU; /* set up the new base offset */ *base_suid = info->DiskOffsetOfLastFullTableInSUs; /* convert users array address to an offset into the last fulltable */ *SUID -= info->FullTableLimitSUID; }}/* * map a stripe ID to a parity stripe ID. * See comment above RaidAddressToParityStripeID in layout.c. */void rf_MapSIDToPSIDDeclustered( RF_RaidLayout_t *layoutPtr, RF_StripeNum_t stripeID, RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru){ RF_DeclusteredConfigInfo_t *info; info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo; *psID = (stripeID / (layoutPtr->SUsPerPU * info->BlocksPerTable)) * info->BlocksPerTable + (stripeID % info->BlocksPerTable); *which_ru = (stripeID % (info->BlocksPerTable * layoutPtr->SUsPerPU)) / info->BlocksPerTable; RF_ASSERT( (*which_ru) < layoutPtr->SUsPerPU/layoutPtr->SUsPerRU);}/* * Called from MapSector and MapParity to retarget an access at the spare unit. * Modifies the "col" and "outSU" parameters only. */void rf_remap_to_spare_space( RF_RaidLayout_t *layoutPtr, RF_DeclusteredConfigInfo_t *info, RF_RowCol_t row, RF_StripeNum_t FullTableID, RF_StripeNum_t TableID, RF_SectorNum_t BlockID, RF_StripeNum_t base_suid, RF_StripeNum_t SpareRegion, RF_RowCol_t *outCol, RF_StripeNum_t *outSU){ RF_StripeNum_t ftID, spareTableStartSU, TableInSpareRegion, lastSROffset, which_ft; /* * note that FullTableID and hence SpareRegion may have gotten * tweaked by rf_decluster_adjust_params. We detect this by * noticing that base_suid is not 0. */ if (base_suid == 0) { ftID = FullTableID; } else { /* * There may be > 1.0 full tables in the last (i.e. partial) * spare region. find out which of these we're in. */ lastSROffset = info->NumCompleteSRs * info->SpareRegionDepthInSUs; which_ft = (info->DiskOffsetOfLastFullTableInSUs - lastSROffset) / (info->FullTableDepthInPUs * layoutPtr->SUsPerPU); /* compute the actual full table ID */ ftID = info->DiskOffsetOfLastFullTableInSUs / (info->FullTableDepthInPUs * layoutPtr->SUsPerPU) + which_ft; SpareRegion = info->NumCompleteSRs; } TableInSpareRegion = (ftID * info->NumParityReps + TableID) % info->TablesPerSpareRegion; *outCol = info->SpareTable[TableInSpareRegion][BlockID].spareDisk; RF_ASSERT( *outCol != -1); spareTableStartSU = (SpareRegion == info->NumCompleteSRs) ? info->DiskOffsetOfLastFullTableInSUs + info->ExtraTablesPerDisk * info->TableDepthInPUs * layoutPtr->SUsPerPU : (SpareRegion+1) * info->SpareRegionDepthInSUs - info->SpareSpaceDepthPerRegionInSUs; *outSU = spareTableStartSU + info->SpareTable[TableInSpareRegion][BlockID].spareBlockOffsetInSUs; if (*outSU >= layoutPtr->stripeUnitsPerDisk) { printf("rf_remap_to_spare_space: invalid remapped disk SU offset %ld\n",*outSU); }}int rf_InstallSpareTable( RF_Raid_t *raidPtr, RF_RowCol_t frow, RF_RowCol_t fcol){ RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; RF_SparetWait_t *req; int retcode; RF_Malloc(req, sizeof(*req), (RF_SparetWait_t *)); req->C = raidPtr->numCol; req->G = raidPtr->Layout.numDataCol + raidPtr->Layout.numParityCol; req->fcol = fcol; req->SUsPerPU = raidPtr->Layout.SUsPerPU; req->TablesPerSpareRegion = info->TablesPerSpareRegion; req->BlocksPerTable = info->BlocksPerTable; req->TableDepthInPUs = info->TableDepthInPUs; req->SpareSpaceDepthPerRegionInSUs = info->SpareSpaceDepthPerRegionInSUs;#ifndef KERNEL info->SpareTable = rf_ReadSpareTable(req, info->sparemap_fname); RF_Free(req, sizeof(*req)); retcode = (info->SpareTable) ? 0 : 1;#else /* !KERNEL */ retcode = rf_GetSpareTableFromDaemon(req); RF_ASSERT(!retcode); /* XXX -- fix this to recover gracefully -- XXX */#endif /* !KERNEL */ return(retcode);}#ifdef KERNEL/* * Invoked via ioctl to install a spare table in the kernel. */int rf_SetSpareTable(raidPtr, data) RF_Raid_t *raidPtr; void *data;{ RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; RF_SpareTableEntry_t **ptrs; int i, retcode; /* what we need to copyin is a 2-d array, so first copyin the user pointers to the rows in the table */ RF_Malloc(ptrs, info->TablesPerSpareRegion * sizeof(RF_SpareTableEntry_t *), (RF_SpareTableEntry_t **)); retcode = copyin((caddr_t) data, (caddr_t) ptrs, info->TablesPerSpareRegion * sizeof(RF_SpareTableEntry_t *)); if (retcode) return(retcode); /* now allocate kernel space for the row pointers */ RF_Malloc(info->SpareTable, info->TablesPerSpareRegion * sizeof(RF_SpareTableEntry_t *), (RF_SpareTableEntry_t **)); /* now allocate kernel space for each row in the table, and copy it in from user space */ for (i=0; i<info->TablesPerSpareRegion; i++) { RF_Malloc(info->SpareTable[i], info->BlocksPerTable * sizeof(RF_SpareTableEntry_t), (RF_SpareTableEntry_t *)); retcode = copyin(ptrs[i], info->SpareTable[i], info->BlocksPerTable * sizeof(RF_SpareTableEntry_t)); if (retcode) { info->SpareTable = NULL; /* blow off the memory we've allocated */ return(retcode); } } /* free up the temporary array we used */ RF_Free(ptrs, info->TablesPerSpareRegion * sizeof(RF_SpareTableEntry_t *)); return(0);}#endif /* KERNEL */RF_ReconUnitCount_t rf_GetNumSpareRUsDeclustered(raidPtr) RF_Raid_t *raidPtr;{ RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; return( ((RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo)->TotSparePUsPerDisk );}void rf_FreeSpareTable(raidPtr) RF_Raid_t *raidPtr;{ long i; RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo; RF_SpareTableEntry_t **table = info->SpareTable; for (i=0; i<info->TablesPerSpareRegion; i++) {RF_Free(table[i], info->BlocksPerTable * sizeof(RF_SpareTableEntry_t));} RF_Free(table, info->TablesPerSpareRegion * sizeof(RF_SpareTableEntry_t *)); info->SpareTable = (RF_SpareTableEntry_t **) NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -