1 1.51 oster /* $NetBSD: rf_map.c,v 1.51 2021/07/23 00:54:45 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: Mark Holland 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 * map.c -- main code for mapping RAID addresses to physical disk addresses 32 1.1 oster * 33 1.1 oster **************************************************************************/ 34 1.9 lukem 35 1.9 lukem #include <sys/cdefs.h> 36 1.51 oster __KERNEL_RCSID(0, "$NetBSD: rf_map.c,v 1.51 2021/07/23 00:54:45 oster Exp $"); 37 1.1 oster 38 1.7 oster #include <dev/raidframe/raidframevar.h> 39 1.7 oster 40 1.1 oster #include "rf_threadstuff.h" 41 1.1 oster #include "rf_raid.h" 42 1.1 oster #include "rf_general.h" 43 1.1 oster #include "rf_map.h" 44 1.1 oster #include "rf_shutdown.h" 45 1.1 oster 46 1.51 oster static void rf_FreePDAList(RF_Raid_t *raidPtr, RF_PhysDiskAddr_t *pda_list); 47 1.51 oster static void rf_FreeASMList(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asm_list); 48 1.1 oster 49 1.21 oster /*************************************************************************** 50 1.1 oster * 51 1.21 oster * MapAccess -- main 1st order mapping routine. Maps an access in the 52 1.21 oster * RAID address space to the corresponding set of physical disk 53 1.21 oster * addresses. The result is returned as a list of AccessStripeMap 54 1.21 oster * structures, one per stripe accessed. Each ASM structure contains a 55 1.21 oster * pointer to a list of PhysDiskAddr structures, which describe the 56 1.25 oster * physical locations touched by the user access. Note that this 57 1.25 oster * routine returns only static mapping information, i.e. the list of 58 1.25 oster * physical addresses returned does not necessarily identify the set 59 1.25 oster * of physical locations that will actually be read or written. The 60 1.25 oster * routine also maps the parity. The physical disk location returned 61 1.25 oster * always indicates the entire parity unit, even when only a subset of 62 1.25 oster * it is being accessed. This is because an access that is not stripe 63 1.25 oster * unit aligned but that spans a stripe unit boundary may require 64 1.25 oster * access two distinct portions of the parity unit, and we can't yet 65 1.25 oster * tell which portion(s) we'll actually need. We leave it up to the 66 1.25 oster * algorithm selection code to decide what subset of the parity unit 67 1.25 oster * to access. Note that addresses in the RAID address space must 68 1.25 oster * always be maintained as longs, instead of ints. 69 1.38 perry * 70 1.1 oster * This routine returns NULL if numBlocks is 0 71 1.1 oster * 72 1.26 oster * raidAddress - starting address in RAID address space 73 1.26 oster * numBlocks - number of blocks in RAID address space to access 74 1.50 msaitoh * buffer - buffer to supply/receive data 75 1.26 oster * remap - 1 => remap address to spare space 76 1.21 oster ***************************************************************************/ 77 1.1 oster 78 1.3 oster RF_AccessStripeMapHeader_t * 79 1.26 oster rf_MapAccess(RF_Raid_t *raidPtr, RF_RaidAddr_t raidAddress, 80 1.43 christos RF_SectorCount_t numBlocks, void *buffer, int remap) 81 1.3 oster { 82 1.3 oster RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); 83 1.3 oster RF_AccessStripeMapHeader_t *asm_hdr = NULL; 84 1.3 oster RF_AccessStripeMap_t *asm_list = NULL, *asm_p = NULL; 85 1.3 oster int faultsTolerated = layoutPtr->map->faultsTolerated; 86 1.25 oster /* we'll change raidAddress along the way */ 87 1.25 oster RF_RaidAddr_t startAddress = raidAddress; 88 1.3 oster RF_RaidAddr_t endAddress = raidAddress + numBlocks; 89 1.23 oster RF_RaidDisk_t *disks = raidPtr->Disks; 90 1.31 oster RF_PhysDiskAddr_t *pda_p; 91 1.31 oster #if (RF_INCLUDE_DECL_PQ > 0) || (RF_INCLUDE_RAID6 > 0) 92 1.31 oster RF_PhysDiskAddr_t *pda_q; 93 1.31 oster #endif 94 1.3 oster RF_StripeCount_t numStripes = 0; 95 1.38 perry RF_RaidAddr_t stripeRealEndAddress, stripeEndAddress, 96 1.25 oster nextStripeUnitAddress; 97 1.3 oster RF_RaidAddr_t startAddrWithinStripe, lastRaidAddr; 98 1.3 oster RF_StripeCount_t totStripes; 99 1.3 oster RF_StripeNum_t stripeID, lastSID, SUID, lastSUID; 100 1.3 oster RF_AccessStripeMap_t *asmList, *t_asm; 101 1.3 oster RF_PhysDiskAddr_t *pdaList, *t_pda; 102 1.3 oster 103 1.3 oster /* allocate all the ASMs and PDAs up front */ 104 1.3 oster lastRaidAddr = raidAddress + numBlocks - 1; 105 1.3 oster stripeID = rf_RaidAddressToStripeID(layoutPtr, raidAddress); 106 1.3 oster lastSID = rf_RaidAddressToStripeID(layoutPtr, lastRaidAddr); 107 1.3 oster totStripes = lastSID - stripeID + 1; 108 1.3 oster SUID = rf_RaidAddressToStripeUnitID(layoutPtr, raidAddress); 109 1.3 oster lastSUID = rf_RaidAddressToStripeUnitID(layoutPtr, lastRaidAddr); 110 1.3 oster 111 1.51 oster asmList = rf_AllocASMList(raidPtr, totStripes); 112 1.25 oster 113 1.25 oster /* may also need pda(s) per stripe for parity */ 114 1.51 oster pdaList = rf_AllocPDAList(raidPtr, lastSUID - SUID + 1 + 115 1.38 perry faultsTolerated * totStripes); 116 1.25 oster 117 1.3 oster 118 1.3 oster if (raidAddress + numBlocks > raidPtr->totalSectors) { 119 1.3 oster RF_ERRORMSG1("Unable to map access because offset (%d) was invalid\n", 120 1.3 oster (int) raidAddress); 121 1.3 oster return (NULL); 122 1.3 oster } 123 1.15 oster #if RF_DEBUG_MAP 124 1.3 oster if (rf_mapDebug) 125 1.3 oster rf_PrintRaidAddressInfo(raidPtr, raidAddress, numBlocks); 126 1.15 oster #endif 127 1.3 oster for (; raidAddress < endAddress;) { 128 1.3 oster /* make the next stripe structure */ 129 1.3 oster RF_ASSERT(asmList); 130 1.3 oster t_asm = asmList; 131 1.3 oster asmList = asmList->next; 132 1.48 christos memset(t_asm, 0, sizeof(*t_asm)); 133 1.3 oster if (!asm_p) 134 1.3 oster asm_list = asm_p = t_asm; 135 1.3 oster else { 136 1.3 oster asm_p->next = t_asm; 137 1.3 oster asm_p = asm_p->next; 138 1.3 oster } 139 1.3 oster numStripes++; 140 1.3 oster 141 1.3 oster /* map SUs from current location to the end of the stripe */ 142 1.3 oster asm_p->stripeID = /* rf_RaidAddressToStripeID(layoutPtr, 143 1.3 oster raidAddress) */ stripeID++; 144 1.3 oster stripeRealEndAddress = rf_RaidAddressOfNextStripeBoundary(layoutPtr, raidAddress); 145 1.3 oster stripeEndAddress = RF_MIN(endAddress, stripeRealEndAddress); 146 1.3 oster asm_p->raidAddress = raidAddress; 147 1.3 oster asm_p->endRaidAddress = stripeEndAddress; 148 1.3 oster 149 1.3 oster /* map each stripe unit in the stripe */ 150 1.3 oster pda_p = NULL; 151 1.25 oster 152 1.25 oster /* Raid addr of start of portion of access that is 153 1.25 oster within this stripe */ 154 1.38 perry startAddrWithinStripe = raidAddress; 155 1.25 oster 156 1.3 oster for (; raidAddress < stripeEndAddress;) { 157 1.3 oster RF_ASSERT(pdaList); 158 1.3 oster t_pda = pdaList; 159 1.3 oster pdaList = pdaList->next; 160 1.48 christos memset(t_pda, 0, sizeof(*t_pda)); 161 1.3 oster if (!pda_p) 162 1.3 oster asm_p->physInfo = pda_p = t_pda; 163 1.3 oster else { 164 1.3 oster pda_p->next = t_pda; 165 1.3 oster pda_p = pda_p->next; 166 1.3 oster } 167 1.3 oster 168 1.3 oster pda_p->type = RF_PDA_TYPE_DATA; 169 1.38 perry (layoutPtr->map->MapSector) (raidPtr, raidAddress, 170 1.38 perry &(pda_p->col), 171 1.38 perry &(pda_p->startSector), 172 1.25 oster remap); 173 1.25 oster 174 1.25 oster /* mark any failures we find. failedPDA is 175 1.25 oster * don't-care if there is more than one 176 1.25 oster * failure */ 177 1.25 oster 178 1.25 oster /* the RAID address corresponding to this 179 1.25 oster physical diskaddress */ 180 1.38 perry pda_p->raidAddress = raidAddress; 181 1.3 oster nextStripeUnitAddress = rf_RaidAddressOfNextStripeUnitBoundary(layoutPtr, raidAddress); 182 1.3 oster pda_p->numSector = RF_MIN(endAddress, nextStripeUnitAddress) - raidAddress; 183 1.3 oster RF_ASSERT(pda_p->numSector != 0); 184 1.3 oster rf_ASMCheckStatus(raidPtr, pda_p, asm_p, disks, 0); 185 1.43 christos pda_p->bufPtr = (char *)buffer + rf_RaidAddressToByte(raidPtr, (raidAddress - startAddress)); 186 1.3 oster asm_p->totalSectorsAccessed += pda_p->numSector; 187 1.3 oster asm_p->numStripeUnitsAccessed++; 188 1.3 oster 189 1.3 oster raidAddress = RF_MIN(endAddress, nextStripeUnitAddress); 190 1.3 oster } 191 1.3 oster 192 1.3 oster /* Map the parity. At this stage, the startSector and 193 1.25 oster * numSector fields for the parity unit are always set 194 1.25 oster * to indicate the entire parity unit. We may modify 195 1.25 oster * this after mapping the data portion. */ 196 1.3 oster switch (faultsTolerated) { 197 1.3 oster case 0: 198 1.3 oster break; 199 1.3 oster case 1: /* single fault tolerant */ 200 1.3 oster RF_ASSERT(pdaList); 201 1.3 oster t_pda = pdaList; 202 1.3 oster pdaList = pdaList->next; 203 1.48 christos memset(t_pda, 0, sizeof(*t_pda)); 204 1.3 oster pda_p = asm_p->parityInfo = t_pda; 205 1.3 oster pda_p->type = RF_PDA_TYPE_PARITY; 206 1.3 oster (layoutPtr->map->MapParity) (raidPtr, rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr, startAddrWithinStripe), 207 1.23 oster &(pda_p->col), &(pda_p->startSector), remap); 208 1.3 oster pda_p->numSector = layoutPtr->sectorsPerStripeUnit; 209 1.3 oster /* raidAddr may be needed to find unit to redirect to */ 210 1.3 oster pda_p->raidAddress = rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr, startAddrWithinStripe); 211 1.3 oster rf_ASMCheckStatus(raidPtr, pda_p, asm_p, disks, 1); 212 1.51 oster rf_ASMParityAdjust(raidPtr, asm_p->parityInfo, startAddrWithinStripe, endAddress, layoutPtr, asm_p); 213 1.3 oster 214 1.3 oster break; 215 1.31 oster #if (RF_INCLUDE_DECL_PQ > 0) || (RF_INCLUDE_RAID6 > 0) 216 1.3 oster case 2: /* two fault tolerant */ 217 1.3 oster RF_ASSERT(pdaList && pdaList->next); 218 1.3 oster t_pda = pdaList; 219 1.3 oster pdaList = pdaList->next; 220 1.48 christos memset(t_pda, 0, sizeof(*t_pda)); 221 1.3 oster pda_p = asm_p->parityInfo = t_pda; 222 1.3 oster pda_p->type = RF_PDA_TYPE_PARITY; 223 1.3 oster t_pda = pdaList; 224 1.3 oster pdaList = pdaList->next; 225 1.48 christos memset(t_pda, 0, sizeof(*t_pda)); 226 1.3 oster pda_q = asm_p->qInfo = t_pda; 227 1.3 oster pda_q->type = RF_PDA_TYPE_Q; 228 1.3 oster (layoutPtr->map->MapParity) (raidPtr, rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr, startAddrWithinStripe), 229 1.23 oster &(pda_p->col), &(pda_p->startSector), remap); 230 1.3 oster (layoutPtr->map->MapQ) (raidPtr, rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr, startAddrWithinStripe), 231 1.23 oster &(pda_q->col), &(pda_q->startSector), remap); 232 1.3 oster pda_q->numSector = pda_p->numSector = layoutPtr->sectorsPerStripeUnit; 233 1.3 oster /* raidAddr may be needed to find unit to redirect to */ 234 1.3 oster pda_p->raidAddress = rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr, startAddrWithinStripe); 235 1.3 oster pda_q->raidAddress = rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr, startAddrWithinStripe); 236 1.3 oster /* failure mode stuff */ 237 1.3 oster rf_ASMCheckStatus(raidPtr, pda_p, asm_p, disks, 1); 238 1.3 oster rf_ASMCheckStatus(raidPtr, pda_q, asm_p, disks, 1); 239 1.51 oster rf_ASMParityAdjust(raidPtr, asm_p->parityInfo, startAddrWithinStripe, endAddress, layoutPtr, asm_p); 240 1.51 oster rf_ASMParityAdjust(raidPtr, asm_p->qInfo, startAddrWithinStripe, endAddress, layoutPtr, asm_p); 241 1.3 oster break; 242 1.31 oster #endif 243 1.3 oster } 244 1.3 oster } 245 1.3 oster RF_ASSERT(asmList == NULL && pdaList == NULL); 246 1.3 oster /* make the header structure */ 247 1.51 oster asm_hdr = rf_AllocAccessStripeMapHeader(raidPtr); 248 1.3 oster RF_ASSERT(numStripes == totStripes); 249 1.3 oster asm_hdr->numStripes = numStripes; 250 1.3 oster asm_hdr->stripeMap = asm_list; 251 1.3 oster 252 1.15 oster #if RF_DEBUG_MAP 253 1.3 oster if (rf_mapDebug) 254 1.3 oster rf_PrintAccessStripeMap(asm_hdr); 255 1.15 oster #endif 256 1.3 oster return (asm_hdr); 257 1.1 oster } 258 1.21 oster 259 1.21 oster /*************************************************************************** 260 1.21 oster * This routine walks through an ASM list and marks the PDAs that have 261 1.21 oster * failed. It's called only when a disk failure causes an in-flight 262 1.21 oster * DAG to fail. The parity may consist of two components, but we want 263 1.21 oster * to use only one failedPDA pointer. Thus we set failedPDA to point 264 1.21 oster * to the first parity component, and rely on the rest of the code to 265 1.21 oster * do the right thing with this. 266 1.21 oster ***************************************************************************/ 267 1.1 oster 268 1.38 perry void 269 1.38 perry rf_MarkFailuresInASMList(RF_Raid_t *raidPtr, 270 1.26 oster RF_AccessStripeMapHeader_t *asm_h) 271 1.3 oster { 272 1.23 oster RF_RaidDisk_t *disks = raidPtr->Disks; 273 1.3 oster RF_AccessStripeMap_t *asmap; 274 1.3 oster RF_PhysDiskAddr_t *pda; 275 1.3 oster 276 1.3 oster for (asmap = asm_h->stripeMap; asmap; asmap = asmap->next) { 277 1.25 oster asmap->numDataFailed = 0; 278 1.25 oster asmap->numParityFailed = 0; 279 1.25 oster asmap->numQFailed = 0; 280 1.3 oster asmap->numFailedPDAs = 0; 281 1.48 christos memset(asmap->failedPDAs, 0, 282 1.48 christos RF_MAX_FAILED_PDA * sizeof(*asmap->failedPDAs)); 283 1.3 oster for (pda = asmap->physInfo; pda; pda = pda->next) { 284 1.23 oster if (RF_DEAD_DISK(disks[pda->col].status)) { 285 1.3 oster asmap->numDataFailed++; 286 1.3 oster asmap->failedPDAs[asmap->numFailedPDAs] = pda; 287 1.3 oster asmap->numFailedPDAs++; 288 1.3 oster } 289 1.3 oster } 290 1.3 oster pda = asmap->parityInfo; 291 1.23 oster if (pda && RF_DEAD_DISK(disks[pda->col].status)) { 292 1.3 oster asmap->numParityFailed++; 293 1.3 oster asmap->failedPDAs[asmap->numFailedPDAs] = pda; 294 1.3 oster asmap->numFailedPDAs++; 295 1.3 oster } 296 1.3 oster pda = asmap->qInfo; 297 1.23 oster if (pda && RF_DEAD_DISK(disks[pda->col].status)) { 298 1.3 oster asmap->numQFailed++; 299 1.3 oster asmap->failedPDAs[asmap->numFailedPDAs] = pda; 300 1.3 oster asmap->numFailedPDAs++; 301 1.3 oster } 302 1.3 oster } 303 1.1 oster } 304 1.3 oster 305 1.21 oster /*************************************************************************** 306 1.1 oster * 307 1.21 oster * routines to allocate and free list elements. All allocation 308 1.21 oster * routines zero the structure before returning it. 309 1.1 oster * 310 1.21 oster * FreePhysDiskAddr is static. It should never be called directly, 311 1.21 oster * because FreeAccessStripeMap takes care of freeing the PhysDiskAddr 312 1.21 oster * list. 313 1.1 oster * 314 1.21 oster ***************************************************************************/ 315 1.1 oster 316 1.1 oster #define RF_MAX_FREE_ASMHDR 128 317 1.30 oster #define RF_MIN_FREE_ASMHDR 32 318 1.1 oster 319 1.1 oster #define RF_MAX_FREE_ASM 192 320 1.30 oster #define RF_MIN_FREE_ASM 64 321 1.1 oster 322 1.1 oster #define RF_MAX_FREE_PDA 192 323 1.30 oster #define RF_MIN_FREE_PDA 64 324 1.1 oster 325 1.34 oster #define RF_MAX_FREE_ASMHLE 64 326 1.34 oster #define RF_MIN_FREE_ASMHLE 16 327 1.34 oster 328 1.34 oster #define RF_MAX_FREE_FSS 128 329 1.34 oster #define RF_MIN_FREE_FSS 32 330 1.34 oster 331 1.34 oster #define RF_MAX_FREE_VFPLE 128 332 1.34 oster #define RF_MIN_FREE_VFPLE 32 333 1.34 oster 334 1.37 oster #define RF_MAX_FREE_VPLE 128 335 1.37 oster #define RF_MIN_FREE_VPLE 32 336 1.37 oster 337 1.34 oster 338 1.25 oster /* called at shutdown time. So far, all that is necessary is to 339 1.25 oster release all the free lists */ 340 1.1 oster static void rf_ShutdownMapModule(void *); 341 1.38 perry static void 342 1.51 oster rf_ShutdownMapModule(void *arg) 343 1.1 oster { 344 1.51 oster RF_Raid_t *raidPtr; 345 1.51 oster 346 1.51 oster raidPtr = (RF_Raid_t *) arg; 347 1.51 oster 348 1.51 oster pool_destroy(&raidPtr->pools.asm_hdr); 349 1.51 oster pool_destroy(&raidPtr->pools.asmap); 350 1.51 oster pool_destroy(&raidPtr->pools.asmhle); 351 1.51 oster pool_destroy(&raidPtr->pools.pda); 352 1.51 oster pool_destroy(&raidPtr->pools.fss); 353 1.51 oster pool_destroy(&raidPtr->pools.vfple); 354 1.51 oster pool_destroy(&raidPtr->pools.vple); 355 1.1 oster } 356 1.1 oster 357 1.38 perry int 358 1.51 oster rf_ConfigureMapModule(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr, 359 1.51 oster RF_Config_t *cfgPtr) 360 1.1 oster { 361 1.1 oster 362 1.51 oster rf_pool_init(raidPtr, raidPtr->poolNames.asm_hdr, &raidPtr->pools.asm_hdr, sizeof(RF_AccessStripeMapHeader_t), 363 1.51 oster "asmhdr", RF_MIN_FREE_ASMHDR, RF_MAX_FREE_ASMHDR); 364 1.51 oster rf_pool_init(raidPtr, raidPtr->poolNames.asmap, &raidPtr->pools.asmap, sizeof(RF_AccessStripeMap_t), 365 1.51 oster "asmap", RF_MIN_FREE_ASM, RF_MAX_FREE_ASM); 366 1.51 oster rf_pool_init(raidPtr, raidPtr->poolNames.asmhle, &raidPtr->pools.asmhle, sizeof(RF_ASMHeaderListElem_t), 367 1.51 oster "asmhle", RF_MIN_FREE_ASMHLE, RF_MAX_FREE_ASMHLE); 368 1.51 oster rf_pool_init(raidPtr, raidPtr->poolNames.pda, &raidPtr->pools.pda, sizeof(RF_PhysDiskAddr_t), 369 1.51 oster "pda", RF_MIN_FREE_PDA, RF_MAX_FREE_PDA); 370 1.51 oster rf_pool_init(raidPtr, raidPtr->poolNames.fss, &raidPtr->pools.fss, sizeof(RF_FailedStripe_t), 371 1.51 oster "fss", RF_MIN_FREE_FSS, RF_MAX_FREE_FSS); 372 1.51 oster rf_pool_init(raidPtr, raidPtr->poolNames.vfple, &raidPtr->pools.vfple, sizeof(RF_VoidFunctionPointerListElem_t), 373 1.51 oster "vfple", RF_MIN_FREE_VFPLE, RF_MAX_FREE_VFPLE); 374 1.51 oster rf_pool_init(raidPtr, raidPtr->poolNames.vple, &raidPtr->pools.vple, sizeof(RF_VoidPointerListElem_t), 375 1.51 oster "vple", RF_MIN_FREE_VPLE, RF_MAX_FREE_VPLE); 376 1.51 oster rf_ShutdownCreate(listp, rf_ShutdownMapModule, raidPtr); 377 1.29 oster 378 1.3 oster return (0); 379 1.1 oster } 380 1.1 oster 381 1.3 oster RF_AccessStripeMapHeader_t * 382 1.51 oster rf_AllocAccessStripeMapHeader(RF_Raid_t *raidPtr) 383 1.1 oster { 384 1.51 oster return pool_get(&raidPtr->pools.asm_hdr, PR_WAITOK | PR_ZERO); 385 1.1 oster } 386 1.1 oster 387 1.38 perry void 388 1.51 oster rf_FreeAccessStripeMapHeader(RF_Raid_t *raidPtr, RF_AccessStripeMapHeader_t *p) 389 1.1 oster { 390 1.51 oster pool_put(&raidPtr->pools.asm_hdr, p); 391 1.1 oster } 392 1.1 oster 393 1.34 oster 394 1.34 oster RF_VoidFunctionPointerListElem_t * 395 1.51 oster rf_AllocVFPListElem(RF_Raid_t *raidPtr) 396 1.34 oster { 397 1.51 oster return pool_get(&raidPtr->pools.vfple, PR_WAITOK | PR_ZERO); 398 1.34 oster } 399 1.34 oster 400 1.34 oster void 401 1.51 oster rf_FreeVFPListElem(RF_Raid_t *raidPtr, RF_VoidFunctionPointerListElem_t *p) 402 1.34 oster { 403 1.34 oster 404 1.51 oster pool_put(&raidPtr->pools.vfple, p); 405 1.34 oster } 406 1.34 oster 407 1.37 oster 408 1.37 oster RF_VoidPointerListElem_t * 409 1.51 oster rf_AllocVPListElem(RF_Raid_t *raidPtr) 410 1.37 oster { 411 1.51 oster return pool_get(&raidPtr->pools.vple, PR_WAITOK | PR_ZERO); 412 1.37 oster } 413 1.37 oster 414 1.37 oster void 415 1.51 oster rf_FreeVPListElem(RF_Raid_t *raidPtr, RF_VoidPointerListElem_t *p) 416 1.37 oster { 417 1.37 oster 418 1.51 oster pool_put(&raidPtr->pools.vple, p); 419 1.37 oster } 420 1.37 oster 421 1.34 oster RF_ASMHeaderListElem_t * 422 1.51 oster rf_AllocASMHeaderListElem(RF_Raid_t *raidPtr) 423 1.34 oster { 424 1.51 oster return pool_get(&raidPtr->pools.asmhle, PR_WAITOK | PR_ZERO); 425 1.34 oster } 426 1.34 oster 427 1.34 oster void 428 1.51 oster rf_FreeASMHeaderListElem(RF_Raid_t *raidPtr, RF_ASMHeaderListElem_t *p) 429 1.34 oster { 430 1.34 oster 431 1.51 oster pool_put(&raidPtr->pools.asmhle, p); 432 1.34 oster } 433 1.34 oster 434 1.34 oster RF_FailedStripe_t * 435 1.51 oster rf_AllocFailedStripeStruct(RF_Raid_t *raidPtr) 436 1.34 oster { 437 1.51 oster return pool_get(&raidPtr->pools.fss, PR_WAITOK | PR_ZERO); 438 1.34 oster } 439 1.34 oster 440 1.34 oster void 441 1.51 oster rf_FreeFailedStripeStruct(RF_Raid_t *raidPtr, RF_FailedStripe_t *p) 442 1.34 oster { 443 1.51 oster pool_put(&raidPtr->pools.fss, p); 444 1.34 oster } 445 1.34 oster 446 1.34 oster 447 1.34 oster 448 1.34 oster 449 1.34 oster 450 1.3 oster RF_PhysDiskAddr_t * 451 1.51 oster rf_AllocPhysDiskAddr(RF_Raid_t *raidPtr) 452 1.1 oster { 453 1.51 oster return pool_get(&raidPtr->pools.pda, PR_WAITOK | PR_ZERO); 454 1.1 oster } 455 1.25 oster /* allocates a list of PDAs, locking the free list only once when we 456 1.25 oster * have to call calloc, we do it one component at a time to simplify 457 1.25 oster * the process of freeing the list at program shutdown. This should 458 1.25 oster * not be much of a performance hit, because it should be very 459 1.25 oster * infrequently executed. */ 460 1.3 oster RF_PhysDiskAddr_t * 461 1.51 oster rf_AllocPDAList(RF_Raid_t *raidPtr, int count) 462 1.1 oster { 463 1.24 oster RF_PhysDiskAddr_t *p, *prev; 464 1.24 oster int i; 465 1.24 oster 466 1.24 oster p = NULL; 467 1.24 oster prev = NULL; 468 1.24 oster for (i = 0; i < count; i++) { 469 1.51 oster p = pool_get(&raidPtr->pools.pda, PR_WAITOK); 470 1.24 oster p->next = prev; 471 1.24 oster prev = p; 472 1.24 oster } 473 1.1 oster 474 1.3 oster return (p); 475 1.1 oster } 476 1.1 oster 477 1.38 perry void 478 1.51 oster rf_FreePhysDiskAddr(RF_Raid_t *raidPtr, RF_PhysDiskAddr_t *p) 479 1.1 oster { 480 1.51 oster pool_put(&raidPtr->pools.pda, p); 481 1.1 oster } 482 1.1 oster 483 1.38 perry static void 484 1.51 oster rf_FreePDAList(RF_Raid_t *raidPtr, RF_PhysDiskAddr_t *pda_list) 485 1.1 oster { 486 1.24 oster RF_PhysDiskAddr_t *p, *tmp; 487 1.24 oster 488 1.27 oster p=pda_list; 489 1.24 oster while (p) { 490 1.24 oster tmp = p->next; 491 1.51 oster pool_put(&raidPtr->pools.pda, p); 492 1.24 oster p = tmp; 493 1.24 oster } 494 1.1 oster } 495 1.1 oster 496 1.25 oster /* this is essentially identical to AllocPDAList. I should combine 497 1.25 oster * the two. when we have to call calloc, we do it one component at a 498 1.25 oster * time to simplify the process of freeing the list at program 499 1.25 oster * shutdown. This should not be much of a performance hit, because it 500 1.25 oster * should be very infrequently executed. */ 501 1.3 oster RF_AccessStripeMap_t * 502 1.51 oster rf_AllocASMList(RF_Raid_t *raidPtr, int count) 503 1.1 oster { 504 1.24 oster RF_AccessStripeMap_t *p, *prev; 505 1.24 oster int i; 506 1.1 oster 507 1.24 oster p = NULL; 508 1.24 oster prev = NULL; 509 1.24 oster for (i = 0; i < count; i++) { 510 1.51 oster p = pool_get(&raidPtr->pools.asmap, PR_WAITOK); 511 1.24 oster p->next = prev; 512 1.24 oster prev = p; 513 1.24 oster } 514 1.3 oster return (p); 515 1.1 oster } 516 1.1 oster 517 1.38 perry static void 518 1.51 oster rf_FreeASMList(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asm_list) 519 1.3 oster { 520 1.24 oster RF_AccessStripeMap_t *p, *tmp; 521 1.24 oster 522 1.27 oster p=asm_list; 523 1.24 oster while (p) { 524 1.24 oster tmp = p->next; 525 1.51 oster pool_put(&raidPtr->pools.asmap, p); 526 1.24 oster p = tmp; 527 1.24 oster } 528 1.3 oster } 529 1.3 oster 530 1.38 perry void 531 1.51 oster rf_FreeAccessStripeMap(RF_Raid_t *raidPtr, RF_AccessStripeMapHeader_t *hdr) 532 1.3 oster { 533 1.28 oster RF_AccessStripeMap_t *p; 534 1.3 oster RF_PhysDiskAddr_t *pdp, *trailer, *pdaList = NULL, *pdaEnd = NULL; 535 1.47 oster int count = 0, t; 536 1.3 oster 537 1.3 oster for (p = hdr->stripeMap; p; p = p->next) { 538 1.3 oster 539 1.3 oster /* link the 3 pda lists into the accumulating pda list */ 540 1.3 oster 541 1.3 oster if (!pdaList) 542 1.3 oster pdaList = p->qInfo; 543 1.3 oster else 544 1.3 oster pdaEnd->next = p->qInfo; 545 1.3 oster for (trailer = NULL, pdp = p->qInfo; pdp;) { 546 1.3 oster trailer = pdp; 547 1.3 oster pdp = pdp->next; 548 1.3 oster count++; 549 1.3 oster } 550 1.3 oster if (trailer) 551 1.3 oster pdaEnd = trailer; 552 1.3 oster 553 1.3 oster if (!pdaList) 554 1.3 oster pdaList = p->parityInfo; 555 1.3 oster else 556 1.3 oster pdaEnd->next = p->parityInfo; 557 1.3 oster for (trailer = NULL, pdp = p->parityInfo; pdp;) { 558 1.3 oster trailer = pdp; 559 1.3 oster pdp = pdp->next; 560 1.3 oster count++; 561 1.3 oster } 562 1.3 oster if (trailer) 563 1.3 oster pdaEnd = trailer; 564 1.3 oster 565 1.3 oster if (!pdaList) 566 1.3 oster pdaList = p->physInfo; 567 1.3 oster else 568 1.3 oster pdaEnd->next = p->physInfo; 569 1.3 oster for (trailer = NULL, pdp = p->physInfo; pdp;) { 570 1.3 oster trailer = pdp; 571 1.3 oster pdp = pdp->next; 572 1.3 oster count++; 573 1.3 oster } 574 1.3 oster if (trailer) 575 1.3 oster pdaEnd = trailer; 576 1.3 oster } 577 1.3 oster 578 1.3 oster /* debug only */ 579 1.3 oster for (t = 0, pdp = pdaList; pdp; pdp = pdp->next) 580 1.3 oster t++; 581 1.3 oster RF_ASSERT(t == count); 582 1.3 oster 583 1.3 oster if (pdaList) 584 1.51 oster rf_FreePDAList(raidPtr, pdaList); 585 1.51 oster rf_FreeASMList(raidPtr, hdr->stripeMap); 586 1.51 oster rf_FreeAccessStripeMapHeader(raidPtr, hdr); 587 1.1 oster } 588 1.21 oster /* We can't use the large write optimization if there are any failures 589 1.21 oster * in the stripe. In the declustered layout, there is no way to 590 1.21 oster * immediately determine what disks constitute a stripe, so we 591 1.21 oster * actually have to hunt through the stripe looking for failures. The 592 1.21 oster * reason we map the parity instead of just using asm->parityInfo->col 593 1.21 oster * is because the latter may have been already redirected to a spare 594 1.21 oster * drive, which would mess up the computation of the stripe offset. 595 1.1 oster * 596 1.21 oster * ASSUMES AT MOST ONE FAILURE IN THE STRIPE. */ 597 1.38 perry int 598 1.26 oster rf_CheckStripeForFailures(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap) 599 1.3 oster { 600 1.23 oster RF_RowCol_t tcol, pcol, *diskids, i; 601 1.3 oster RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 602 1.3 oster RF_StripeCount_t stripeOffset; 603 1.3 oster int numFailures; 604 1.3 oster RF_RaidAddr_t sosAddr; 605 1.3 oster RF_SectorNum_t diskOffset, poffset; 606 1.3 oster 607 1.3 oster /* quick out in the fault-free case. */ 608 1.45 mrg rf_lock_mutex2(raidPtr->mutex); 609 1.3 oster numFailures = raidPtr->numFailures; 610 1.45 mrg rf_unlock_mutex2(raidPtr->mutex); 611 1.3 oster if (numFailures == 0) 612 1.3 oster return (0); 613 1.3 oster 614 1.38 perry sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, 615 1.25 oster asmap->raidAddress); 616 1.38 perry (layoutPtr->map->IdentifyStripe) (raidPtr, asmap->raidAddress, 617 1.25 oster &diskids); 618 1.38 perry (layoutPtr->map->MapParity) (raidPtr, asmap->raidAddress, 619 1.25 oster &pcol, &poffset, 0); /* get pcol */ 620 1.3 oster 621 1.25 oster /* this need not be true if we've redirected the access to a 622 1.25 oster * spare in another row RF_ASSERT(row == testrow); */ 623 1.3 oster stripeOffset = 0; 624 1.3 oster for (i = 0; i < layoutPtr->numDataCol + layoutPtr->numParityCol; i++) { 625 1.3 oster if (diskids[i] != pcol) { 626 1.23 oster if (RF_DEAD_DISK(raidPtr->Disks[diskids[i]].status)) { 627 1.23 oster if (raidPtr->status != rf_rs_reconstructing) 628 1.3 oster return (1); 629 1.23 oster RF_ASSERT(raidPtr->reconControl->fcol == diskids[i]); 630 1.3 oster layoutPtr->map->MapSector(raidPtr, 631 1.3 oster sosAddr + stripeOffset * layoutPtr->sectorsPerStripeUnit, 632 1.23 oster &tcol, &diskOffset, 0); 633 1.23 oster RF_ASSERT(tcol == diskids[i]); 634 1.23 oster if (!rf_CheckRUReconstructed(raidPtr->reconControl->reconMap, diskOffset)) 635 1.3 oster return (1); 636 1.3 oster asmap->flags |= RF_ASM_REDIR_LARGE_WRITE; 637 1.3 oster return (0); 638 1.3 oster } 639 1.3 oster stripeOffset++; 640 1.3 oster } 641 1.3 oster } 642 1.3 oster return (0); 643 1.1 oster } 644 1.18 oster #if (RF_INCLUDE_DECL_PQ > 0) || (RF_INCLUDE_RAID6 > 0) || (RF_INCLUDE_EVENODD >0) 645 1.1 oster /* 646 1.1 oster return the number of failed data units in the stripe. 647 1.1 oster */ 648 1.1 oster 649 1.38 perry int 650 1.26 oster rf_NumFailedDataUnitsInStripe(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap) 651 1.3 oster { 652 1.3 oster RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 653 1.23 oster RF_RowCol_t tcol, i; 654 1.3 oster RF_SectorNum_t diskOffset; 655 1.3 oster RF_RaidAddr_t sosAddr; 656 1.3 oster int numFailures; 657 1.3 oster 658 1.3 oster /* quick out in the fault-free case. */ 659 1.45 mrg rf_lock_mutex2(raidPtr->mutex); 660 1.3 oster numFailures = raidPtr->numFailures; 661 1.45 mrg rf_unlock_mutex2(raidPtr->mutex); 662 1.3 oster if (numFailures == 0) 663 1.3 oster return (0); 664 1.3 oster numFailures = 0; 665 1.3 oster 666 1.38 perry sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, 667 1.25 oster asmap->raidAddress); 668 1.3 oster for (i = 0; i < layoutPtr->numDataCol; i++) { 669 1.3 oster (layoutPtr->map->MapSector) (raidPtr, sosAddr + i * layoutPtr->sectorsPerStripeUnit, 670 1.40 oster &tcol, &diskOffset, 0); 671 1.23 oster if (RF_DEAD_DISK(raidPtr->Disks[tcol].status)) 672 1.3 oster numFailures++; 673 1.3 oster } 674 1.1 oster 675 1.3 oster return numFailures; 676 1.1 oster } 677 1.18 oster #endif 678 1.1 oster 679 1.25 oster /**************************************************************************** 680 1.1 oster * 681 1.1 oster * debug routines 682 1.1 oster * 683 1.25 oster ***************************************************************************/ 684 1.18 oster #if RF_DEBUG_MAP 685 1.38 perry void 686 1.26 oster rf_PrintAccessStripeMap(RF_AccessStripeMapHeader_t *asm_h) 687 1.1 oster { 688 1.3 oster rf_PrintFullAccessStripeMap(asm_h, 0); 689 1.1 oster } 690 1.18 oster #endif 691 1.1 oster 692 1.26 oster /* prbuf - flag to print buffer pointers */ 693 1.38 perry void 694 1.26 oster rf_PrintFullAccessStripeMap(RF_AccessStripeMapHeader_t *asm_h, int prbuf) 695 1.3 oster { 696 1.3 oster int i; 697 1.3 oster RF_AccessStripeMap_t *asmap = asm_h->stripeMap; 698 1.3 oster RF_PhysDiskAddr_t *p; 699 1.3 oster printf("%d stripes total\n", (int) asm_h->numStripes); 700 1.3 oster for (; asmap; asmap = asmap->next) { 701 1.3 oster /* printf("Num failures: %d\n",asmap->numDataFailed); */ 702 1.3 oster /* printf("Num sectors: 703 1.3 oster * %d\n",(int)asmap->totalSectorsAccessed); */ 704 1.3 oster printf("Stripe %d (%d sectors), failures: %d data, %d parity: ", 705 1.3 oster (int) asmap->stripeID, 706 1.3 oster (int) asmap->totalSectorsAccessed, 707 1.3 oster (int) asmap->numDataFailed, 708 1.3 oster (int) asmap->numParityFailed); 709 1.3 oster if (asmap->parityInfo) { 710 1.23 oster printf("Parity [c%d s%d-%d", asmap->parityInfo->col, 711 1.3 oster (int) asmap->parityInfo->startSector, 712 1.3 oster (int) (asmap->parityInfo->startSector + 713 1.3 oster asmap->parityInfo->numSector - 1)); 714 1.3 oster if (prbuf) 715 1.3 oster printf(" b0x%lx", (unsigned long) asmap->parityInfo->bufPtr); 716 1.3 oster if (asmap->parityInfo->next) { 717 1.23 oster printf(", c%d s%d-%d", asmap->parityInfo->next->col, 718 1.3 oster (int) asmap->parityInfo->next->startSector, 719 1.3 oster (int) (asmap->parityInfo->next->startSector + 720 1.3 oster asmap->parityInfo->next->numSector - 1)); 721 1.3 oster if (prbuf) 722 1.3 oster printf(" b0x%lx", (unsigned long) asmap->parityInfo->next->bufPtr); 723 1.3 oster RF_ASSERT(asmap->parityInfo->next->next == NULL); 724 1.3 oster } 725 1.3 oster printf("]\n\t"); 726 1.3 oster } 727 1.3 oster for (i = 0, p = asmap->physInfo; p; p = p->next, i++) { 728 1.23 oster printf("SU c%d s%d-%d ", p->col, (int) p->startSector, 729 1.3 oster (int) (p->startSector + p->numSector - 1)); 730 1.3 oster if (prbuf) 731 1.3 oster printf("b0x%lx ", (unsigned long) p->bufPtr); 732 1.3 oster if (i && !(i & 1)) 733 1.3 oster printf("\n\t"); 734 1.3 oster } 735 1.3 oster printf("\n"); 736 1.3 oster p = asm_h->stripeMap->failedPDAs[0]; 737 1.3 oster if (asm_h->stripeMap->numDataFailed + asm_h->stripeMap->numParityFailed > 1) 738 1.3 oster printf("[multiple failures]\n"); 739 1.3 oster else 740 1.3 oster if (asm_h->stripeMap->numDataFailed + asm_h->stripeMap->numParityFailed > 0) 741 1.23 oster printf("\t[Failed PDA: c%d s%d-%d]\n", p->col, 742 1.3 oster (int) p->startSector, (int) (p->startSector + p->numSector - 1)); 743 1.3 oster } 744 1.1 oster } 745 1.1 oster 746 1.15 oster #if RF_MAP_DEBUG 747 1.38 perry void 748 1.38 perry rf_PrintRaidAddressInfo(RF_Raid_t *raidPtr, RF_RaidAddr_t raidAddr, 749 1.26 oster RF_SectorCount_t numBlocks) 750 1.3 oster { 751 1.3 oster RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 752 1.3 oster RF_RaidAddr_t ra, sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr); 753 1.3 oster 754 1.3 oster printf("Raid addrs of SU boundaries from start of stripe to end of access:\n\t"); 755 1.3 oster for (ra = sosAddr; ra <= raidAddr + numBlocks; ra += layoutPtr->sectorsPerStripeUnit) { 756 1.3 oster printf("%d (0x%x), ", (int) ra, (int) ra); 757 1.3 oster } 758 1.3 oster printf("\n"); 759 1.3 oster printf("Offset into stripe unit: %d (0x%x)\n", 760 1.3 oster (int) (raidAddr % layoutPtr->sectorsPerStripeUnit), 761 1.3 oster (int) (raidAddr % layoutPtr->sectorsPerStripeUnit)); 762 1.3 oster } 763 1.15 oster #endif 764 1.25 oster /* given a parity descriptor and the starting address within a stripe, 765 1.25 oster * range restrict the parity descriptor to touch only the correct 766 1.25 oster * stuff. */ 767 1.38 perry void 768 1.51 oster rf_ASMParityAdjust(RF_Raid_t *raidPtr, 769 1.51 oster RF_PhysDiskAddr_t *toAdjust, 770 1.26 oster RF_StripeNum_t startAddrWithinStripe, 771 1.26 oster RF_SectorNum_t endAddress, 772 1.26 oster RF_RaidLayout_t *layoutPtr, 773 1.26 oster RF_AccessStripeMap_t *asm_p) 774 1.3 oster { 775 1.3 oster RF_PhysDiskAddr_t *new_pda; 776 1.3 oster 777 1.25 oster /* when we're accessing only a portion of one stripe unit, we 778 1.25 oster * want the parity descriptor to identify only the chunk of 779 1.25 oster * parity associated with the data. When the access spans 780 1.25 oster * exactly one stripe unit boundary and is less than a stripe 781 1.25 oster * unit in size, it uses two disjoint regions of the parity 782 1.25 oster * unit. When an access spans more than one stripe unit 783 1.25 oster * boundary, it uses all of the parity unit. 784 1.38 perry * 785 1.25 oster * To better handle the case where stripe units are small, we 786 1.25 oster * may eventually want to change the 2nd case so that if the 787 1.25 oster * SU size is below some threshold, we just read/write the 788 1.25 oster * whole thing instead of breaking it up into two accesses. */ 789 1.3 oster if (asm_p->numStripeUnitsAccessed == 1) { 790 1.3 oster int x = (startAddrWithinStripe % layoutPtr->sectorsPerStripeUnit); 791 1.3 oster toAdjust->startSector += x; 792 1.3 oster toAdjust->raidAddress += x; 793 1.3 oster toAdjust->numSector = asm_p->physInfo->numSector; 794 1.3 oster RF_ASSERT(toAdjust->numSector != 0); 795 1.3 oster } else 796 1.3 oster if (asm_p->numStripeUnitsAccessed == 2 && asm_p->totalSectorsAccessed < layoutPtr->sectorsPerStripeUnit) { 797 1.3 oster int x = (startAddrWithinStripe % layoutPtr->sectorsPerStripeUnit); 798 1.3 oster 799 1.3 oster /* create a second pda and copy the parity map info 800 1.3 oster * into it */ 801 1.3 oster RF_ASSERT(toAdjust->next == NULL); 802 1.38 perry /* the following will get freed in rf_FreeAccessStripeMap() via 803 1.35 oster rf_FreePDAList() */ 804 1.51 oster new_pda = toAdjust->next = rf_AllocPhysDiskAddr(raidPtr); 805 1.3 oster *new_pda = *toAdjust; /* structure assignment */ 806 1.3 oster new_pda->next = NULL; 807 1.3 oster 808 1.3 oster /* adjust the start sector & number of blocks for the 809 1.3 oster * first parity pda */ 810 1.3 oster toAdjust->startSector += x; 811 1.3 oster toAdjust->raidAddress += x; 812 1.3 oster toAdjust->numSector = rf_RaidAddressOfNextStripeUnitBoundary(layoutPtr, startAddrWithinStripe) - startAddrWithinStripe; 813 1.3 oster RF_ASSERT(toAdjust->numSector != 0); 814 1.3 oster 815 1.3 oster /* adjust the second pda */ 816 1.3 oster new_pda->numSector = endAddress - rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr, endAddress); 817 1.3 oster /* new_pda->raidAddress = 818 1.3 oster * rf_RaidAddressOfNextStripeUnitBoundary(layoutPtr, 819 1.3 oster * toAdjust->raidAddress); */ 820 1.3 oster RF_ASSERT(new_pda->numSector != 0); 821 1.3 oster } 822 1.1 oster } 823 1.11 oster 824 1.25 oster /* Check if a disk has been spared or failed. If spared, redirect the 825 1.46 oster * I/O. If it has been failed, record it in the asm pointer. Fifth 826 1.25 oster * arg is whether data or parity. */ 827 1.38 perry void 828 1.26 oster rf_ASMCheckStatus(RF_Raid_t *raidPtr, RF_PhysDiskAddr_t *pda_p, 829 1.26 oster RF_AccessStripeMap_t *asm_p, RF_RaidDisk_t *disks, 830 1.26 oster int parity) 831 1.3 oster { 832 1.3 oster RF_DiskStatus_t dstatus; 833 1.23 oster RF_RowCol_t fcol; 834 1.3 oster 835 1.23 oster dstatus = disks[pda_p->col].status; 836 1.3 oster 837 1.3 oster if (dstatus == rf_ds_spared) { 838 1.3 oster /* if the disk has been spared, redirect access to the spare */ 839 1.3 oster fcol = pda_p->col; 840 1.23 oster pda_p->col = disks[fcol].spareCol; 841 1.3 oster } else 842 1.3 oster if (dstatus == rf_ds_dist_spared) { 843 1.3 oster /* ditto if disk has been spared to dist spare space */ 844 1.15 oster #if RF_DEBUG_MAP 845 1.23 oster RF_RowCol_t oc = pda_p->col; 846 1.3 oster RF_SectorNum_t oo = pda_p->startSector; 847 1.15 oster #endif 848 1.3 oster if (pda_p->type == RF_PDA_TYPE_DATA) 849 1.23 oster raidPtr->Layout.map->MapSector(raidPtr, pda_p->raidAddress, &pda_p->col, &pda_p->startSector, RF_REMAP); 850 1.3 oster else 851 1.23 oster raidPtr->Layout.map->MapParity(raidPtr, pda_p->raidAddress, &pda_p->col, &pda_p->startSector, RF_REMAP); 852 1.3 oster 853 1.15 oster #if RF_DEBUG_MAP 854 1.3 oster if (rf_mapDebug) { 855 1.23 oster printf("Redirected c %d o %d -> c %d o %d\n", oc, (int) oo, 856 1.23 oster pda_p->col, (int) pda_p->startSector); 857 1.3 oster } 858 1.15 oster #endif 859 1.3 oster } else 860 1.3 oster if (RF_DEAD_DISK(dstatus)) { 861 1.3 oster /* if the disk is inaccessible, mark the 862 1.3 oster * failure */ 863 1.3 oster if (parity) 864 1.3 oster asm_p->numParityFailed++; 865 1.3 oster else { 866 1.3 oster asm_p->numDataFailed++; 867 1.3 oster } 868 1.3 oster asm_p->failedPDAs[asm_p->numFailedPDAs] = pda_p; 869 1.3 oster asm_p->numFailedPDAs++; 870 1.1 oster #if 0 871 1.3 oster switch (asm_p->numParityFailed + asm_p->numDataFailed) { 872 1.3 oster case 1: 873 1.3 oster asm_p->failedPDAs[0] = pda_p; 874 1.3 oster break; 875 1.3 oster case 2: 876 1.3 oster asm_p->failedPDAs[1] = pda_p; 877 1.3 oster default: 878 1.3 oster break; 879 1.3 oster } 880 1.1 oster #endif 881 1.3 oster } 882 1.3 oster /* the redirected access should never span a stripe unit boundary */ 883 1.3 oster RF_ASSERT(rf_RaidAddressToStripeUnitID(&raidPtr->Layout, pda_p->raidAddress) == 884 1.3 oster rf_RaidAddressToStripeUnitID(&raidPtr->Layout, pda_p->raidAddress + pda_p->numSector - 1)); 885 1.3 oster RF_ASSERT(pda_p->col != -1); 886 1.1 oster } 887