rf_reconbuffer.c revision 1.2 1 1.2 oster /* $NetBSD: rf_reconbuffer.c,v 1.2 1999/01/26 02:34:01 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 * rf_reconbuffer.c -- reconstruction buffer manager
32 1.1 oster *
33 1.1 oster ***************************************************/
34 1.1 oster
35 1.1 oster #include "rf_raid.h"
36 1.1 oster #include "rf_reconbuffer.h"
37 1.1 oster #include "rf_acctrace.h"
38 1.1 oster #include "rf_etimer.h"
39 1.1 oster #include "rf_general.h"
40 1.1 oster #include "rf_debugprint.h"
41 1.1 oster #include "rf_revent.h"
42 1.1 oster #include "rf_reconutil.h"
43 1.1 oster #include "rf_nwayxor.h"
44 1.1 oster
45 1.1 oster #define Dprintf1(s,a) if (rf_reconbufferDebug) printf(s,a)
46 1.1 oster #define Dprintf2(s,a,b) if (rf_reconbufferDebug) printf(s,a,b)
47 1.1 oster #define Dprintf3(s,a,b,c) if (rf_reconbufferDebug) printf(s,a,b,c)
48 1.1 oster #define Dprintf4(s,a,b,c,d) if (rf_reconbufferDebug) printf(s,a,b,c,d)
49 1.1 oster #define Dprintf5(s,a,b,c,d,e) if (rf_reconbufferDebug) printf(s,a,b,c,d,e)
50 1.1 oster
51 1.1 oster /*****************************************************************************************
52 1.1 oster *
53 1.1 oster * Submit a reconstruction buffer to the manager for XOR.
54 1.1 oster * We can only submit a buffer if (1) we can xor into an existing buffer, which means
55 1.1 oster * we don't have to acquire a new one, (2) we can acquire a floating
56 1.1 oster * recon buffer, or (3) the caller has indicated that we are allowed to keep the
57 1.1 oster * submitted buffer.
58 1.1 oster *
59 1.1 oster * Returns non-zero if and only if we were not able to submit.
60 1.1 oster * In this case, we append the current disk ID to the wait list on the indicated
61 1.1 oster * RU, so that it will be re-enabled when we acquire a buffer for this RU.
62 1.1 oster *
63 1.1 oster ****************************************************************************************/
64 1.1 oster
65 1.1 oster /* just to make the code below more readable */
66 1.1 oster #define BUFWAIT_APPEND(_cb_, _pssPtr_, _row_, _col_) \
67 1.1 oster _cb_ = rf_AllocCallbackDesc(); \
68 1.1 oster (_cb_)->row = (_row_); (_cb_)->col = (_col_); (_cb_)->next = (_pssPtr_)->bufWaitList; (_pssPtr_)->bufWaitList = (_cb_);
69 1.1 oster
70 1.1 oster /*
71 1.1 oster * nWayXorFuncs[i] is a pointer to a function that will xor "i"
72 1.1 oster * bufs into the accumulating sum.
73 1.1 oster */
74 1.1 oster static RF_VoidFuncPtr nWayXorFuncs[] = {
75 1.1 oster NULL,
76 1.1 oster (RF_VoidFuncPtr)rf_nWayXor1,
77 1.1 oster (RF_VoidFuncPtr)rf_nWayXor2,
78 1.1 oster (RF_VoidFuncPtr)rf_nWayXor3,
79 1.1 oster (RF_VoidFuncPtr)rf_nWayXor4,
80 1.1 oster (RF_VoidFuncPtr)rf_nWayXor5,
81 1.1 oster (RF_VoidFuncPtr)rf_nWayXor6,
82 1.1 oster (RF_VoidFuncPtr)rf_nWayXor7,
83 1.1 oster (RF_VoidFuncPtr)rf_nWayXor8,
84 1.1 oster (RF_VoidFuncPtr)rf_nWayXor9
85 1.1 oster };
86 1.1 oster
87 1.1 oster int rf_SubmitReconBuffer(rbuf, keep_it, use_committed)
88 1.1 oster RF_ReconBuffer_t *rbuf; /* the recon buffer to submit */
89 1.1 oster int keep_it; /* whether we can keep this buffer or we have to return it */
90 1.1 oster int use_committed; /* whether to use a committed or an available recon buffer */
91 1.1 oster {
92 1.1 oster RF_LayoutSW_t *lp;
93 1.1 oster int rc;
94 1.1 oster
95 1.1 oster lp = rbuf->raidPtr->Layout.map;
96 1.1 oster rc = lp->SubmitReconBuffer(rbuf, keep_it, use_committed);
97 1.1 oster return(rc);
98 1.1 oster }
99 1.1 oster
100 1.1 oster int rf_SubmitReconBufferBasic(rbuf, keep_it, use_committed)
101 1.1 oster RF_ReconBuffer_t *rbuf; /* the recon buffer to submit */
102 1.1 oster int keep_it; /* whether we can keep this buffer or we have to return it */
103 1.1 oster int use_committed; /* whether to use a committed or an available recon buffer */
104 1.1 oster {
105 1.1 oster RF_Raid_t *raidPtr = rbuf->raidPtr;
106 1.1 oster RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
107 1.1 oster RF_ReconCtrl_t *reconCtrlPtr = raidPtr->reconControl[rbuf->row];
108 1.1 oster RF_ReconParityStripeStatus_t *pssPtr;
109 1.1 oster RF_ReconBuffer_t *targetRbuf, *t = NULL; /* temporary rbuf pointers */
110 1.1 oster caddr_t ta; /* temporary data buffer pointer */
111 1.1 oster RF_CallbackDesc_t *cb, *p;
112 1.1 oster int retcode = 0, created = 0;
113 1.1 oster
114 1.1 oster RF_Etimer_t timer;
115 1.1 oster
116 1.1 oster /* makes no sense to have a submission from the failed disk */
117 1.1 oster RF_ASSERT(rbuf);
118 1.1 oster RF_ASSERT(rbuf->col != reconCtrlPtr->fcol);
119 1.1 oster
120 1.1 oster Dprintf5("RECON: submission by row %d col %d for psid %ld ru %d (failed offset %ld)\n",
121 1.1 oster rbuf->row, rbuf->col, (long)rbuf->parityStripeID, rbuf->which_ru, (long)rbuf->failedDiskSectorOffset);
122 1.1 oster
123 1.1 oster RF_LOCK_PSS_MUTEX(raidPtr,rbuf->row,rbuf->parityStripeID);
124 1.1 oster
125 1.1 oster RF_LOCK_MUTEX(reconCtrlPtr->rb_mutex);
126 1.1 oster
127 1.1 oster pssPtr = rf_LookupRUStatus(raidPtr, reconCtrlPtr->pssTable, rbuf->parityStripeID, rbuf->which_ru, RF_PSS_NONE, &created);
128 1.1 oster RF_ASSERT(pssPtr); /* if it didn't exist, we wouldn't have gotten an rbuf for it */
129 1.1 oster
130 1.1 oster /* check to see if enough buffers have accumulated to do an XOR. If so, there's no need to
131 1.1 oster * acquire a floating rbuf. Before we can do any XORing, we must have acquired a destination
132 1.1 oster * buffer. If we have, then we can go ahead and do the XOR if (1) including this buffer, enough
133 1.1 oster * bufs have accumulated, or (2) this is the last submission for this stripe.
134 1.1 oster * Otherwise, we have to go acquire a floating rbuf.
135 1.1 oster */
136 1.1 oster
137 1.1 oster targetRbuf = (RF_ReconBuffer_t *) pssPtr->rbuf;
138 1.1 oster if ( (targetRbuf != NULL) &&
139 1.1 oster ((pssPtr->xorBufCount == rf_numBufsToAccumulate-1) || (targetRbuf->count + pssPtr->xorBufCount + 1 == layoutPtr->numDataCol)) ) {
140 1.1 oster pssPtr->rbufsForXor[ pssPtr->xorBufCount++ ] = rbuf; /* install this buffer */
141 1.1 oster Dprintf3("RECON: row %d col %d invoking a %d-way XOR\n",rbuf->row, rbuf->col,pssPtr->xorBufCount);
142 1.1 oster RF_ETIMER_START(timer);
143 1.1 oster rf_MultiWayReconXor(raidPtr, pssPtr);
144 1.1 oster RF_ETIMER_STOP(timer); RF_ETIMER_EVAL(timer);
145 1.1 oster raidPtr->accumXorTimeUs += RF_ETIMER_VAL_US(timer);
146 1.1 oster if (!keep_it) {
147 1.1 oster raidPtr->recon_tracerecs[rbuf->col].xor_us = RF_ETIMER_VAL_US(timer);
148 1.1 oster RF_ETIMER_STOP(raidPtr->recon_tracerecs[rbuf->col].recon_timer);
149 1.1 oster RF_ETIMER_EVAL(raidPtr->recon_tracerecs[rbuf->col].recon_timer);
150 1.1 oster raidPtr->recon_tracerecs[rbuf->col].specific.recon.recon_return_to_submit_us +=
151 1.1 oster RF_ETIMER_VAL_US(raidPtr->recon_tracerecs[rbuf->col].recon_timer);
152 1.1 oster RF_ETIMER_START(raidPtr->recon_tracerecs[rbuf->col].recon_timer);
153 1.1 oster
154 1.1 oster rf_LogTraceRec(raidPtr, &raidPtr->recon_tracerecs[rbuf->col]);
155 1.1 oster }
156 1.1 oster rf_CheckForFullRbuf(raidPtr, reconCtrlPtr, pssPtr, layoutPtr->numDataCol);
157 1.1 oster
158 1.1 oster /* if use_committed is on, we _must_ consume a buffer off the committed list. */
159 1.1 oster if (use_committed) {
160 1.1 oster t = reconCtrlPtr->committedRbufs;
161 1.1 oster RF_ASSERT(t);
162 1.1 oster reconCtrlPtr->committedRbufs = t->next;
163 1.1 oster rf_ReleaseFloatingReconBuffer(raidPtr, rbuf->row, t);
164 1.1 oster }
165 1.1 oster if (keep_it) {
166 1.1 oster RF_UNLOCK_PSS_MUTEX( raidPtr,rbuf->row,rbuf->parityStripeID);
167 1.1 oster RF_UNLOCK_MUTEX( reconCtrlPtr->rb_mutex );
168 1.1 oster rf_FreeReconBuffer(rbuf);
169 1.1 oster return(retcode);
170 1.1 oster }
171 1.1 oster goto out;
172 1.1 oster }
173 1.1 oster
174 1.1 oster /* set the value of "t", which we'll use as the rbuf from here on */
175 1.1 oster if (keep_it) {
176 1.1 oster t = rbuf;
177 1.1 oster }
178 1.1 oster else {
179 1.1 oster if (use_committed) { /* if a buffer has been committed to us, use it */
180 1.1 oster t = reconCtrlPtr->committedRbufs;
181 1.1 oster RF_ASSERT(t);
182 1.1 oster reconCtrlPtr->committedRbufs = t->next;
183 1.1 oster t->next = NULL;
184 1.1 oster } else if (reconCtrlPtr->floatingRbufs) {
185 1.1 oster t = reconCtrlPtr->floatingRbufs;
186 1.1 oster reconCtrlPtr->floatingRbufs = t->next;
187 1.1 oster t->next = NULL;
188 1.1 oster }
189 1.1 oster }
190 1.1 oster
191 1.1 oster /* If we weren't able to acquire a buffer,
192 1.1 oster * append to the end of the buf list in the recon ctrl struct.
193 1.1 oster */
194 1.1 oster if (!t) {
195 1.1 oster RF_ASSERT(!keep_it && !use_committed);
196 1.1 oster Dprintf2("RECON: row %d col %d failed to acquire floating rbuf\n",rbuf->row, rbuf->col);
197 1.1 oster
198 1.1 oster raidPtr->procsInBufWait++;
199 1.1 oster if ( (raidPtr->procsInBufWait == raidPtr->numCol -1) && (raidPtr->numFullReconBuffers == 0)) {
200 1.1 oster printf("Buffer wait deadlock detected. Exiting.\n");
201 1.1 oster rf_PrintPSStatusTable(raidPtr, rbuf->row);
202 1.1 oster RF_PANIC();
203 1.1 oster }
204 1.1 oster pssPtr->flags |= RF_PSS_BUFFERWAIT;
205 1.1 oster cb = rf_AllocCallbackDesc(); /* append to buf wait list in recon ctrl structure */
206 1.1 oster cb->row = rbuf->row; cb->col = rbuf->col;
207 1.1 oster cb->callbackArg.v = rbuf->parityStripeID;
208 1.1 oster cb->callbackArg2.v = rbuf->which_ru;
209 1.1 oster cb->next = NULL;
210 1.1 oster if (!reconCtrlPtr->bufferWaitList) reconCtrlPtr->bufferWaitList = cb;
211 1.1 oster else { /* might want to maintain head/tail pointers here rather than search for end of list */
212 1.1 oster for (p = reconCtrlPtr->bufferWaitList; p->next; p=p->next);
213 1.1 oster p->next = cb;
214 1.1 oster }
215 1.1 oster retcode = 1;
216 1.1 oster goto out;
217 1.1 oster }
218 1.1 oster Dprintf2("RECON: row %d col %d acquired rbuf\n",rbuf->row, rbuf->col);
219 1.1 oster RF_ETIMER_STOP(raidPtr->recon_tracerecs[rbuf->col].recon_timer);
220 1.1 oster RF_ETIMER_EVAL(raidPtr->recon_tracerecs[rbuf->col].recon_timer);
221 1.1 oster raidPtr->recon_tracerecs[rbuf->col].specific.recon.recon_return_to_submit_us +=
222 1.1 oster RF_ETIMER_VAL_US(raidPtr->recon_tracerecs[rbuf->col].recon_timer);
223 1.1 oster RF_ETIMER_START(raidPtr->recon_tracerecs[rbuf->col].recon_timer);
224 1.1 oster
225 1.1 oster rf_LogTraceRec(raidPtr, &raidPtr->recon_tracerecs[rbuf->col]);
226 1.1 oster
227 1.1 oster /* initialize the buffer */
228 1.1 oster if (t!=rbuf) {
229 1.1 oster t->row = rbuf->row; t->col = reconCtrlPtr->fcol;
230 1.1 oster t->parityStripeID = rbuf->parityStripeID;
231 1.1 oster t->which_ru = rbuf->which_ru;
232 1.1 oster t->failedDiskSectorOffset = rbuf->failedDiskSectorOffset;
233 1.1 oster t->spRow=rbuf->spRow;
234 1.1 oster t->spCol=rbuf->spCol;
235 1.1 oster t->spOffset=rbuf->spOffset;
236 1.1 oster
237 1.1 oster ta = t->buffer; t->buffer = rbuf->buffer; rbuf->buffer = ta; /* swap buffers */
238 1.1 oster }
239 1.1 oster
240 1.1 oster /* the first installation always gets installed as the destination buffer.
241 1.1 oster * subsequent installations get stacked up to allow for multi-way XOR
242 1.1 oster */
243 1.1 oster if (!pssPtr->rbuf) {pssPtr->rbuf = t; t->count = 1;}
244 1.1 oster else pssPtr->rbufsForXor[ pssPtr->xorBufCount++ ] = t; /* install this buffer */
245 1.1 oster
246 1.1 oster rf_CheckForFullRbuf(raidPtr, reconCtrlPtr, pssPtr, layoutPtr->numDataCol); /* the buffer is full if G=2 */
247 1.1 oster
248 1.1 oster out:
249 1.1 oster RF_UNLOCK_PSS_MUTEX( raidPtr,rbuf->row,rbuf->parityStripeID);
250 1.1 oster RF_UNLOCK_MUTEX( reconCtrlPtr->rb_mutex );
251 1.1 oster return(retcode);
252 1.1 oster }
253 1.1 oster
254 1.1 oster int rf_MultiWayReconXor(raidPtr, pssPtr)
255 1.1 oster RF_Raid_t *raidPtr;
256 1.1 oster RF_ReconParityStripeStatus_t *pssPtr; /* the pss descriptor for this parity stripe */
257 1.1 oster {
258 1.1 oster int i, numBufs = pssPtr->xorBufCount;
259 1.1 oster int numBytes = rf_RaidAddressToByte(raidPtr, raidPtr->Layout.sectorsPerStripeUnit * raidPtr->Layout.SUsPerRU);
260 1.1 oster RF_ReconBuffer_t **rbufs = (RF_ReconBuffer_t **) pssPtr->rbufsForXor;
261 1.1 oster RF_ReconBuffer_t *targetRbuf = (RF_ReconBuffer_t *) pssPtr->rbuf;
262 1.1 oster
263 1.1 oster RF_ASSERT(pssPtr->rbuf != NULL);
264 1.1 oster RF_ASSERT(numBufs > 0 && numBufs < RF_PS_MAX_BUFS);
265 1.2 oster #ifdef _KERNEL
266 1.1 oster #ifndef __NetBSD__
267 1.1 oster thread_block(); /* yield the processor before doing a big XOR */
268 1.1 oster #endif
269 1.2 oster #endif /* _KERNEL */
270 1.1 oster /*
271 1.1 oster * XXX
272 1.1 oster *
273 1.1 oster * What if more than 9 bufs?
274 1.1 oster */
275 1.1 oster nWayXorFuncs[numBufs](pssPtr->rbufsForXor, targetRbuf, numBytes/sizeof(long));
276 1.1 oster
277 1.1 oster /* release all the reconstruction buffers except the last one, which belongs to the
278 1.1 oster * the disk who's submission caused this XOR to take place
279 1.1 oster */
280 1.1 oster for (i=0; i < numBufs-1; i++) {
281 1.1 oster if (rbufs[i]->type == RF_RBUF_TYPE_FLOATING) rf_ReleaseFloatingReconBuffer(raidPtr, rbufs[i]->row, rbufs[i]);
282 1.1 oster else if (rbufs[i]->type == RF_RBUF_TYPE_FORCED) rf_FreeReconBuffer(rbufs[i]);
283 1.1 oster else RF_ASSERT(0);
284 1.1 oster }
285 1.1 oster targetRbuf->count += pssPtr->xorBufCount;
286 1.1 oster pssPtr->xorBufCount = 0;
287 1.1 oster return(0);
288 1.1 oster }
289 1.1 oster
290 1.1 oster /* removes one full buffer from one of the full-buffer lists and returns it.
291 1.1 oster *
292 1.1 oster * ASSUMES THE RB_MUTEX IS UNLOCKED AT ENTRY.
293 1.1 oster */
294 1.1 oster RF_ReconBuffer_t *rf_GetFullReconBuffer(reconCtrlPtr)
295 1.1 oster RF_ReconCtrl_t *reconCtrlPtr;
296 1.1 oster {
297 1.1 oster RF_ReconBuffer_t *p;
298 1.1 oster
299 1.1 oster RF_LOCK_MUTEX(reconCtrlPtr->rb_mutex);
300 1.1 oster
301 1.1 oster if ( (p=reconCtrlPtr->priorityList) != NULL) {
302 1.1 oster reconCtrlPtr->priorityList = p->next;
303 1.1 oster p->next = NULL;
304 1.1 oster goto out;
305 1.1 oster }
306 1.1 oster if ( (p=reconCtrlPtr->fullBufferList) != NULL) {
307 1.1 oster reconCtrlPtr->fullBufferList = p->next;
308 1.1 oster p->next = NULL;
309 1.1 oster goto out;
310 1.1 oster }
311 1.1 oster
312 1.1 oster out:
313 1.1 oster RF_UNLOCK_MUTEX(reconCtrlPtr->rb_mutex);
314 1.1 oster return(p);
315 1.1 oster }
316 1.1 oster
317 1.1 oster
318 1.1 oster /* if the reconstruction buffer is full, move it to the full list, which is maintained
319 1.1 oster * sorted by failed disk sector offset
320 1.1 oster *
321 1.1 oster * ASSUMES THE RB_MUTEX IS LOCKED AT ENTRY.
322 1.1 oster */
323 1.1 oster int rf_CheckForFullRbuf(raidPtr, reconCtrl, pssPtr, numDataCol)
324 1.1 oster RF_Raid_t *raidPtr;
325 1.1 oster RF_ReconCtrl_t *reconCtrl;
326 1.1 oster RF_ReconParityStripeStatus_t *pssPtr;
327 1.1 oster int numDataCol;
328 1.1 oster {
329 1.1 oster RF_ReconBuffer_t *p, *pt, *rbuf = (RF_ReconBuffer_t *) pssPtr->rbuf;
330 1.1 oster
331 1.1 oster if (rbuf->count == numDataCol) {
332 1.1 oster raidPtr->numFullReconBuffers++;
333 1.1 oster Dprintf2("RECON: rbuf for psid %ld ru %d has filled\n",
334 1.1 oster (long)rbuf->parityStripeID, rbuf->which_ru);
335 1.1 oster if (!reconCtrl->fullBufferList || (rbuf->failedDiskSectorOffset < reconCtrl->fullBufferList->failedDiskSectorOffset)) {
336 1.1 oster Dprintf2("RECON: rbuf for psid %ld ru %d is head of list\n",
337 1.1 oster (long)rbuf->parityStripeID, rbuf->which_ru);
338 1.1 oster rbuf->next = reconCtrl->fullBufferList;
339 1.1 oster reconCtrl->fullBufferList = rbuf;
340 1.1 oster }
341 1.1 oster else {
342 1.1 oster for (pt = reconCtrl->fullBufferList, p = pt->next; p && p->failedDiskSectorOffset < rbuf->failedDiskSectorOffset; pt=p, p=p->next);
343 1.1 oster rbuf->next = p;
344 1.1 oster pt->next = rbuf;
345 1.1 oster Dprintf2("RECON: rbuf for psid %ld ru %d is in list\n",
346 1.1 oster (long)rbuf->parityStripeID, rbuf->which_ru);
347 1.1 oster }
348 1.1 oster #if 0
349 1.1 oster pssPtr->writeRbuf = pssPtr->rbuf; /* DEBUG ONLY: we like to be able to find this rbuf while it's awaiting write */
350 1.1 oster #else
351 1.1 oster rbuf->pssPtr = pssPtr;
352 1.1 oster #endif
353 1.1 oster pssPtr->rbuf = NULL;
354 1.1 oster rf_CauseReconEvent(raidPtr, rbuf->row, rbuf->col, NULL, RF_REVENT_BUFREADY);
355 1.1 oster }
356 1.1 oster return(0);
357 1.1 oster }
358 1.1 oster
359 1.1 oster
360 1.1 oster /* release a floating recon buffer for someone else to use.
361 1.1 oster * assumes the rb_mutex is LOCKED at entry
362 1.1 oster */
363 1.1 oster void rf_ReleaseFloatingReconBuffer(raidPtr, row, rbuf)
364 1.1 oster RF_Raid_t *raidPtr;
365 1.1 oster RF_RowCol_t row;
366 1.1 oster RF_ReconBuffer_t *rbuf;
367 1.1 oster {
368 1.1 oster RF_ReconCtrl_t *rcPtr = raidPtr->reconControl[row];
369 1.1 oster RF_CallbackDesc_t *cb;
370 1.1 oster
371 1.1 oster Dprintf2("RECON: releasing rbuf for psid %ld ru %d\n",
372 1.1 oster (long)rbuf->parityStripeID, rbuf->which_ru);
373 1.1 oster
374 1.1 oster /* if anyone is waiting on buffers, wake one of them up. They will subsequently wake up anyone
375 1.1 oster * else waiting on their RU
376 1.1 oster */
377 1.1 oster if (rcPtr->bufferWaitList) {
378 1.1 oster rbuf->next = rcPtr->committedRbufs;
379 1.1 oster rcPtr->committedRbufs = rbuf;
380 1.1 oster cb = rcPtr->bufferWaitList;
381 1.1 oster rcPtr->bufferWaitList = cb->next;
382 1.1 oster rf_CauseReconEvent(raidPtr, cb->row, cb->col, (void *) 1, RF_REVENT_BUFCLEAR); /* arg==1 => we've committed a buffer */
383 1.1 oster rf_FreeCallbackDesc(cb);
384 1.1 oster raidPtr->procsInBufWait--;
385 1.1 oster } else {
386 1.1 oster rbuf->next = rcPtr->floatingRbufs;
387 1.1 oster rcPtr->floatingRbufs = rbuf;
388 1.1 oster }
389 1.1 oster }
390 1.1 oster
391 1.1 oster /* release any disk that is waiting on a buffer for the indicated RU.
392 1.1 oster * assumes the rb_mutex is LOCKED at entry
393 1.1 oster */
394 1.1 oster void rf_ReleaseBufferWaiters(raidPtr, pssPtr)
395 1.1 oster RF_Raid_t *raidPtr;
396 1.1 oster RF_ReconParityStripeStatus_t *pssPtr;
397 1.1 oster {
398 1.1 oster RF_CallbackDesc_t *cb1, *cb = pssPtr->bufWaitList;
399 1.1 oster
400 1.1 oster Dprintf2("RECON: releasing buf waiters for psid %ld ru %d\n",
401 1.1 oster (long)pssPtr->parityStripeID, pssPtr->which_ru);
402 1.1 oster pssPtr->flags &= ~RF_PSS_BUFFERWAIT;
403 1.1 oster while (cb) {
404 1.1 oster cb1 = cb->next;
405 1.1 oster cb->next = NULL;
406 1.1 oster rf_CauseReconEvent(raidPtr, cb->row, cb->col, (void *) 0, RF_REVENT_BUFCLEAR); /* arg==0 => we haven't committed a buffer */
407 1.1 oster rf_FreeCallbackDesc(cb);
408 1.1 oster cb = cb1;
409 1.1 oster }
410 1.1 oster pssPtr->bufWaitList = NULL;
411 1.1 oster }
412 1.1 oster
413 1.1 oster /* when reconstruction is forced on an RU, there may be some disks waiting to
414 1.1 oster * acquire a buffer for that RU. Since we allocate a new buffer as part of
415 1.1 oster * the forced-reconstruction process, we no longer have to wait for any
416 1.1 oster * buffers, so we wakeup any waiter that we find in the bufferWaitList
417 1.1 oster *
418 1.1 oster * assumes the rb_mutex is LOCKED at entry
419 1.1 oster */
420 1.1 oster void rf_ReleaseBufferWaiter(rcPtr, rbuf)
421 1.1 oster RF_ReconCtrl_t *rcPtr;
422 1.1 oster RF_ReconBuffer_t *rbuf;
423 1.1 oster {
424 1.1 oster RF_CallbackDesc_t *cb, *cbt;
425 1.1 oster
426 1.1 oster for (cbt = NULL, cb = rcPtr->bufferWaitList; cb; cbt = cb, cb=cb->next) {
427 1.1 oster if ( (cb->callbackArg.v == rbuf->parityStripeID) && ( cb->callbackArg2.v == rbuf->which_ru)) {
428 1.1 oster Dprintf2("RECON: Dropping row %d col %d from buffer wait list\n", cb->row, cb->col);
429 1.1 oster if (cbt) cbt->next = cb->next;
430 1.1 oster else rcPtr->bufferWaitList = cb->next;
431 1.1 oster rf_CauseReconEvent((RF_Raid_t *) rbuf->raidPtr, cb->row, cb->col, (void *) 0, RF_REVENT_BUFREADY); /* arg==0 => no committed buffer */
432 1.1 oster rf_FreeCallbackDesc(cb);
433 1.1 oster return;
434 1.1 oster }
435 1.1 oster }
436 1.1 oster }
437