1 1.38 oster /* $NetBSD: rf_reconutil.c,v 1.38 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 * rf_reconutil.c -- reconstruction utilities 31 1.1 oster ********************************************/ 32 1.5 lukem 33 1.5 lukem #include <sys/cdefs.h> 34 1.38 oster __KERNEL_RCSID(0, "$NetBSD: rf_reconutil.c,v 1.38 2021/07/23 00:54:45 oster Exp $"); 35 1.1 oster 36 1.4 oster #include <dev/raidframe/raidframevar.h> 37 1.4 oster 38 1.1 oster #include "rf_raid.h" 39 1.1 oster #include "rf_desc.h" 40 1.1 oster #include "rf_reconutil.h" 41 1.1 oster #include "rf_reconbuffer.h" 42 1.1 oster #include "rf_general.h" 43 1.1 oster #include "rf_decluster.h" 44 1.1 oster #include "rf_raid5_rotatedspare.h" 45 1.1 oster #include "rf_interdecluster.h" 46 1.1 oster #include "rf_chaindecluster.h" 47 1.1 oster 48 1.1 oster /******************************************************************* 49 1.1 oster * allocates/frees the reconstruction control information structures 50 1.1 oster *******************************************************************/ 51 1.19 oster 52 1.19 oster /* fcol - failed column 53 1.19 oster * scol - identifies which spare we are using 54 1.19 oster */ 55 1.19 oster 56 1.3 oster RF_ReconCtrl_t * 57 1.25 perry rf_MakeReconControl(RF_RaidReconDesc_t *reconDesc, 58 1.19 oster RF_RowCol_t fcol, RF_RowCol_t scol) 59 1.1 oster { 60 1.3 oster RF_Raid_t *raidPtr = reconDesc->raidPtr; 61 1.3 oster RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 62 1.3 oster RF_ReconUnitCount_t RUsPerPU = layoutPtr->SUsPerPU / layoutPtr->SUsPerRU; 63 1.3 oster RF_ReconUnitCount_t numSpareRUs; 64 1.3 oster RF_ReconCtrl_t *reconCtrlPtr; 65 1.3 oster RF_ReconBuffer_t *rbuf; 66 1.14 jdolecek const RF_LayoutSW_t *lp; 67 1.12 oster #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0) 68 1.12 oster int retcode; 69 1.12 oster #endif 70 1.3 oster RF_RowCol_t i; 71 1.3 oster 72 1.3 oster lp = raidPtr->Layout.map; 73 1.3 oster 74 1.3 oster /* make and zero the global reconstruction structure and the per-disk 75 1.3 oster * structure */ 76 1.37 christos reconCtrlPtr = RF_Malloc(sizeof(*reconCtrlPtr)); 77 1.11 oster 78 1.11 oster /* note: this zeros the perDiskInfo */ 79 1.37 christos reconCtrlPtr->perDiskInfo = RF_Malloc(raidPtr->numCol * 80 1.37 christos sizeof(*reconCtrlPtr->perDiskInfo)); 81 1.3 oster reconCtrlPtr->reconDesc = reconDesc; 82 1.3 oster reconCtrlPtr->fcol = fcol; 83 1.3 oster reconCtrlPtr->spareCol = scol; 84 1.3 oster reconCtrlPtr->lastPSID = layoutPtr->numStripe / layoutPtr->SUsPerPU; 85 1.3 oster reconCtrlPtr->percentComplete = 0; 86 1.24 oster reconCtrlPtr->error = 0; 87 1.24 oster reconCtrlPtr->pending_writes = 0; 88 1.3 oster 89 1.3 oster /* initialize each per-disk recon information structure */ 90 1.3 oster for (i = 0; i < raidPtr->numCol; i++) { 91 1.3 oster reconCtrlPtr->perDiskInfo[i].reconCtrl = reconCtrlPtr; 92 1.3 oster reconCtrlPtr->perDiskInfo[i].col = i; 93 1.11 oster /* make it appear as if we just finished an RU */ 94 1.25 perry reconCtrlPtr->perDiskInfo[i].curPSID = -1; 95 1.3 oster reconCtrlPtr->perDiskInfo[i].ru_count = RUsPerPU - 1; 96 1.3 oster } 97 1.3 oster 98 1.3 oster /* Get the number of spare units per disk and the sparemap in case 99 1.3 oster * spare is distributed */ 100 1.3 oster 101 1.3 oster if (lp->GetNumSpareRUs) { 102 1.3 oster numSpareRUs = lp->GetNumSpareRUs(raidPtr); 103 1.3 oster } else { 104 1.3 oster numSpareRUs = 0; 105 1.3 oster } 106 1.3 oster 107 1.12 oster #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0) 108 1.3 oster /* 109 1.3 oster * Not all distributed sparing archs need dynamic mappings 110 1.3 oster */ 111 1.3 oster if (lp->InstallSpareTable) { 112 1.36 mrg retcode = rf_InstallSpareTable(raidPtr, fcol); 113 1.3 oster if (retcode) { 114 1.3 oster RF_PANIC(); /* XXX fix this */ 115 1.3 oster } 116 1.3 oster } 117 1.12 oster #endif 118 1.3 oster /* make the reconstruction map */ 119 1.3 oster reconCtrlPtr->reconMap = rf_MakeReconMap(raidPtr, (int) (layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit), 120 1.3 oster raidPtr->sectorsPerDisk, numSpareRUs); 121 1.3 oster 122 1.3 oster /* make the per-disk reconstruction buffers */ 123 1.3 oster for (i = 0; i < raidPtr->numCol; i++) { 124 1.15 oster reconCtrlPtr->perDiskInfo[i].rbuf = (i == fcol) ? NULL : rf_MakeReconBuffer(raidPtr, i, RF_RBUF_TYPE_EXCLUSIVE); 125 1.3 oster } 126 1.3 oster 127 1.3 oster /* initialize the event queue */ 128 1.32 mrg rf_init_mutex2(reconCtrlPtr->eq_mutex, IPL_VM); 129 1.32 mrg rf_init_cond2(reconCtrlPtr->eq_cv, "rfevq"); 130 1.17 oster 131 1.3 oster reconCtrlPtr->eventQueue = NULL; 132 1.3 oster reconCtrlPtr->eq_count = 0; 133 1.3 oster 134 1.3 oster /* make the floating recon buffers and append them to the free list */ 135 1.33 mrg rf_init_mutex2(reconCtrlPtr->rb_mutex, IPL_VM); 136 1.33 mrg rf_init_cond2(reconCtrlPtr->rb_cv, "rfrcw"); 137 1.17 oster 138 1.3 oster reconCtrlPtr->fullBufferList = NULL; 139 1.3 oster reconCtrlPtr->floatingRbufs = NULL; 140 1.3 oster reconCtrlPtr->committedRbufs = NULL; 141 1.3 oster for (i = 0; i < raidPtr->numFloatingReconBufs; i++) { 142 1.25 perry rbuf = rf_MakeReconBuffer(raidPtr, fcol, 143 1.11 oster RF_RBUF_TYPE_FLOATING); 144 1.3 oster rbuf->next = reconCtrlPtr->floatingRbufs; 145 1.3 oster reconCtrlPtr->floatingRbufs = rbuf; 146 1.3 oster } 147 1.3 oster 148 1.3 oster /* create the parity stripe status table */ 149 1.3 oster reconCtrlPtr->pssTable = rf_MakeParityStripeStatusTable(raidPtr); 150 1.3 oster 151 1.3 oster /* set the initial min head sep counter val */ 152 1.3 oster reconCtrlPtr->minHeadSepCounter = 0; 153 1.3 oster 154 1.3 oster return (reconCtrlPtr); 155 1.1 oster } 156 1.1 oster 157 1.25 perry void 158 1.19 oster rf_FreeReconControl(RF_Raid_t *raidPtr) 159 1.1 oster { 160 1.15 oster RF_ReconCtrl_t *reconCtrlPtr = raidPtr->reconControl; 161 1.3 oster RF_ReconBuffer_t *t; 162 1.3 oster RF_ReconUnitNum_t i; 163 1.3 oster 164 1.3 oster RF_ASSERT(reconCtrlPtr); 165 1.3 oster for (i = 0; i < raidPtr->numCol; i++) 166 1.3 oster if (reconCtrlPtr->perDiskInfo[i].rbuf) 167 1.3 oster rf_FreeReconBuffer(reconCtrlPtr->perDiskInfo[i].rbuf); 168 1.24 oster 169 1.24 oster t = reconCtrlPtr->floatingRbufs; 170 1.24 oster while (t) { 171 1.3 oster reconCtrlPtr->floatingRbufs = t->next; 172 1.3 oster rf_FreeReconBuffer(t); 173 1.24 oster t = reconCtrlPtr->floatingRbufs; 174 1.3 oster } 175 1.24 oster 176 1.32 mrg rf_destroy_mutex2(reconCtrlPtr->eq_mutex); 177 1.32 mrg rf_destroy_cond2(reconCtrlPtr->eq_cv); 178 1.32 mrg 179 1.33 mrg rf_destroy_mutex2(reconCtrlPtr->rb_mutex); 180 1.33 mrg rf_destroy_cond2(reconCtrlPtr->rb_cv); 181 1.33 mrg 182 1.3 oster rf_FreeReconMap(reconCtrlPtr->reconMap); 183 1.3 oster rf_FreeParityStripeStatusTable(raidPtr, reconCtrlPtr->pssTable); 184 1.25 perry RF_Free(reconCtrlPtr->perDiskInfo, 185 1.11 oster raidPtr->numCol * sizeof(RF_PerDiskReconCtrl_t)); 186 1.3 oster RF_Free(reconCtrlPtr, sizeof(*reconCtrlPtr)); 187 1.1 oster } 188 1.1 oster 189 1.1 oster 190 1.1 oster /****************************************************************************** 191 1.1 oster * computes the default head separation limit 192 1.1 oster *****************************************************************************/ 193 1.25 perry RF_HeadSepLimit_t 194 1.19 oster rf_GetDefaultHeadSepLimit(RF_Raid_t *raidPtr) 195 1.1 oster { 196 1.3 oster RF_HeadSepLimit_t hsl; 197 1.14 jdolecek const RF_LayoutSW_t *lp; 198 1.1 oster 199 1.3 oster lp = raidPtr->Layout.map; 200 1.3 oster if (lp->GetDefaultHeadSepLimit == NULL) 201 1.3 oster return (-1); 202 1.3 oster hsl = lp->GetDefaultHeadSepLimit(raidPtr); 203 1.3 oster return (hsl); 204 1.1 oster } 205 1.1 oster 206 1.1 oster 207 1.1 oster /****************************************************************************** 208 1.1 oster * computes the default number of floating recon buffers 209 1.1 oster *****************************************************************************/ 210 1.25 perry int 211 1.19 oster rf_GetDefaultNumFloatingReconBuffers(RF_Raid_t *raidPtr) 212 1.1 oster { 213 1.14 jdolecek const RF_LayoutSW_t *lp; 214 1.3 oster int nrb; 215 1.1 oster 216 1.3 oster lp = raidPtr->Layout.map; 217 1.3 oster if (lp->GetDefaultNumFloatingReconBuffers == NULL) 218 1.3 oster return (3 * raidPtr->numCol); 219 1.3 oster nrb = lp->GetDefaultNumFloatingReconBuffers(raidPtr); 220 1.3 oster return (nrb); 221 1.1 oster } 222 1.1 oster 223 1.1 oster 224 1.1 oster /****************************************************************************** 225 1.1 oster * creates and initializes a reconstruction buffer 226 1.1 oster *****************************************************************************/ 227 1.3 oster RF_ReconBuffer_t * 228 1.19 oster rf_MakeReconBuffer(RF_Raid_t *raidPtr, RF_RowCol_t col, RF_RbufType_t type) 229 1.1 oster { 230 1.3 oster RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 231 1.3 oster RF_ReconBuffer_t *t; 232 1.3 oster u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr, layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit); 233 1.3 oster 234 1.38 oster t = pool_get(&raidPtr->pools.reconbuffer, PR_WAITOK); 235 1.37 christos t->buffer = RF_Malloc(recon_buffer_size); 236 1.3 oster t->raidPtr = raidPtr; 237 1.3 oster t->col = col; 238 1.3 oster t->priority = RF_IO_RECON_PRIORITY; 239 1.3 oster t->type = type; 240 1.3 oster t->pssPtr = NULL; 241 1.3 oster t->next = NULL; 242 1.3 oster return (t); 243 1.1 oster } 244 1.1 oster /****************************************************************************** 245 1.1 oster * frees a reconstruction buffer 246 1.1 oster *****************************************************************************/ 247 1.25 perry void 248 1.19 oster rf_FreeReconBuffer(RF_ReconBuffer_t *rbuf) 249 1.1 oster { 250 1.3 oster RF_Raid_t *raidPtr = rbuf->raidPtr; 251 1.35 martin u_int recon_buffer_size __unused; 252 1.9 oster 253 1.9 oster recon_buffer_size = rf_RaidAddressToByte(raidPtr, raidPtr->Layout.SUsPerRU * raidPtr->Layout.sectorsPerStripeUnit); 254 1.3 oster 255 1.3 oster RF_Free(rbuf->buffer, recon_buffer_size); 256 1.38 oster pool_put(&raidPtr->pools.reconbuffer, rbuf); 257 1.1 oster } 258 1.1 oster 259 1.10 oster #if RF_DEBUG_RECON 260 1.23 oster XXXX IF you use this, you really want to fix the locking in here. 261 1.1 oster /****************************************************************************** 262 1.1 oster * debug only: sanity check the number of floating recon bufs in use 263 1.1 oster *****************************************************************************/ 264 1.25 perry void 265 1.19 oster rf_CheckFloatingRbufCount(RF_Raid_t *raidPtr, int dolock) 266 1.1 oster { 267 1.3 oster RF_ReconParityStripeStatus_t *p; 268 1.3 oster RF_PSStatusHeader_t *pssTable; 269 1.3 oster RF_ReconBuffer_t *rbuf; 270 1.3 oster int i, j, sum = 0; 271 1.3 oster 272 1.3 oster if (dolock) 273 1.33 mrg rf_lock_mutex2(raidPtr->reconControl->rb_mutex); 274 1.15 oster pssTable = raidPtr->reconControl->pssTable; 275 1.3 oster 276 1.3 oster for (i = 0; i < raidPtr->pssTableSize; i++) { 277 1.34 mrg rf_lock_mutex2(pssTable[i].mutex); 278 1.3 oster for (p = pssTable[i].chain; p; p = p->next) { 279 1.3 oster rbuf = (RF_ReconBuffer_t *) p->rbuf; 280 1.3 oster if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING) 281 1.3 oster sum++; 282 1.3 oster 283 1.3 oster rbuf = (RF_ReconBuffer_t *) p->writeRbuf; 284 1.3 oster if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING) 285 1.3 oster sum++; 286 1.3 oster 287 1.3 oster for (j = 0; j < p->xorBufCount; j++) { 288 1.3 oster rbuf = (RF_ReconBuffer_t *) p->rbufsForXor[j]; 289 1.3 oster RF_ASSERT(rbuf); 290 1.3 oster if (rbuf->type == RF_RBUF_TYPE_FLOATING) 291 1.3 oster sum++; 292 1.3 oster } 293 1.3 oster } 294 1.34 mrg rf_unlock_mutex2(pssTable[i].mutex); 295 1.3 oster } 296 1.3 oster 297 1.25 perry for (rbuf = raidPtr->reconControl->floatingRbufs; rbuf; 298 1.11 oster rbuf = rbuf->next) { 299 1.3 oster if (rbuf->type == RF_RBUF_TYPE_FLOATING) 300 1.3 oster sum++; 301 1.3 oster } 302 1.25 perry for (rbuf = raidPtr->reconControl->committedRbufs; rbuf; 303 1.11 oster rbuf = rbuf->next) { 304 1.3 oster if (rbuf->type == RF_RBUF_TYPE_FLOATING) 305 1.3 oster sum++; 306 1.3 oster } 307 1.25 perry for (rbuf = raidPtr->reconControl->fullBufferList; rbuf; 308 1.11 oster rbuf = rbuf->next) { 309 1.3 oster if (rbuf->type == RF_RBUF_TYPE_FLOATING) 310 1.3 oster sum++; 311 1.3 oster } 312 1.3 oster RF_ASSERT(sum == raidPtr->numFloatingReconBufs); 313 1.1 oster 314 1.3 oster if (dolock) 315 1.33 mrg rf_unlock_mutex2(raidPtr->reconControl->rb_mutex); 316 1.1 oster } 317 1.7 oster #endif 318 1.7 oster 319