1 /* $NetBSD: rf_reconbuffer.c,v 1.1 1998/11/13 04:20:33 oster Exp $ */ 2 /* 3 * Copyright (c) 1995 Carnegie-Mellon University. 4 * All rights reserved. 5 * 6 * Author: Mark Holland 7 * 8 * Permission to use, copy, modify and distribute this software and 9 * its documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 16 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie the 26 * rights to redistribute these changes. 27 */ 28 29 /*************************************************** 30 * 31 * rf_reconbuffer.c -- reconstruction buffer manager 32 * 33 ***************************************************/ 34 35 /* : 36 * Log: rf_reconbuffer.c,v 37 * Revision 1.33 1996/07/27 23:36:08 jimz 38 * Solaris port of simulator 39 * 40 * Revision 1.32 1996/07/17 21:00:58 jimz 41 * clean up timer interface, tracing 42 * 43 * Revision 1.31 1996/07/13 00:00:59 jimz 44 * sanitized generalized reconstruction architecture 45 * cleaned up head sep, rbuf problems 46 * 47 * Revision 1.30 1996/06/07 21:33:04 jimz 48 * begin using consistent types for sector numbers, 49 * stripe numbers, row+col numbers, recon unit numbers 50 * 51 * Revision 1.29 1996/06/06 01:23:58 jimz 52 * don't free reconCtrlPtr until after all fields have been used out of it 53 * 54 * Revision 1.28 1996/06/05 18:06:02 jimz 55 * Major code cleanup. The Great Renaming is now done. 56 * Better modularity. Better typing. Fixed a bunch of 57 * synchronization bugs. Made a lot of global stuff 58 * per-desc or per-array. Removed dead code. 59 * 60 * Revision 1.27 1996/06/03 23:28:26 jimz 61 * more bugfixes 62 * check in tree to sync for IPDS runs with current bugfixes 63 * there still may be a problem with threads in the script test 64 * getting I/Os stuck- not trivially reproducible (runs ~50 times 65 * in a row without getting stuck) 66 * 67 * Revision 1.26 1996/06/02 17:31:48 jimz 68 * Moved a lot of global stuff into array structure, where it belongs. 69 * Fixed up paritylogging, pss modules in this manner. Some general 70 * code cleanup. Removed lots of dead code, some dead files. 71 * 72 * Revision 1.25 1996/05/31 22:26:54 jimz 73 * fix a lot of mapping problems, memory allocation problems 74 * found some weird lock issues, fixed 'em 75 * more code cleanup 76 * 77 * Revision 1.24 1996/05/30 12:59:18 jimz 78 * make etimer happier, more portable 79 * 80 * Revision 1.23 1996/05/27 18:56:37 jimz 81 * more code cleanup 82 * better typing 83 * compiles in all 3 environments 84 * 85 * Revision 1.22 1996/05/24 22:17:04 jimz 86 * continue code + namespace cleanup 87 * typed a bunch of flags 88 * 89 * Revision 1.21 1996/05/23 21:46:35 jimz 90 * checkpoint in code cleanup (release prep) 91 * lots of types, function names have been fixed 92 * 93 * Revision 1.20 1996/05/23 00:33:23 jimz 94 * code cleanup: move all debug decls to rf_options.c, all extern 95 * debug decls to rf_options.h, all debug vars preceded by rf_ 96 * 97 * Revision 1.19 1996/05/18 19:51:34 jimz 98 * major code cleanup- fix syntax, make some types consistent, 99 * add prototypes, clean out dead code, et cetera 100 * 101 * Revision 1.18 1995/12/12 18:10:06 jimz 102 * MIN -> RF_MIN, MAX -> RF_MAX, ASSERT -> RF_ASSERT 103 * fix 80-column brain damage in comments 104 * 105 * Revision 1.17 1995/12/06 15:03:24 root 106 * added copyright info 107 * 108 */ 109 110 #ifdef _KERNEL 111 #define KERNEL 112 #endif 113 114 #include "rf_raid.h" 115 #include "rf_reconbuffer.h" 116 #include "rf_acctrace.h" 117 #include "rf_etimer.h" 118 #include "rf_general.h" 119 #include "rf_debugprint.h" 120 #include "rf_revent.h" 121 #include "rf_reconutil.h" 122 #include "rf_nwayxor.h" 123 124 #ifdef KERNEL 125 #define Dprintf1(s,a) if (rf_reconbufferDebug) printf(s,a) 126 #define Dprintf2(s,a,b) if (rf_reconbufferDebug) printf(s,a,b) 127 #define Dprintf3(s,a,b,c) if (rf_reconbufferDebug) printf(s,a,b,c) 128 #define Dprintf4(s,a,b,c,d) if (rf_reconbufferDebug) printf(s,a,b,c,d) 129 #define Dprintf5(s,a,b,c,d,e) if (rf_reconbufferDebug) printf(s,a,b,c,d,e) 130 #else /* KERNEL */ 131 #define Dprintf1(s,a) if (rf_reconbufferDebug) rf_debug_printf(s,(void *)((unsigned long)a),NULL,NULL,NULL,NULL,NULL,NULL,NULL) 132 #define Dprintf2(s,a,b) if (rf_reconbufferDebug) rf_debug_printf(s,(void *)((unsigned long)a),(void *)((unsigned long)b),NULL,NULL,NULL,NULL,NULL,NULL) 133 #define Dprintf3(s,a,b,c) if (rf_reconbufferDebug) rf_debug_printf(s,(void *)((unsigned long)a),(void *)((unsigned long)b),(void *)((unsigned long)c),NULL,NULL,NULL,NULL,NULL) 134 #define Dprintf4(s,a,b,c,d) if (rf_reconbufferDebug) rf_debug_printf(s,(void *)((unsigned long)a),(void *)((unsigned long)b),(void *)((unsigned long)c),(void *)((unsigned long)d),NULL,NULL,NULL,NULL) 135 #define Dprintf5(s,a,b,c,d,e) if (rf_reconbufferDebug) rf_debug_printf(s,(void *)((unsigned long)a),(void *)((unsigned long)b),(void *)((unsigned long)c),(void *)((unsigned long)d),(void *)((unsigned long)e),NULL,NULL,NULL) 136 #endif /* KERNEL */ 137 138 #if defined(__NetBSD__) && defined(_KERNEL) 139 140 /* XXX XXX XXX This is wrong, for a number of reasons: 141 a) thread_block doesn't exist with UVM 142 b) The prototype begin used here is wrong for the regular VM 143 (regular VM expects a (char *) as an argument. I don't put 144 that in here as this code uses thread_block with no arguments.. :-/ 145 146 */ 147 #if 0 148 void thread_block(void); 149 #endif 150 #endif 151 152 /***************************************************************************************** 153 * 154 * Submit a reconstruction buffer to the manager for XOR. 155 * We can only submit a buffer if (1) we can xor into an existing buffer, which means 156 * we don't have to acquire a new one, (2) we can acquire a floating 157 * recon buffer, or (3) the caller has indicated that we are allowed to keep the 158 * submitted buffer. 159 * 160 * Returns non-zero if and only if we were not able to submit. 161 * In this case, we append the current disk ID to the wait list on the indicated 162 * RU, so that it will be re-enabled when we acquire a buffer for this RU. 163 * 164 ****************************************************************************************/ 165 166 /* just to make the code below more readable */ 167 #define BUFWAIT_APPEND(_cb_, _pssPtr_, _row_, _col_) \ 168 _cb_ = rf_AllocCallbackDesc(); \ 169 (_cb_)->row = (_row_); (_cb_)->col = (_col_); (_cb_)->next = (_pssPtr_)->bufWaitList; (_pssPtr_)->bufWaitList = (_cb_); 170 171 /* 172 * nWayXorFuncs[i] is a pointer to a function that will xor "i" 173 * bufs into the accumulating sum. 174 */ 175 static RF_VoidFuncPtr nWayXorFuncs[] = { 176 NULL, 177 (RF_VoidFuncPtr)rf_nWayXor1, 178 (RF_VoidFuncPtr)rf_nWayXor2, 179 (RF_VoidFuncPtr)rf_nWayXor3, 180 (RF_VoidFuncPtr)rf_nWayXor4, 181 (RF_VoidFuncPtr)rf_nWayXor5, 182 (RF_VoidFuncPtr)rf_nWayXor6, 183 (RF_VoidFuncPtr)rf_nWayXor7, 184 (RF_VoidFuncPtr)rf_nWayXor8, 185 (RF_VoidFuncPtr)rf_nWayXor9 186 }; 187 188 int rf_SubmitReconBuffer(rbuf, keep_it, use_committed) 189 RF_ReconBuffer_t *rbuf; /* the recon buffer to submit */ 190 int keep_it; /* whether we can keep this buffer or we have to return it */ 191 int use_committed; /* whether to use a committed or an available recon buffer */ 192 { 193 RF_LayoutSW_t *lp; 194 int rc; 195 196 lp = rbuf->raidPtr->Layout.map; 197 rc = lp->SubmitReconBuffer(rbuf, keep_it, use_committed); 198 return(rc); 199 } 200 201 int rf_SubmitReconBufferBasic(rbuf, keep_it, use_committed) 202 RF_ReconBuffer_t *rbuf; /* the recon buffer to submit */ 203 int keep_it; /* whether we can keep this buffer or we have to return it */ 204 int use_committed; /* whether to use a committed or an available recon buffer */ 205 { 206 RF_Raid_t *raidPtr = rbuf->raidPtr; 207 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 208 RF_ReconCtrl_t *reconCtrlPtr = raidPtr->reconControl[rbuf->row]; 209 RF_ReconParityStripeStatus_t *pssPtr; 210 RF_ReconBuffer_t *targetRbuf, *t = NULL; /* temporary rbuf pointers */ 211 caddr_t ta; /* temporary data buffer pointer */ 212 RF_CallbackDesc_t *cb, *p; 213 int retcode = 0, created = 0; 214 215 RF_Etimer_t timer; 216 217 /* makes no sense to have a submission from the failed disk */ 218 RF_ASSERT(rbuf); 219 RF_ASSERT(rbuf->col != reconCtrlPtr->fcol); 220 221 Dprintf5("RECON: submission by row %d col %d for psid %ld ru %d (failed offset %ld)\n", 222 rbuf->row, rbuf->col, (long)rbuf->parityStripeID, rbuf->which_ru, (long)rbuf->failedDiskSectorOffset); 223 224 RF_LOCK_PSS_MUTEX(raidPtr,rbuf->row,rbuf->parityStripeID); 225 226 RF_LOCK_MUTEX(reconCtrlPtr->rb_mutex); 227 228 pssPtr = rf_LookupRUStatus(raidPtr, reconCtrlPtr->pssTable, rbuf->parityStripeID, rbuf->which_ru, RF_PSS_NONE, &created); 229 RF_ASSERT(pssPtr); /* if it didn't exist, we wouldn't have gotten an rbuf for it */ 230 231 /* check to see if enough buffers have accumulated to do an XOR. If so, there's no need to 232 * acquire a floating rbuf. Before we can do any XORing, we must have acquired a destination 233 * buffer. If we have, then we can go ahead and do the XOR if (1) including this buffer, enough 234 * bufs have accumulated, or (2) this is the last submission for this stripe. 235 * Otherwise, we have to go acquire a floating rbuf. 236 */ 237 238 targetRbuf = (RF_ReconBuffer_t *) pssPtr->rbuf; 239 if ( (targetRbuf != NULL) && 240 ((pssPtr->xorBufCount == rf_numBufsToAccumulate-1) || (targetRbuf->count + pssPtr->xorBufCount + 1 == layoutPtr->numDataCol)) ) { 241 pssPtr->rbufsForXor[ pssPtr->xorBufCount++ ] = rbuf; /* install this buffer */ 242 Dprintf3("RECON: row %d col %d invoking a %d-way XOR\n",rbuf->row, rbuf->col,pssPtr->xorBufCount); 243 RF_ETIMER_START(timer); 244 rf_MultiWayReconXor(raidPtr, pssPtr); 245 RF_ETIMER_STOP(timer); RF_ETIMER_EVAL(timer); 246 raidPtr->accumXorTimeUs += RF_ETIMER_VAL_US(timer); 247 if (!keep_it) { 248 raidPtr->recon_tracerecs[rbuf->col].xor_us = RF_ETIMER_VAL_US(timer); 249 RF_ETIMER_STOP(raidPtr->recon_tracerecs[rbuf->col].recon_timer); 250 RF_ETIMER_EVAL(raidPtr->recon_tracerecs[rbuf->col].recon_timer); 251 raidPtr->recon_tracerecs[rbuf->col].specific.recon.recon_return_to_submit_us += 252 RF_ETIMER_VAL_US(raidPtr->recon_tracerecs[rbuf->col].recon_timer); 253 RF_ETIMER_START(raidPtr->recon_tracerecs[rbuf->col].recon_timer); 254 255 rf_LogTraceRec(raidPtr, &raidPtr->recon_tracerecs[rbuf->col]); 256 } 257 rf_CheckForFullRbuf(raidPtr, reconCtrlPtr, pssPtr, layoutPtr->numDataCol); 258 259 /* if use_committed is on, we _must_ consume a buffer off the committed list. */ 260 if (use_committed) { 261 t = reconCtrlPtr->committedRbufs; 262 RF_ASSERT(t); 263 reconCtrlPtr->committedRbufs = t->next; 264 rf_ReleaseFloatingReconBuffer(raidPtr, rbuf->row, t); 265 } 266 if (keep_it) { 267 RF_UNLOCK_PSS_MUTEX( raidPtr,rbuf->row,rbuf->parityStripeID); 268 RF_UNLOCK_MUTEX( reconCtrlPtr->rb_mutex ); 269 rf_FreeReconBuffer(rbuf); 270 return(retcode); 271 } 272 goto out; 273 } 274 275 /* set the value of "t", which we'll use as the rbuf from here on */ 276 if (keep_it) { 277 t = rbuf; 278 } 279 else { 280 if (use_committed) { /* if a buffer has been committed to us, use it */ 281 t = reconCtrlPtr->committedRbufs; 282 RF_ASSERT(t); 283 reconCtrlPtr->committedRbufs = t->next; 284 t->next = NULL; 285 } else if (reconCtrlPtr->floatingRbufs) { 286 t = reconCtrlPtr->floatingRbufs; 287 reconCtrlPtr->floatingRbufs = t->next; 288 t->next = NULL; 289 } 290 } 291 292 /* If we weren't able to acquire a buffer, 293 * append to the end of the buf list in the recon ctrl struct. 294 */ 295 if (!t) { 296 RF_ASSERT(!keep_it && !use_committed); 297 Dprintf2("RECON: row %d col %d failed to acquire floating rbuf\n",rbuf->row, rbuf->col); 298 299 raidPtr->procsInBufWait++; 300 if ( (raidPtr->procsInBufWait == raidPtr->numCol -1) && (raidPtr->numFullReconBuffers == 0)) { 301 printf("Buffer wait deadlock detected. Exiting.\n"); 302 rf_PrintPSStatusTable(raidPtr, rbuf->row); 303 RF_PANIC(); 304 } 305 pssPtr->flags |= RF_PSS_BUFFERWAIT; 306 cb = rf_AllocCallbackDesc(); /* append to buf wait list in recon ctrl structure */ 307 cb->row = rbuf->row; cb->col = rbuf->col; 308 cb->callbackArg.v = rbuf->parityStripeID; 309 cb->callbackArg2.v = rbuf->which_ru; 310 cb->next = NULL; 311 if (!reconCtrlPtr->bufferWaitList) reconCtrlPtr->bufferWaitList = cb; 312 else { /* might want to maintain head/tail pointers here rather than search for end of list */ 313 for (p = reconCtrlPtr->bufferWaitList; p->next; p=p->next); 314 p->next = cb; 315 } 316 retcode = 1; 317 goto out; 318 } 319 Dprintf2("RECON: row %d col %d acquired rbuf\n",rbuf->row, rbuf->col); 320 RF_ETIMER_STOP(raidPtr->recon_tracerecs[rbuf->col].recon_timer); 321 RF_ETIMER_EVAL(raidPtr->recon_tracerecs[rbuf->col].recon_timer); 322 raidPtr->recon_tracerecs[rbuf->col].specific.recon.recon_return_to_submit_us += 323 RF_ETIMER_VAL_US(raidPtr->recon_tracerecs[rbuf->col].recon_timer); 324 RF_ETIMER_START(raidPtr->recon_tracerecs[rbuf->col].recon_timer); 325 326 rf_LogTraceRec(raidPtr, &raidPtr->recon_tracerecs[rbuf->col]); 327 328 /* initialize the buffer */ 329 if (t!=rbuf) { 330 t->row = rbuf->row; t->col = reconCtrlPtr->fcol; 331 t->parityStripeID = rbuf->parityStripeID; 332 t->which_ru = rbuf->which_ru; 333 t->failedDiskSectorOffset = rbuf->failedDiskSectorOffset; 334 t->spRow=rbuf->spRow; 335 t->spCol=rbuf->spCol; 336 t->spOffset=rbuf->spOffset; 337 338 ta = t->buffer; t->buffer = rbuf->buffer; rbuf->buffer = ta; /* swap buffers */ 339 } 340 341 /* the first installation always gets installed as the destination buffer. 342 * subsequent installations get stacked up to allow for multi-way XOR 343 */ 344 if (!pssPtr->rbuf) {pssPtr->rbuf = t; t->count = 1;} 345 else pssPtr->rbufsForXor[ pssPtr->xorBufCount++ ] = t; /* install this buffer */ 346 347 rf_CheckForFullRbuf(raidPtr, reconCtrlPtr, pssPtr, layoutPtr->numDataCol); /* the buffer is full if G=2 */ 348 349 out: 350 RF_UNLOCK_PSS_MUTEX( raidPtr,rbuf->row,rbuf->parityStripeID); 351 RF_UNLOCK_MUTEX( reconCtrlPtr->rb_mutex ); 352 return(retcode); 353 } 354 355 int rf_MultiWayReconXor(raidPtr, pssPtr) 356 RF_Raid_t *raidPtr; 357 RF_ReconParityStripeStatus_t *pssPtr; /* the pss descriptor for this parity stripe */ 358 { 359 int i, numBufs = pssPtr->xorBufCount; 360 int numBytes = rf_RaidAddressToByte(raidPtr, raidPtr->Layout.sectorsPerStripeUnit * raidPtr->Layout.SUsPerRU); 361 RF_ReconBuffer_t **rbufs = (RF_ReconBuffer_t **) pssPtr->rbufsForXor; 362 RF_ReconBuffer_t *targetRbuf = (RF_ReconBuffer_t *) pssPtr->rbuf; 363 364 RF_ASSERT(pssPtr->rbuf != NULL); 365 RF_ASSERT(numBufs > 0 && numBufs < RF_PS_MAX_BUFS); 366 #ifdef KERNEL 367 #ifndef __NetBSD__ 368 thread_block(); /* yield the processor before doing a big XOR */ 369 #endif 370 #endif /* KERNEL */ 371 /* 372 * XXX 373 * 374 * What if more than 9 bufs? 375 */ 376 nWayXorFuncs[numBufs](pssPtr->rbufsForXor, targetRbuf, numBytes/sizeof(long)); 377 378 /* release all the reconstruction buffers except the last one, which belongs to the 379 * the disk who's submission caused this XOR to take place 380 */ 381 for (i=0; i < numBufs-1; i++) { 382 if (rbufs[i]->type == RF_RBUF_TYPE_FLOATING) rf_ReleaseFloatingReconBuffer(raidPtr, rbufs[i]->row, rbufs[i]); 383 else if (rbufs[i]->type == RF_RBUF_TYPE_FORCED) rf_FreeReconBuffer(rbufs[i]); 384 else RF_ASSERT(0); 385 } 386 targetRbuf->count += pssPtr->xorBufCount; 387 pssPtr->xorBufCount = 0; 388 return(0); 389 } 390 391 /* removes one full buffer from one of the full-buffer lists and returns it. 392 * 393 * ASSUMES THE RB_MUTEX IS UNLOCKED AT ENTRY. 394 */ 395 RF_ReconBuffer_t *rf_GetFullReconBuffer(reconCtrlPtr) 396 RF_ReconCtrl_t *reconCtrlPtr; 397 { 398 RF_ReconBuffer_t *p; 399 400 RF_LOCK_MUTEX(reconCtrlPtr->rb_mutex); 401 402 if ( (p=reconCtrlPtr->priorityList) != NULL) { 403 reconCtrlPtr->priorityList = p->next; 404 p->next = NULL; 405 goto out; 406 } 407 if ( (p=reconCtrlPtr->fullBufferList) != NULL) { 408 reconCtrlPtr->fullBufferList = p->next; 409 p->next = NULL; 410 goto out; 411 } 412 413 out: 414 RF_UNLOCK_MUTEX(reconCtrlPtr->rb_mutex); 415 return(p); 416 } 417 418 419 /* if the reconstruction buffer is full, move it to the full list, which is maintained 420 * sorted by failed disk sector offset 421 * 422 * ASSUMES THE RB_MUTEX IS LOCKED AT ENTRY. 423 */ 424 int rf_CheckForFullRbuf(raidPtr, reconCtrl, pssPtr, numDataCol) 425 RF_Raid_t *raidPtr; 426 RF_ReconCtrl_t *reconCtrl; 427 RF_ReconParityStripeStatus_t *pssPtr; 428 int numDataCol; 429 { 430 RF_ReconBuffer_t *p, *pt, *rbuf = (RF_ReconBuffer_t *) pssPtr->rbuf; 431 432 if (rbuf->count == numDataCol) { 433 raidPtr->numFullReconBuffers++; 434 Dprintf2("RECON: rbuf for psid %ld ru %d has filled\n", 435 (long)rbuf->parityStripeID, rbuf->which_ru); 436 if (!reconCtrl->fullBufferList || (rbuf->failedDiskSectorOffset < reconCtrl->fullBufferList->failedDiskSectorOffset)) { 437 Dprintf2("RECON: rbuf for psid %ld ru %d is head of list\n", 438 (long)rbuf->parityStripeID, rbuf->which_ru); 439 rbuf->next = reconCtrl->fullBufferList; 440 reconCtrl->fullBufferList = rbuf; 441 } 442 else { 443 for (pt = reconCtrl->fullBufferList, p = pt->next; p && p->failedDiskSectorOffset < rbuf->failedDiskSectorOffset; pt=p, p=p->next); 444 rbuf->next = p; 445 pt->next = rbuf; 446 Dprintf2("RECON: rbuf for psid %ld ru %d is in list\n", 447 (long)rbuf->parityStripeID, rbuf->which_ru); 448 } 449 #if 0 450 pssPtr->writeRbuf = pssPtr->rbuf; /* DEBUG ONLY: we like to be able to find this rbuf while it's awaiting write */ 451 #else 452 rbuf->pssPtr = pssPtr; 453 #endif 454 pssPtr->rbuf = NULL; 455 rf_CauseReconEvent(raidPtr, rbuf->row, rbuf->col, NULL, RF_REVENT_BUFREADY); 456 } 457 return(0); 458 } 459 460 461 /* release a floating recon buffer for someone else to use. 462 * assumes the rb_mutex is LOCKED at entry 463 */ 464 void rf_ReleaseFloatingReconBuffer(raidPtr, row, rbuf) 465 RF_Raid_t *raidPtr; 466 RF_RowCol_t row; 467 RF_ReconBuffer_t *rbuf; 468 { 469 RF_ReconCtrl_t *rcPtr = raidPtr->reconControl[row]; 470 RF_CallbackDesc_t *cb; 471 472 Dprintf2("RECON: releasing rbuf for psid %ld ru %d\n", 473 (long)rbuf->parityStripeID, rbuf->which_ru); 474 475 /* if anyone is waiting on buffers, wake one of them up. They will subsequently wake up anyone 476 * else waiting on their RU 477 */ 478 if (rcPtr->bufferWaitList) { 479 rbuf->next = rcPtr->committedRbufs; 480 rcPtr->committedRbufs = rbuf; 481 cb = rcPtr->bufferWaitList; 482 rcPtr->bufferWaitList = cb->next; 483 rf_CauseReconEvent(raidPtr, cb->row, cb->col, (void *) 1, RF_REVENT_BUFCLEAR); /* arg==1 => we've committed a buffer */ 484 rf_FreeCallbackDesc(cb); 485 raidPtr->procsInBufWait--; 486 } else { 487 rbuf->next = rcPtr->floatingRbufs; 488 rcPtr->floatingRbufs = rbuf; 489 } 490 } 491 492 /* release any disk that is waiting on a buffer for the indicated RU. 493 * assumes the rb_mutex is LOCKED at entry 494 */ 495 void rf_ReleaseBufferWaiters(raidPtr, pssPtr) 496 RF_Raid_t *raidPtr; 497 RF_ReconParityStripeStatus_t *pssPtr; 498 { 499 RF_CallbackDesc_t *cb1, *cb = pssPtr->bufWaitList; 500 501 Dprintf2("RECON: releasing buf waiters for psid %ld ru %d\n", 502 (long)pssPtr->parityStripeID, pssPtr->which_ru); 503 pssPtr->flags &= ~RF_PSS_BUFFERWAIT; 504 while (cb) { 505 cb1 = cb->next; 506 cb->next = NULL; 507 rf_CauseReconEvent(raidPtr, cb->row, cb->col, (void *) 0, RF_REVENT_BUFCLEAR); /* arg==0 => we haven't committed a buffer */ 508 rf_FreeCallbackDesc(cb); 509 cb = cb1; 510 } 511 pssPtr->bufWaitList = NULL; 512 } 513 514 /* when reconstruction is forced on an RU, there may be some disks waiting to 515 * acquire a buffer for that RU. Since we allocate a new buffer as part of 516 * the forced-reconstruction process, we no longer have to wait for any 517 * buffers, so we wakeup any waiter that we find in the bufferWaitList 518 * 519 * assumes the rb_mutex is LOCKED at entry 520 */ 521 void rf_ReleaseBufferWaiter(rcPtr, rbuf) 522 RF_ReconCtrl_t *rcPtr; 523 RF_ReconBuffer_t *rbuf; 524 { 525 RF_CallbackDesc_t *cb, *cbt; 526 527 for (cbt = NULL, cb = rcPtr->bufferWaitList; cb; cbt = cb, cb=cb->next) { 528 if ( (cb->callbackArg.v == rbuf->parityStripeID) && ( cb->callbackArg2.v == rbuf->which_ru)) { 529 Dprintf2("RECON: Dropping row %d col %d from buffer wait list\n", cb->row, cb->col); 530 if (cbt) cbt->next = cb->next; 531 else rcPtr->bufferWaitList = cb->next; 532 rf_CauseReconEvent((RF_Raid_t *) rbuf->raidPtr, cb->row, cb->col, (void *) 0, RF_REVENT_BUFREADY); /* arg==0 => no committed buffer */ 533 rf_FreeCallbackDesc(cb); 534 return; 535 } 536 } 537 } 538