rf_reconbuffer.c revision 1.1 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 (at) 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