rf_paritylog.c revision 1.2 1 1.2 oster /* $NetBSD: rf_paritylog.c,v 1.2 1999/01/26 02:33:59 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: William V. Courtright II
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 /* Code for manipulating in-core parity logs
30 1.1 oster *
31 1.1 oster */
32 1.1 oster
33 1.1 oster #include "rf_archs.h"
34 1.1 oster
35 1.1 oster #if RF_INCLUDE_PARITYLOGGING > 0
36 1.1 oster
37 1.1 oster /*
38 1.1 oster * Append-only log for recording parity "update" and "overwrite" records
39 1.1 oster */
40 1.1 oster
41 1.1 oster #include "rf_types.h"
42 1.1 oster #include "rf_threadstuff.h"
43 1.1 oster #include "rf_mcpair.h"
44 1.1 oster #include "rf_raid.h"
45 1.1 oster #include "rf_dag.h"
46 1.1 oster #include "rf_dagfuncs.h"
47 1.1 oster #include "rf_desc.h"
48 1.1 oster #include "rf_layout.h"
49 1.1 oster #include "rf_diskqueue.h"
50 1.1 oster #include "rf_etimer.h"
51 1.1 oster #include "rf_paritylog.h"
52 1.1 oster #include "rf_general.h"
53 1.1 oster #include "rf_threadid.h"
54 1.1 oster #include "rf_map.h"
55 1.1 oster #include "rf_paritylogging.h"
56 1.1 oster #include "rf_paritylogDiskMgr.h"
57 1.1 oster #include "rf_sys.h"
58 1.1 oster
59 1.1 oster static RF_CommonLogData_t *AllocParityLogCommonData(RF_Raid_t *raidPtr)
60 1.1 oster {
61 1.1 oster RF_CommonLogData_t *common = NULL;
62 1.1 oster int rc;
63 1.1 oster
64 1.1 oster /* Return a struct for holding common parity log information from the free
65 1.1 oster list (rf_parityLogDiskQueue.freeCommonList). If the free list is empty, call
66 1.1 oster RF_Malloc to create a new structure.
67 1.1 oster NON-BLOCKING */
68 1.1 oster
69 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
70 1.1 oster if (raidPtr->parityLogDiskQueue.freeCommonList)
71 1.1 oster {
72 1.1 oster common = raidPtr->parityLogDiskQueue.freeCommonList;
73 1.1 oster raidPtr->parityLogDiskQueue.freeCommonList = raidPtr->parityLogDiskQueue.freeCommonList->next;
74 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
75 1.1 oster }
76 1.1 oster else
77 1.1 oster {
78 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
79 1.1 oster RF_Malloc(common, sizeof(RF_CommonLogData_t), (RF_CommonLogData_t *));
80 1.1 oster rc = rf_mutex_init(&common->mutex);
81 1.1 oster if (rc) {
82 1.1 oster RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
83 1.1 oster __LINE__, rc);
84 1.1 oster RF_Free(common, sizeof(RF_CommonLogData_t));
85 1.1 oster common = NULL;
86 1.1 oster }
87 1.1 oster }
88 1.1 oster common->next = NULL;
89 1.1 oster return(common);
90 1.1 oster }
91 1.1 oster
92 1.1 oster static void FreeParityLogCommonData(RF_CommonLogData_t *common)
93 1.1 oster {
94 1.1 oster RF_Raid_t *raidPtr;
95 1.1 oster
96 1.1 oster /* Insert a single struct for holding parity log information
97 1.1 oster (data) into the free list (rf_parityLogDiskQueue.freeCommonList).
98 1.1 oster NON-BLOCKING */
99 1.1 oster
100 1.1 oster raidPtr = common->raidPtr;
101 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
102 1.1 oster common->next = raidPtr->parityLogDiskQueue.freeCommonList;
103 1.1 oster raidPtr->parityLogDiskQueue.freeCommonList = common;
104 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
105 1.1 oster }
106 1.1 oster
107 1.1 oster static RF_ParityLogData_t *AllocParityLogData(RF_Raid_t *raidPtr)
108 1.1 oster {
109 1.1 oster RF_ParityLogData_t *data = NULL;
110 1.1 oster
111 1.1 oster /* Return a struct for holding parity log information from the free
112 1.1 oster list (rf_parityLogDiskQueue.freeList). If the free list is empty, call
113 1.1 oster RF_Malloc to create a new structure.
114 1.1 oster NON-BLOCKING */
115 1.1 oster
116 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
117 1.1 oster if (raidPtr->parityLogDiskQueue.freeDataList)
118 1.1 oster {
119 1.1 oster data = raidPtr->parityLogDiskQueue.freeDataList;
120 1.1 oster raidPtr->parityLogDiskQueue.freeDataList = raidPtr->parityLogDiskQueue.freeDataList->next;
121 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
122 1.1 oster }
123 1.1 oster else
124 1.1 oster {
125 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
126 1.1 oster RF_Malloc(data, sizeof(RF_ParityLogData_t), (RF_ParityLogData_t *));
127 1.1 oster }
128 1.1 oster data->next = NULL;
129 1.1 oster data->prev = NULL;
130 1.1 oster return(data);
131 1.1 oster }
132 1.1 oster
133 1.1 oster
134 1.1 oster static void FreeParityLogData(RF_ParityLogData_t *data)
135 1.1 oster {
136 1.1 oster RF_ParityLogData_t *nextItem;
137 1.1 oster RF_Raid_t *raidPtr;
138 1.1 oster
139 1.1 oster /* Insert a linked list of structs for holding parity log
140 1.1 oster information (data) into the free list (parityLogDiskQueue.freeList).
141 1.1 oster NON-BLOCKING */
142 1.1 oster
143 1.1 oster raidPtr = data->common->raidPtr;
144 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
145 1.1 oster while (data)
146 1.1 oster {
147 1.1 oster nextItem = data->next;
148 1.1 oster data->next = raidPtr->parityLogDiskQueue.freeDataList;
149 1.1 oster raidPtr->parityLogDiskQueue.freeDataList = data;
150 1.1 oster data = nextItem;
151 1.1 oster }
152 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
153 1.1 oster }
154 1.1 oster
155 1.1 oster
156 1.1 oster static void EnqueueParityLogData(
157 1.1 oster RF_ParityLogData_t *data,
158 1.1 oster RF_ParityLogData_t **head,
159 1.1 oster RF_ParityLogData_t **tail)
160 1.1 oster {
161 1.1 oster RF_Raid_t *raidPtr;
162 1.1 oster
163 1.1 oster /* Insert an in-core parity log (*data) into the head of
164 1.1 oster a disk queue (*head, *tail).
165 1.1 oster NON-BLOCKING */
166 1.1 oster
167 1.1 oster raidPtr = data->common->raidPtr;
168 1.1 oster if (rf_parityLogDebug)
169 1.1 oster printf("[enqueueing parity log data, region %d, raidAddress %d, numSector %d]\n",data->regionID,(int)data->diskAddress.raidAddress, (int)data->diskAddress.numSector);
170 1.1 oster RF_ASSERT(data->prev == NULL);
171 1.1 oster RF_ASSERT(data->next == NULL);
172 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
173 1.1 oster if (*head)
174 1.1 oster {
175 1.1 oster /* insert into head of queue */
176 1.1 oster RF_ASSERT((*head)->prev == NULL);
177 1.1 oster RF_ASSERT((*tail)->next == NULL);
178 1.1 oster data->next = *head;
179 1.1 oster (*head)->prev = data;
180 1.1 oster *head = data;
181 1.1 oster }
182 1.1 oster else
183 1.1 oster {
184 1.1 oster /* insert into empty list */
185 1.1 oster RF_ASSERT(*head == NULL);
186 1.1 oster RF_ASSERT(*tail == NULL);
187 1.1 oster *head = data;
188 1.1 oster *tail = data;
189 1.1 oster }
190 1.1 oster RF_ASSERT((*head)->prev == NULL);
191 1.1 oster RF_ASSERT((*tail)->next == NULL);
192 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
193 1.1 oster }
194 1.1 oster
195 1.1 oster static RF_ParityLogData_t *DequeueParityLogData(
196 1.1 oster RF_Raid_t *raidPtr,
197 1.1 oster RF_ParityLogData_t **head,
198 1.1 oster RF_ParityLogData_t **tail,
199 1.1 oster int ignoreLocks)
200 1.1 oster {
201 1.1 oster RF_ParityLogData_t *data;
202 1.1 oster
203 1.1 oster /* Remove and return an in-core parity log from the tail of
204 1.1 oster a disk queue (*head, *tail).
205 1.1 oster NON-BLOCKING */
206 1.1 oster
207 1.1 oster /* remove from tail, preserving FIFO order */
208 1.1 oster if (!ignoreLocks)
209 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
210 1.1 oster data = *tail;
211 1.1 oster if (data)
212 1.1 oster {
213 1.1 oster if (*head == *tail)
214 1.1 oster {
215 1.1 oster /* removing last item from queue */
216 1.1 oster *head = NULL;
217 1.1 oster *tail = NULL;
218 1.1 oster }
219 1.1 oster else
220 1.1 oster {
221 1.1 oster *tail = (*tail)->prev;
222 1.1 oster (*tail)->next = NULL;
223 1.1 oster RF_ASSERT((*head)->prev == NULL);
224 1.1 oster RF_ASSERT((*tail)->next == NULL);
225 1.1 oster }
226 1.1 oster data->next = NULL;
227 1.1 oster data->prev = NULL;
228 1.1 oster if (rf_parityLogDebug)
229 1.1 oster printf("[dequeueing parity log data, region %d, raidAddress %d, numSector %d]\n",data->regionID,(int)data->diskAddress.raidAddress, (int)data->diskAddress.numSector);
230 1.1 oster }
231 1.1 oster if (*head)
232 1.1 oster {
233 1.1 oster RF_ASSERT((*head)->prev == NULL);
234 1.1 oster RF_ASSERT((*tail)->next == NULL);
235 1.1 oster }
236 1.1 oster if (!ignoreLocks)
237 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
238 1.1 oster return(data);
239 1.1 oster }
240 1.1 oster
241 1.1 oster
242 1.1 oster static void RequeueParityLogData(
243 1.1 oster RF_ParityLogData_t *data,
244 1.1 oster RF_ParityLogData_t **head,
245 1.1 oster RF_ParityLogData_t **tail)
246 1.1 oster {
247 1.1 oster RF_Raid_t *raidPtr;
248 1.1 oster
249 1.1 oster /* Insert an in-core parity log (*data) into the tail of
250 1.1 oster a disk queue (*head, *tail).
251 1.1 oster NON-BLOCKING */
252 1.1 oster
253 1.1 oster raidPtr = data->common->raidPtr;
254 1.1 oster RF_ASSERT(data);
255 1.1 oster if (rf_parityLogDebug)
256 1.1 oster printf("[requeueing parity log data, region %d, raidAddress %d, numSector %d]\n",data->regionID,(int)data->diskAddress.raidAddress, (int) data->diskAddress.numSector);
257 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
258 1.1 oster if (*tail)
259 1.1 oster {
260 1.1 oster /* append to tail of list */
261 1.1 oster data->prev = *tail;
262 1.1 oster data->next = NULL;
263 1.1 oster (*tail)->next = data;
264 1.1 oster *tail = data;
265 1.1 oster }
266 1.1 oster else
267 1.1 oster {
268 1.1 oster /* inserting into an empty list */
269 1.1 oster *head = data;
270 1.1 oster *tail = data;
271 1.1 oster (*head)->prev = NULL;
272 1.1 oster (*tail)->next = NULL;
273 1.1 oster }
274 1.1 oster RF_ASSERT((*head)->prev == NULL);
275 1.1 oster RF_ASSERT((*tail)->next == NULL);
276 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
277 1.1 oster }
278 1.1 oster
279 1.1 oster RF_ParityLogData_t *rf_CreateParityLogData(
280 1.1 oster RF_ParityRecordType_t operation,
281 1.1 oster RF_PhysDiskAddr_t *pda,
282 1.1 oster caddr_t bufPtr,
283 1.1 oster RF_Raid_t *raidPtr,
284 1.1 oster int (*wakeFunc)(RF_DagNode_t *node, int status),
285 1.1 oster void *wakeArg,
286 1.1 oster RF_AccTraceEntry_t *tracerec,
287 1.1 oster RF_Etimer_t startTime)
288 1.1 oster {
289 1.1 oster RF_ParityLogData_t *data, *resultHead = NULL, *resultTail = NULL;
290 1.1 oster RF_CommonLogData_t *common;
291 1.1 oster RF_PhysDiskAddr_t *diskAddress;
292 1.1 oster int boundary, offset = 0;
293 1.1 oster
294 1.1 oster /* Return an initialized struct of info to be logged.
295 1.1 oster Build one item per physical disk address, one item per region.
296 1.1 oster
297 1.1 oster NON-BLOCKING */
298 1.1 oster
299 1.1 oster diskAddress = pda;
300 1.1 oster common = AllocParityLogCommonData(raidPtr);
301 1.1 oster RF_ASSERT(common);
302 1.1 oster
303 1.1 oster common->operation = operation;
304 1.1 oster common->bufPtr = bufPtr;
305 1.1 oster common->raidPtr = raidPtr;
306 1.1 oster common->wakeFunc = wakeFunc;
307 1.1 oster common->wakeArg = wakeArg;
308 1.1 oster common->tracerec = tracerec;
309 1.1 oster common->startTime = startTime;
310 1.1 oster common->cnt = 0;
311 1.1 oster
312 1.1 oster if (rf_parityLogDebug)
313 1.1 oster printf("[entering CreateParityLogData]\n");
314 1.1 oster while (diskAddress)
315 1.1 oster {
316 1.1 oster common->cnt++;
317 1.1 oster data = AllocParityLogData(raidPtr);
318 1.1 oster RF_ASSERT(data);
319 1.1 oster data->common = common;
320 1.1 oster data->next = NULL;
321 1.1 oster data->prev = NULL;
322 1.1 oster data->regionID = rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector);
323 1.1 oster if (data->regionID == rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector + diskAddress->numSector - 1))
324 1.1 oster {
325 1.1 oster /* disk address does not cross a region boundary */
326 1.1 oster data->diskAddress = *diskAddress;
327 1.1 oster data->bufOffset = offset;
328 1.1 oster offset = offset + diskAddress->numSector;
329 1.1 oster EnqueueParityLogData(data, &resultHead, &resultTail);
330 1.1 oster /* adjust disk address */
331 1.1 oster diskAddress = diskAddress->next;
332 1.1 oster }
333 1.1 oster else
334 1.1 oster {
335 1.1 oster /* disk address crosses a region boundary */
336 1.1 oster /* find address where region is crossed */
337 1.1 oster boundary = 0;
338 1.1 oster while (data->regionID == rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector + boundary))
339 1.1 oster boundary++;
340 1.1 oster
341 1.1 oster /* enter data before the boundary */
342 1.1 oster data->diskAddress = *diskAddress;
343 1.1 oster data->diskAddress.numSector = boundary;
344 1.1 oster data->bufOffset = offset;
345 1.1 oster offset += boundary;
346 1.1 oster EnqueueParityLogData(data, &resultHead, &resultTail);
347 1.1 oster /* adjust disk address */
348 1.1 oster diskAddress->startSector += boundary;
349 1.1 oster diskAddress->numSector -= boundary;
350 1.1 oster }
351 1.1 oster }
352 1.1 oster if (rf_parityLogDebug)
353 1.1 oster printf("[leaving CreateParityLogData]\n");
354 1.1 oster return(resultHead);
355 1.1 oster }
356 1.1 oster
357 1.1 oster
358 1.1 oster RF_ParityLogData_t *rf_SearchAndDequeueParityLogData(
359 1.1 oster RF_Raid_t *raidPtr,
360 1.1 oster int regionID,
361 1.1 oster RF_ParityLogData_t **head,
362 1.1 oster RF_ParityLogData_t **tail,
363 1.1 oster int ignoreLocks)
364 1.1 oster {
365 1.1 oster RF_ParityLogData_t *w;
366 1.1 oster
367 1.1 oster /* Remove and return an in-core parity log from a specified region (regionID).
368 1.1 oster If a matching log is not found, return NULL.
369 1.1 oster
370 1.1 oster NON-BLOCKING.
371 1.1 oster */
372 1.1 oster
373 1.1 oster /* walk backward through a list, looking for an entry with a matching region ID */
374 1.1 oster if (!ignoreLocks)
375 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
376 1.1 oster w = (*tail);
377 1.1 oster while (w)
378 1.1 oster {
379 1.1 oster if (w->regionID == regionID)
380 1.1 oster {
381 1.1 oster /* remove an element from the list */
382 1.1 oster if (w == *tail)
383 1.1 oster {
384 1.1 oster if (*head == *tail)
385 1.1 oster {
386 1.1 oster /* removing only element in the list */
387 1.1 oster *head = NULL;
388 1.1 oster *tail = NULL;
389 1.1 oster }
390 1.1 oster else
391 1.1 oster {
392 1.1 oster /* removing last item in the list */
393 1.1 oster *tail = (*tail)->prev;
394 1.1 oster (*tail)->next = NULL;
395 1.1 oster RF_ASSERT((*head)->prev == NULL);
396 1.1 oster RF_ASSERT((*tail)->next == NULL);
397 1.1 oster }
398 1.1 oster }
399 1.1 oster else
400 1.1 oster {
401 1.1 oster if (w == *head)
402 1.1 oster {
403 1.1 oster /* removing first item in the list */
404 1.1 oster *head = (*head)->next;
405 1.1 oster (*head)->prev = NULL;
406 1.1 oster RF_ASSERT((*head)->prev == NULL);
407 1.1 oster RF_ASSERT((*tail)->next == NULL);
408 1.1 oster }
409 1.1 oster else
410 1.1 oster {
411 1.1 oster /* removing an item from the middle of the list */
412 1.1 oster w->prev->next = w->next;
413 1.1 oster w->next->prev = w->prev;
414 1.1 oster RF_ASSERT((*head)->prev == NULL);
415 1.1 oster RF_ASSERT((*tail)->next == NULL);
416 1.1 oster }
417 1.1 oster }
418 1.1 oster w->prev = NULL;
419 1.1 oster w->next = NULL;
420 1.1 oster if (rf_parityLogDebug)
421 1.1 oster printf("[dequeueing parity log data, region %d, raidAddress %d, numSector %d]\n",w->regionID,(int)w->diskAddress.raidAddress,(int) w->diskAddress.numSector);
422 1.1 oster return(w);
423 1.1 oster }
424 1.1 oster else
425 1.1 oster w = w->prev;
426 1.1 oster }
427 1.1 oster if (!ignoreLocks)
428 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
429 1.1 oster return(NULL);
430 1.1 oster }
431 1.1 oster
432 1.1 oster static RF_ParityLogData_t *DequeueMatchingLogData(
433 1.1 oster RF_Raid_t *raidPtr,
434 1.1 oster RF_ParityLogData_t **head,
435 1.1 oster RF_ParityLogData_t **tail)
436 1.1 oster {
437 1.1 oster RF_ParityLogData_t *logDataList, *logData;
438 1.1 oster int regionID;
439 1.1 oster
440 1.1 oster /* Remove and return an in-core parity log from the tail of
441 1.1 oster a disk queue (*head, *tail). Then remove all matching
442 1.1 oster (identical regionIDs) logData and return as a linked list.
443 1.1 oster
444 1.1 oster NON-BLOCKING
445 1.1 oster */
446 1.1 oster
447 1.1 oster logDataList = DequeueParityLogData(raidPtr, head, tail, RF_TRUE);
448 1.1 oster if (logDataList)
449 1.1 oster {
450 1.1 oster regionID = logDataList->regionID;
451 1.1 oster logData = logDataList;
452 1.1 oster logData->next = rf_SearchAndDequeueParityLogData(raidPtr, regionID, head, tail, RF_TRUE);
453 1.1 oster while (logData->next)
454 1.1 oster {
455 1.1 oster logData = logData->next;
456 1.1 oster logData->next = rf_SearchAndDequeueParityLogData(raidPtr, regionID, head, tail, RF_TRUE);
457 1.1 oster }
458 1.1 oster }
459 1.1 oster return(logDataList);
460 1.1 oster }
461 1.1 oster
462 1.1 oster
463 1.1 oster static RF_ParityLog_t *AcquireParityLog(
464 1.1 oster RF_ParityLogData_t *logData,
465 1.1 oster int finish)
466 1.1 oster {
467 1.1 oster RF_ParityLog_t *log = NULL;
468 1.1 oster RF_Raid_t *raidPtr;
469 1.1 oster
470 1.1 oster /* Grab a log buffer from the pool and return it.
471 1.1 oster If no buffers are available, return NULL.
472 1.1 oster NON-BLOCKING
473 1.1 oster */
474 1.1 oster raidPtr = logData->common->raidPtr;
475 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogPool.mutex);
476 1.1 oster if (raidPtr->parityLogPool.parityLogs)
477 1.1 oster {
478 1.1 oster log = raidPtr->parityLogPool.parityLogs;
479 1.1 oster raidPtr->parityLogPool.parityLogs = raidPtr->parityLogPool.parityLogs->next;
480 1.1 oster log->regionID = logData->regionID;
481 1.1 oster log->numRecords = 0;
482 1.1 oster log->next = NULL;
483 1.1 oster raidPtr->logsInUse++;
484 1.1 oster RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);
485 1.1 oster }
486 1.1 oster else
487 1.1 oster {
488 1.1 oster /* no logs available, so place ourselves on the queue of work waiting on log buffers
489 1.1 oster this is done while parityLogPool.mutex is held, to ensure synchronization
490 1.1 oster with ReleaseParityLogs.
491 1.1 oster */
492 1.1 oster if (rf_parityLogDebug)
493 1.1 oster printf("[blocked on log, region %d, finish %d]\n", logData->regionID, finish);
494 1.1 oster if (finish)
495 1.1 oster RequeueParityLogData(logData, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);
496 1.1 oster else
497 1.1 oster EnqueueParityLogData(logData, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);
498 1.1 oster }
499 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogPool.mutex);
500 1.1 oster return(log);
501 1.1 oster }
502 1.1 oster
503 1.1 oster void rf_ReleaseParityLogs(
504 1.1 oster RF_Raid_t *raidPtr,
505 1.1 oster RF_ParityLog_t *firstLog)
506 1.1 oster {
507 1.1 oster RF_ParityLogData_t *logDataList;
508 1.1 oster RF_ParityLog_t *log, *lastLog;
509 1.1 oster int cnt;
510 1.1 oster
511 1.1 oster /* Insert a linked list of parity logs (firstLog) to
512 1.1 oster the free list (parityLogPool.parityLogPool)
513 1.1 oster
514 1.1 oster NON-BLOCKING.
515 1.1 oster */
516 1.1 oster
517 1.1 oster RF_ASSERT(firstLog);
518 1.1 oster
519 1.1 oster /* Before returning logs to global free list, service all
520 1.1 oster requests which are blocked on logs. Holding mutexes for parityLogPool and parityLogDiskQueue
521 1.1 oster forces synchronization with AcquireParityLog().
522 1.1 oster */
523 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogPool.mutex);
524 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
525 1.1 oster logDataList = DequeueMatchingLogData(raidPtr, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);
526 1.1 oster log = firstLog;
527 1.1 oster if (firstLog)
528 1.1 oster firstLog = firstLog->next;
529 1.1 oster log->numRecords = 0;
530 1.1 oster log->next = NULL;
531 1.1 oster while (logDataList && log)
532 1.1 oster {
533 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogPool.mutex);
534 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
535 1.1 oster rf_ParityLogAppend(logDataList, RF_TRUE, &log, RF_FALSE);
536 1.1 oster if (rf_parityLogDebug)
537 1.1 oster printf("[finishing up buf-blocked log data, region %d]\n", logDataList->regionID);
538 1.1 oster if (log == NULL)
539 1.1 oster {
540 1.1 oster log = firstLog;
541 1.1 oster if (firstLog)
542 1.1 oster {
543 1.1 oster firstLog = firstLog->next;
544 1.1 oster log->numRecords = 0;
545 1.1 oster log->next = NULL;
546 1.1 oster }
547 1.1 oster }
548 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogPool.mutex);
549 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
550 1.1 oster if (log)
551 1.1 oster logDataList = DequeueMatchingLogData(raidPtr, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);
552 1.1 oster }
553 1.1 oster /* return remaining logs to pool */
554 1.1 oster if (log)
555 1.1 oster {
556 1.1 oster log->next = firstLog;
557 1.1 oster firstLog = log;
558 1.1 oster }
559 1.1 oster if (firstLog)
560 1.1 oster {
561 1.1 oster lastLog = firstLog;
562 1.1 oster raidPtr->logsInUse--;
563 1.1 oster RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);
564 1.1 oster while (lastLog->next)
565 1.1 oster {
566 1.1 oster lastLog = lastLog->next;
567 1.1 oster raidPtr->logsInUse--;
568 1.1 oster RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);
569 1.1 oster }
570 1.1 oster lastLog->next = raidPtr->parityLogPool.parityLogs;
571 1.1 oster raidPtr->parityLogPool.parityLogs = firstLog;
572 1.1 oster cnt = 0;
573 1.1 oster log = raidPtr->parityLogPool.parityLogs;
574 1.1 oster while (log)
575 1.1 oster {
576 1.1 oster cnt++;
577 1.1 oster log = log->next;
578 1.1 oster }
579 1.1 oster RF_ASSERT(cnt + raidPtr->logsInUse == raidPtr->numParityLogs);
580 1.1 oster }
581 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogPool.mutex);
582 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
583 1.1 oster }
584 1.1 oster
585 1.1 oster static void ReintLog(
586 1.1 oster RF_Raid_t *raidPtr,
587 1.1 oster int regionID,
588 1.1 oster RF_ParityLog_t *log)
589 1.1 oster {
590 1.1 oster RF_ASSERT(log);
591 1.1 oster
592 1.1 oster /* Insert an in-core parity log (log) into the disk queue of reintegration
593 1.1 oster work. Set the flag (reintInProgress) for the specified region (regionID)
594 1.1 oster to indicate that reintegration is in progress for this region.
595 1.1 oster NON-BLOCKING
596 1.1 oster */
597 1.1 oster
598 1.1 oster RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].reintMutex);
599 1.1 oster raidPtr->regionInfo[regionID].reintInProgress = RF_TRUE; /* cleared when reint complete */
600 1.1 oster
601 1.1 oster if (rf_parityLogDebug)
602 1.1 oster printf("[requesting reintegration of region %d]\n", log->regionID);
603 1.1 oster /* move record to reintegration queue */
604 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
605 1.1 oster log->next = raidPtr->parityLogDiskQueue.reintQueue;
606 1.1 oster raidPtr->parityLogDiskQueue.reintQueue = log;
607 1.1 oster RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].reintMutex);
608 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
609 1.1 oster RF_SIGNAL_COND(raidPtr->parityLogDiskQueue.cond);
610 1.1 oster }
611 1.1 oster
612 1.1 oster static void FlushLog(
613 1.1 oster RF_Raid_t *raidPtr,
614 1.1 oster RF_ParityLog_t *log)
615 1.1 oster {
616 1.1 oster /* insert a core log (log) into a list of logs (parityLogDiskQueue.flushQueue)
617 1.1 oster waiting to be written to disk.
618 1.1 oster NON-BLOCKING
619 1.1 oster */
620 1.1 oster
621 1.1 oster RF_ASSERT(log);
622 1.1 oster RF_ASSERT(log->numRecords == raidPtr->numSectorsPerLog);
623 1.1 oster RF_ASSERT(log->next == NULL);
624 1.1 oster /* move log to flush queue */
625 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
626 1.1 oster log->next = raidPtr->parityLogDiskQueue.flushQueue;
627 1.1 oster raidPtr->parityLogDiskQueue.flushQueue = log;
628 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
629 1.1 oster RF_SIGNAL_COND(raidPtr->parityLogDiskQueue.cond);
630 1.1 oster }
631 1.1 oster
632 1.1 oster static int DumpParityLogToDisk(
633 1.1 oster int finish,
634 1.1 oster RF_ParityLogData_t *logData)
635 1.1 oster {
636 1.1 oster int i, diskCount, regionID = logData->regionID;
637 1.1 oster RF_ParityLog_t *log;
638 1.1 oster RF_Raid_t *raidPtr;
639 1.1 oster
640 1.1 oster raidPtr = logData->common->raidPtr;
641 1.1 oster
642 1.1 oster /* Move a core log to disk. If the log disk is full, initiate
643 1.1 oster reintegration.
644 1.1 oster
645 1.1 oster Return (0) if we can enqueue the dump immediately, otherwise
646 1.1 oster return (1) to indicate we are blocked on reintegration and
647 1.1 oster control of the thread should be relinquished.
648 1.1 oster
649 1.1 oster Caller must hold regionInfo[regionID].mutex
650 1.1 oster
651 1.1 oster NON-BLOCKING
652 1.1 oster */
653 1.1 oster
654 1.1 oster if (rf_parityLogDebug)
655 1.1 oster printf("[dumping parity log to disk, region %d]\n", regionID);
656 1.1 oster log = raidPtr->regionInfo[regionID].coreLog;
657 1.1 oster RF_ASSERT(log->numRecords == raidPtr->numSectorsPerLog);
658 1.1 oster RF_ASSERT(log->next == NULL);
659 1.1 oster
660 1.1 oster /* if reintegration is in progress, must queue work */
661 1.1 oster RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].reintMutex);
662 1.1 oster if (raidPtr->regionInfo[regionID].reintInProgress)
663 1.1 oster {
664 1.1 oster /* Can not proceed since this region is currently being reintegrated.
665 1.1 oster We can not block, so queue remaining work and return */
666 1.1 oster if (rf_parityLogDebug)
667 1.1 oster printf("[region %d waiting on reintegration]\n",regionID);
668 1.1 oster /* XXX not sure about the use of finish - shouldn't this always be "Enqueue"? */
669 1.1 oster if (finish)
670 1.1 oster RequeueParityLogData(logData, &raidPtr->parityLogDiskQueue.reintBlockHead, &raidPtr->parityLogDiskQueue.reintBlockTail);
671 1.1 oster else
672 1.1 oster EnqueueParityLogData(logData, &raidPtr->parityLogDiskQueue.reintBlockHead, &raidPtr->parityLogDiskQueue.reintBlockTail);
673 1.1 oster RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].reintMutex);
674 1.1 oster return(1); /* relenquish control of this thread */
675 1.1 oster }
676 1.1 oster RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].reintMutex);
677 1.1 oster raidPtr->regionInfo[regionID].coreLog = NULL;
678 1.1 oster if ((raidPtr->regionInfo[regionID].diskCount) < raidPtr->regionInfo[regionID].capacity)
679 1.1 oster /* IMPORTANT!! this loop bound assumes region disk holds an integral number of core logs */
680 1.1 oster {
681 1.1 oster /* update disk map for this region */
682 1.1 oster diskCount = raidPtr->regionInfo[regionID].diskCount;
683 1.1 oster for (i = 0; i < raidPtr->numSectorsPerLog; i++)
684 1.1 oster {
685 1.1 oster raidPtr->regionInfo[regionID].diskMap[i + diskCount].operation = log->records[i].operation;
686 1.1 oster raidPtr->regionInfo[regionID].diskMap[i + diskCount].parityAddr = log->records[i].parityAddr;
687 1.1 oster }
688 1.1 oster log->diskOffset = diskCount;
689 1.1 oster raidPtr->regionInfo[regionID].diskCount += raidPtr->numSectorsPerLog;
690 1.1 oster FlushLog(raidPtr, log);
691 1.1 oster }
692 1.1 oster else
693 1.1 oster {
694 1.1 oster /* no room for log on disk, send it to disk manager and request reintegration */
695 1.1 oster RF_ASSERT(raidPtr->regionInfo[regionID].diskCount == raidPtr->regionInfo[regionID].capacity);
696 1.1 oster ReintLog(raidPtr, regionID, log);
697 1.1 oster }
698 1.1 oster if (rf_parityLogDebug)
699 1.1 oster printf("[finished dumping parity log to disk, region %d]\n", regionID);
700 1.1 oster return(0);
701 1.1 oster }
702 1.1 oster
703 1.1 oster int rf_ParityLogAppend(
704 1.1 oster RF_ParityLogData_t *logData,
705 1.1 oster int finish,
706 1.1 oster RF_ParityLog_t **incomingLog,
707 1.1 oster int clearReintFlag)
708 1.1 oster {
709 1.1 oster int regionID, logItem, itemDone;
710 1.1 oster RF_ParityLogData_t *item;
711 1.1 oster int punt, done = RF_FALSE;
712 1.1 oster RF_ParityLog_t *log;
713 1.1 oster RF_Raid_t *raidPtr;
714 1.1 oster RF_Etimer_t timer;
715 1.1 oster int (*wakeFunc)(RF_DagNode_t *node, int status);
716 1.1 oster void *wakeArg;
717 1.1 oster
718 1.1 oster /* Add parity to the appropriate log, one sector at a time.
719 1.1 oster This routine is called is called by dag functions ParityLogUpdateFunc
720 1.1 oster and ParityLogOverwriteFunc and therefore MUST BE NONBLOCKING.
721 1.1 oster
722 1.1 oster Parity to be logged is contained in a linked-list (logData). When
723 1.1 oster this routine returns, every sector in the list will be in one of
724 1.1 oster three places:
725 1.1 oster 1) entered into the parity log
726 1.1 oster 2) queued, waiting on reintegration
727 1.1 oster 3) queued, waiting on a core log
728 1.1 oster
729 1.1 oster Blocked work is passed to the ParityLoggingDiskManager for completion.
730 1.1 oster Later, as conditions which required the block are removed, the work
731 1.1 oster reenters this routine with the "finish" parameter set to "RF_TRUE."
732 1.1 oster
733 1.1 oster NON-BLOCKING
734 1.1 oster */
735 1.1 oster
736 1.1 oster raidPtr = logData->common->raidPtr;
737 1.1 oster /* lock the region for the first item in logData */
738 1.1 oster RF_ASSERT(logData != NULL);
739 1.1 oster regionID = logData->regionID;
740 1.1 oster RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
741 1.1 oster RF_ASSERT(raidPtr->regionInfo[regionID].loggingEnabled);
742 1.1 oster
743 1.1 oster if (clearReintFlag)
744 1.1 oster {
745 1.1 oster /* Enable flushing for this region. Holding both locks provides
746 1.1 oster a synchronization barrier with DumpParityLogToDisk
747 1.1 oster */
748 1.1 oster RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].reintMutex);
749 1.1 oster RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
750 1.1 oster RF_ASSERT(raidPtr->regionInfo[regionID].reintInProgress == RF_TRUE);
751 1.1 oster raidPtr->regionInfo[regionID].diskCount = 0;
752 1.1 oster raidPtr->regionInfo[regionID].reintInProgress = RF_FALSE;
753 1.1 oster RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].reintMutex); /* flushing is now enabled */
754 1.1 oster RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
755 1.1 oster }
756 1.1 oster
757 1.1 oster /* process each item in logData */
758 1.1 oster while (logData)
759 1.1 oster {
760 1.1 oster /* remove an item from logData */
761 1.1 oster item = logData;
762 1.1 oster logData = logData->next;
763 1.1 oster item->next = NULL;
764 1.1 oster item->prev = NULL;
765 1.1 oster
766 1.1 oster if (rf_parityLogDebug)
767 1.1 oster printf("[appending parity log data, region %d, raidAddress %d, numSector %d]\n",item->regionID,(int)item->diskAddress.raidAddress, (int)item->diskAddress.numSector);
768 1.1 oster
769 1.1 oster /* see if we moved to a new region */
770 1.1 oster if (regionID != item->regionID)
771 1.1 oster {
772 1.1 oster RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
773 1.1 oster regionID = item->regionID;
774 1.1 oster RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
775 1.1 oster RF_ASSERT(raidPtr->regionInfo[regionID].loggingEnabled);
776 1.1 oster }
777 1.1 oster
778 1.1 oster punt = RF_FALSE; /* Set to RF_TRUE if work is blocked. This can happen in one of two ways:
779 1.1 oster 1) no core log (AcquireParityLog)
780 1.1 oster 2) waiting on reintegration (DumpParityLogToDisk)
781 1.1 oster If punt is RF_TRUE, the dataItem was queued, so skip to next item.
782 1.1 oster */
783 1.1 oster
784 1.1 oster /* process item, one sector at a time, until all sectors processed or we punt */
785 1.1 oster if (item->diskAddress.numSector > 0)
786 1.1 oster done = RF_FALSE;
787 1.1 oster else
788 1.1 oster RF_ASSERT(0);
789 1.1 oster while (!punt && !done)
790 1.1 oster {
791 1.1 oster /* verify that a core log exists for this region */
792 1.1 oster if (!raidPtr->regionInfo[regionID].coreLog)
793 1.1 oster {
794 1.1 oster /* Attempt to acquire a parity log.
795 1.1 oster If acquisition fails, queue remaining work in data item and move to nextItem.
796 1.1 oster */
797 1.1 oster if (incomingLog)
798 1.1 oster if (*incomingLog)
799 1.1 oster {
800 1.1 oster RF_ASSERT((*incomingLog)->next == NULL);
801 1.1 oster raidPtr->regionInfo[regionID].coreLog = *incomingLog;
802 1.1 oster raidPtr->regionInfo[regionID].coreLog->regionID = regionID;
803 1.1 oster *incomingLog = NULL;
804 1.1 oster }
805 1.1 oster else
806 1.1 oster raidPtr->regionInfo[regionID].coreLog = AcquireParityLog(item, finish);
807 1.1 oster else
808 1.1 oster raidPtr->regionInfo[regionID].coreLog = AcquireParityLog(item, finish);
809 1.1 oster /* Note: AcquireParityLog either returns a log or enqueues currentItem */
810 1.1 oster }
811 1.1 oster if (!raidPtr->regionInfo[regionID].coreLog)
812 1.1 oster punt = RF_TRUE; /* failed to find a core log */
813 1.1 oster else
814 1.1 oster {
815 1.1 oster RF_ASSERT(raidPtr->regionInfo[regionID].coreLog->next == NULL);
816 1.1 oster /* verify that the log has room for new entries */
817 1.1 oster /* if log is full, dump it to disk and grab a new log */
818 1.1 oster if (raidPtr->regionInfo[regionID].coreLog->numRecords == raidPtr->numSectorsPerLog)
819 1.1 oster {
820 1.1 oster /* log is full, dump it to disk */
821 1.1 oster if (DumpParityLogToDisk(finish, item))
822 1.1 oster punt = RF_TRUE; /* dump unsuccessful, blocked on reintegration */
823 1.1 oster else
824 1.1 oster {
825 1.1 oster /* dump was successful */
826 1.1 oster if (incomingLog)
827 1.1 oster if (*incomingLog)
828 1.1 oster {
829 1.1 oster RF_ASSERT((*incomingLog)->next == NULL);
830 1.1 oster raidPtr->regionInfo[regionID].coreLog = *incomingLog;
831 1.1 oster raidPtr->regionInfo[regionID].coreLog->regionID = regionID;
832 1.1 oster *incomingLog = NULL;
833 1.1 oster }
834 1.1 oster else
835 1.1 oster raidPtr->regionInfo[regionID].coreLog = AcquireParityLog(item, finish);
836 1.1 oster else
837 1.1 oster raidPtr->regionInfo[regionID].coreLog = AcquireParityLog(item, finish);
838 1.1 oster /* if a core log is not available, must queue work and return */
839 1.1 oster if (!raidPtr->regionInfo[regionID].coreLog)
840 1.1 oster punt = RF_TRUE; /* blocked on log availability */
841 1.1 oster }
842 1.1 oster }
843 1.1 oster }
844 1.1 oster /* if we didn't punt on this item, attempt to add a sector to the core log */
845 1.1 oster if (!punt)
846 1.1 oster {
847 1.1 oster RF_ASSERT(raidPtr->regionInfo[regionID].coreLog->next == NULL);
848 1.1 oster /* at this point, we have a core log with enough room for a sector */
849 1.1 oster /* copy a sector into the log */
850 1.1 oster log = raidPtr->regionInfo[regionID].coreLog;
851 1.1 oster RF_ASSERT(log->numRecords < raidPtr->numSectorsPerLog);
852 1.1 oster logItem = log->numRecords++;
853 1.1 oster log->records[logItem].parityAddr = item->diskAddress;
854 1.1 oster RF_ASSERT(log->records[logItem].parityAddr.startSector >= raidPtr->regionInfo[regionID].parityStartAddr);
855 1.1 oster RF_ASSERT(log->records[logItem].parityAddr.startSector < raidPtr->regionInfo[regionID].parityStartAddr + raidPtr->regionInfo[regionID].numSectorsParity);
856 1.1 oster log->records[logItem].parityAddr.numSector = 1;
857 1.1 oster log->records[logItem].operation = item->common->operation;
858 1.1 oster bcopy((item->common->bufPtr + (item->bufOffset++ * (1<<item->common->raidPtr->logBytesPerSector))), log->bufPtr + (logItem * (1<<item->common->raidPtr->logBytesPerSector)), (1<<item->common->raidPtr->logBytesPerSector));
859 1.1 oster item->diskAddress.numSector--;
860 1.1 oster item->diskAddress.startSector++;
861 1.1 oster if (item->diskAddress.numSector == 0)
862 1.1 oster done = RF_TRUE;
863 1.1 oster }
864 1.1 oster }
865 1.1 oster
866 1.1 oster if (!punt)
867 1.1 oster {
868 1.1 oster /* Processed this item completely, decrement count of items
869 1.1 oster to be processed.
870 1.1 oster */
871 1.1 oster RF_ASSERT(item->diskAddress.numSector == 0);
872 1.1 oster RF_LOCK_MUTEX(item->common->mutex);
873 1.1 oster item->common->cnt--;
874 1.1 oster if (item->common->cnt == 0)
875 1.1 oster itemDone = RF_TRUE;
876 1.1 oster else
877 1.1 oster itemDone = RF_FALSE;
878 1.1 oster RF_UNLOCK_MUTEX(item->common->mutex);
879 1.1 oster if (itemDone)
880 1.1 oster {
881 1.1 oster /* Finished processing all log data for this IO
882 1.1 oster Return structs to free list and invoke wakeup function.
883 1.1 oster */
884 1.1 oster timer = item->common->startTime; /* grab initial value of timer */
885 1.1 oster RF_ETIMER_STOP(timer);
886 1.1 oster RF_ETIMER_EVAL(timer);
887 1.1 oster item->common->tracerec->plog_us += RF_ETIMER_VAL_US(timer);
888 1.1 oster if (rf_parityLogDebug)
889 1.1 oster printf("[waking process for region %d]\n", item->regionID);
890 1.1 oster wakeFunc = item->common->wakeFunc;
891 1.1 oster wakeArg = item->common->wakeArg;
892 1.1 oster FreeParityLogCommonData(item->common);
893 1.1 oster FreeParityLogData(item);
894 1.1 oster (wakeFunc)(wakeArg, 0);
895 1.1 oster }
896 1.1 oster else
897 1.1 oster FreeParityLogData(item);
898 1.1 oster }
899 1.1 oster }
900 1.1 oster RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
901 1.1 oster if (rf_parityLogDebug)
902 1.1 oster printf("[exiting ParityLogAppend]\n");
903 1.1 oster return(0);
904 1.1 oster }
905 1.1 oster
906 1.1 oster
907 1.1 oster void rf_EnableParityLogging(RF_Raid_t *raidPtr)
908 1.1 oster {
909 1.1 oster int regionID;
910 1.1 oster
911 1.1 oster for (regionID = 0; regionID < rf_numParityRegions; regionID++) {
912 1.1 oster RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
913 1.1 oster raidPtr->regionInfo[regionID].loggingEnabled = RF_TRUE;
914 1.1 oster RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
915 1.1 oster }
916 1.1 oster if (rf_parityLogDebug)
917 1.1 oster printf("[parity logging enabled]\n");
918 1.1 oster }
919 1.1 oster
920 1.1 oster #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
921