1*b67baf4cSchristos /* $NetBSD: rf_paritylog.c,v 1.20 2019/10/10 03:43:59 christos Exp $ */
238a3987bSoster /*
338a3987bSoster * Copyright (c) 1995 Carnegie-Mellon University.
438a3987bSoster * All rights reserved.
538a3987bSoster *
638a3987bSoster * Author: William V. Courtright II
738a3987bSoster *
838a3987bSoster * Permission to use, copy, modify and distribute this software and
938a3987bSoster * its documentation is hereby granted, provided that both the copyright
1038a3987bSoster * notice and this permission notice appear in all copies of the
1138a3987bSoster * software, derivative works or modified versions, and any portions
1238a3987bSoster * thereof, and that both notices appear in supporting documentation.
1338a3987bSoster *
1438a3987bSoster * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
1538a3987bSoster * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
1638a3987bSoster * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1738a3987bSoster *
1838a3987bSoster * Carnegie Mellon requests users of this software to return to
1938a3987bSoster *
2038a3987bSoster * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
2138a3987bSoster * School of Computer Science
2238a3987bSoster * Carnegie Mellon University
2338a3987bSoster * Pittsburgh PA 15213-3890
2438a3987bSoster *
2538a3987bSoster * any improvements or extensions that they make and grant Carnegie the
2638a3987bSoster * rights to redistribute these changes.
2738a3987bSoster */
2838a3987bSoster
2938a3987bSoster /* Code for manipulating in-core parity logs
3038a3987bSoster *
3138a3987bSoster */
3238a3987bSoster
33a3746e00Slukem #include <sys/cdefs.h>
34*b67baf4cSchristos __KERNEL_RCSID(0, "$NetBSD: rf_paritylog.c,v 1.20 2019/10/10 03:43:59 christos Exp $");
35a3746e00Slukem
3638a3987bSoster #include "rf_archs.h"
3738a3987bSoster
3838a3987bSoster #if RF_INCLUDE_PARITYLOGGING > 0
3938a3987bSoster
4038a3987bSoster /*
4138a3987bSoster * Append-only log for recording parity "update" and "overwrite" records
4238a3987bSoster */
4338a3987bSoster
44765e00d3Soster #include <dev/raidframe/raidframevar.h>
45765e00d3Soster
4638a3987bSoster #include "rf_threadstuff.h"
4738a3987bSoster #include "rf_mcpair.h"
4838a3987bSoster #include "rf_raid.h"
4938a3987bSoster #include "rf_dag.h"
5038a3987bSoster #include "rf_dagfuncs.h"
5138a3987bSoster #include "rf_desc.h"
5238a3987bSoster #include "rf_layout.h"
5338a3987bSoster #include "rf_diskqueue.h"
5438a3987bSoster #include "rf_etimer.h"
5538a3987bSoster #include "rf_paritylog.h"
5638a3987bSoster #include "rf_general.h"
5738a3987bSoster #include "rf_map.h"
5838a3987bSoster #include "rf_paritylogging.h"
5938a3987bSoster #include "rf_paritylogDiskMgr.h"
6038a3987bSoster
6100145885Soster static RF_CommonLogData_t *
AllocParityLogCommonData(RF_Raid_t * raidPtr)6200145885Soster AllocParityLogCommonData(RF_Raid_t * raidPtr)
6338a3987bSoster {
6438a3987bSoster RF_CommonLogData_t *common = NULL;
6538a3987bSoster
6600145885Soster /* Return a struct for holding common parity log information from the
6700145885Soster * free list (rf_parityLogDiskQueue.freeCommonList). If the free list
6800145885Soster * is empty, call RF_Malloc to create a new structure. NON-BLOCKING */
6938a3987bSoster
7032ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
7100145885Soster if (raidPtr->parityLogDiskQueue.freeCommonList) {
7238a3987bSoster common = raidPtr->parityLogDiskQueue.freeCommonList;
7338a3987bSoster raidPtr->parityLogDiskQueue.freeCommonList = raidPtr->parityLogDiskQueue.freeCommonList->next;
7432ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
7500145885Soster } else {
7632ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
7795d8fbc8Schristos common = RF_Malloc(sizeof(*common));
781c0dbcb6Smrg /* destroy is in rf_paritylogging.c */
791c0dbcb6Smrg rf_init_mutex2(common->mutex, IPL_VM);
8038a3987bSoster }
8138a3987bSoster common->next = NULL;
8238a3987bSoster return (common);
8338a3987bSoster }
8438a3987bSoster
8500145885Soster static void
FreeParityLogCommonData(RF_CommonLogData_t * common)8600145885Soster FreeParityLogCommonData(RF_CommonLogData_t * common)
8738a3987bSoster {
8838a3987bSoster RF_Raid_t *raidPtr;
8938a3987bSoster
9000145885Soster /* Insert a single struct for holding parity log information (data)
9100145885Soster * into the free list (rf_parityLogDiskQueue.freeCommonList).
9200145885Soster * NON-BLOCKING */
9338a3987bSoster
9438a3987bSoster raidPtr = common->raidPtr;
9532ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
9638a3987bSoster common->next = raidPtr->parityLogDiskQueue.freeCommonList;
9738a3987bSoster raidPtr->parityLogDiskQueue.freeCommonList = common;
9832ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
9938a3987bSoster }
10038a3987bSoster
10100145885Soster static RF_ParityLogData_t *
AllocParityLogData(RF_Raid_t * raidPtr)10200145885Soster AllocParityLogData(RF_Raid_t * raidPtr)
10338a3987bSoster {
10438a3987bSoster RF_ParityLogData_t *data = NULL;
10538a3987bSoster
10638a3987bSoster /* Return a struct for holding parity log information from the free
10700145885Soster * list (rf_parityLogDiskQueue.freeList). If the free list is empty,
10800145885Soster * call RF_Malloc to create a new structure. NON-BLOCKING */
10938a3987bSoster
11032ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
11100145885Soster if (raidPtr->parityLogDiskQueue.freeDataList) {
11238a3987bSoster data = raidPtr->parityLogDiskQueue.freeDataList;
11338a3987bSoster raidPtr->parityLogDiskQueue.freeDataList = raidPtr->parityLogDiskQueue.freeDataList->next;
11432ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
11500145885Soster } else {
11632ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
11795d8fbc8Schristos data = RF_Malloc(sizeof(*data));
11838a3987bSoster }
11938a3987bSoster data->next = NULL;
12038a3987bSoster data->prev = NULL;
12138a3987bSoster return (data);
12238a3987bSoster }
12338a3987bSoster
12438a3987bSoster
12500145885Soster static void
FreeParityLogData(RF_ParityLogData_t * data)12600145885Soster FreeParityLogData(RF_ParityLogData_t * data)
12738a3987bSoster {
12838a3987bSoster RF_ParityLogData_t *nextItem;
12938a3987bSoster RF_Raid_t *raidPtr;
13038a3987bSoster
13100145885Soster /* Insert a linked list of structs for holding parity log information
13200145885Soster * (data) into the free list (parityLogDiskQueue.freeList).
13300145885Soster * NON-BLOCKING */
13438a3987bSoster
13538a3987bSoster raidPtr = data->common->raidPtr;
13632ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
13700145885Soster while (data) {
13838a3987bSoster nextItem = data->next;
13938a3987bSoster data->next = raidPtr->parityLogDiskQueue.freeDataList;
14038a3987bSoster raidPtr->parityLogDiskQueue.freeDataList = data;
14138a3987bSoster data = nextItem;
14238a3987bSoster }
14332ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
14438a3987bSoster }
14538a3987bSoster
14638a3987bSoster
14700145885Soster static void
EnqueueParityLogData(RF_ParityLogData_t * data,RF_ParityLogData_t ** head,RF_ParityLogData_t ** tail)14800145885Soster EnqueueParityLogData(
14938a3987bSoster RF_ParityLogData_t * data,
15038a3987bSoster RF_ParityLogData_t ** head,
15138a3987bSoster RF_ParityLogData_t ** tail)
15238a3987bSoster {
15338a3987bSoster RF_Raid_t *raidPtr;
15438a3987bSoster
15500145885Soster /* Insert an in-core parity log (*data) into the head of a disk queue
15600145885Soster * (*head, *tail). NON-BLOCKING */
15738a3987bSoster
15838a3987bSoster raidPtr = data->common->raidPtr;
15938a3987bSoster if (rf_parityLogDebug)
16038a3987bSoster printf("[enqueueing parity log data, region %d, raidAddress %d, numSector %d]\n", data->regionID, (int) data->diskAddress.raidAddress, (int) data->diskAddress.numSector);
16138a3987bSoster RF_ASSERT(data->prev == NULL);
16238a3987bSoster RF_ASSERT(data->next == NULL);
16332ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
16400145885Soster if (*head) {
16538a3987bSoster /* insert into head of queue */
16638a3987bSoster RF_ASSERT((*head)->prev == NULL);
16738a3987bSoster RF_ASSERT((*tail)->next == NULL);
16838a3987bSoster data->next = *head;
16938a3987bSoster (*head)->prev = data;
17038a3987bSoster *head = data;
17100145885Soster } else {
17238a3987bSoster /* insert into empty list */
17338a3987bSoster RF_ASSERT(*head == NULL);
17438a3987bSoster RF_ASSERT(*tail == NULL);
17538a3987bSoster *head = data;
17638a3987bSoster *tail = data;
17738a3987bSoster }
17838a3987bSoster RF_ASSERT((*head)->prev == NULL);
17938a3987bSoster RF_ASSERT((*tail)->next == NULL);
18032ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
18138a3987bSoster }
18238a3987bSoster
18300145885Soster static RF_ParityLogData_t *
DequeueParityLogData(RF_Raid_t * raidPtr,RF_ParityLogData_t ** head,RF_ParityLogData_t ** tail,int ignoreLocks)18400145885Soster DequeueParityLogData(
18538a3987bSoster RF_Raid_t * raidPtr,
18638a3987bSoster RF_ParityLogData_t ** head,
18738a3987bSoster RF_ParityLogData_t ** tail,
18838a3987bSoster int ignoreLocks)
18938a3987bSoster {
19038a3987bSoster RF_ParityLogData_t *data;
19138a3987bSoster
19200145885Soster /* Remove and return an in-core parity log from the tail of a disk
19300145885Soster * queue (*head, *tail). NON-BLOCKING */
19438a3987bSoster
19538a3987bSoster /* remove from tail, preserving FIFO order */
19638a3987bSoster if (!ignoreLocks)
19732ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
19838a3987bSoster data = *tail;
19900145885Soster if (data) {
20000145885Soster if (*head == *tail) {
20138a3987bSoster /* removing last item from queue */
20238a3987bSoster *head = NULL;
20338a3987bSoster *tail = NULL;
20400145885Soster } else {
20538a3987bSoster *tail = (*tail)->prev;
20638a3987bSoster (*tail)->next = NULL;
20738a3987bSoster RF_ASSERT((*head)->prev == NULL);
20838a3987bSoster RF_ASSERT((*tail)->next == NULL);
20938a3987bSoster }
21038a3987bSoster data->next = NULL;
21138a3987bSoster data->prev = NULL;
21238a3987bSoster if (rf_parityLogDebug)
21338a3987bSoster printf("[dequeueing parity log data, region %d, raidAddress %d, numSector %d]\n", data->regionID, (int) data->diskAddress.raidAddress, (int) data->diskAddress.numSector);
21438a3987bSoster }
21500145885Soster if (*head) {
21638a3987bSoster RF_ASSERT((*head)->prev == NULL);
21738a3987bSoster RF_ASSERT((*tail)->next == NULL);
21838a3987bSoster }
21938a3987bSoster if (!ignoreLocks)
22032ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
22138a3987bSoster return (data);
22238a3987bSoster }
22338a3987bSoster
22438a3987bSoster
22500145885Soster static void
RequeueParityLogData(RF_ParityLogData_t * data,RF_ParityLogData_t ** head,RF_ParityLogData_t ** tail)22600145885Soster RequeueParityLogData(
22738a3987bSoster RF_ParityLogData_t * data,
22838a3987bSoster RF_ParityLogData_t ** head,
22938a3987bSoster RF_ParityLogData_t ** tail)
23038a3987bSoster {
23138a3987bSoster RF_Raid_t *raidPtr;
23238a3987bSoster
23300145885Soster /* Insert an in-core parity log (*data) into the tail of a disk queue
23400145885Soster * (*head, *tail). NON-BLOCKING */
23538a3987bSoster
23638a3987bSoster raidPtr = data->common->raidPtr;
23738a3987bSoster RF_ASSERT(data);
23838a3987bSoster if (rf_parityLogDebug)
23938a3987bSoster printf("[requeueing parity log data, region %d, raidAddress %d, numSector %d]\n", data->regionID, (int) data->diskAddress.raidAddress, (int) data->diskAddress.numSector);
24032ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
24100145885Soster if (*tail) {
24238a3987bSoster /* append to tail of list */
24338a3987bSoster data->prev = *tail;
24438a3987bSoster data->next = NULL;
24538a3987bSoster (*tail)->next = data;
24638a3987bSoster *tail = data;
24700145885Soster } else {
24838a3987bSoster /* inserting into an empty list */
24938a3987bSoster *head = data;
25038a3987bSoster *tail = data;
25138a3987bSoster (*head)->prev = NULL;
25238a3987bSoster (*tail)->next = NULL;
25338a3987bSoster }
25438a3987bSoster RF_ASSERT((*head)->prev == NULL);
25538a3987bSoster RF_ASSERT((*tail)->next == NULL);
25632ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
25738a3987bSoster }
25838a3987bSoster
25900145885Soster RF_ParityLogData_t *
rf_CreateParityLogData(RF_ParityRecordType_t operation,RF_PhysDiskAddr_t * pda,void * bufPtr,RF_Raid_t * raidPtr,void (* wakeFunc)(void *,int),void * wakeArg,RF_AccTraceEntry_t * tracerec,RF_Etimer_t startTime)26000145885Soster rf_CreateParityLogData(
26138a3987bSoster RF_ParityRecordType_t operation,
26238a3987bSoster RF_PhysDiskAddr_t * pda,
26353524e44Schristos void *bufPtr,
26438a3987bSoster RF_Raid_t * raidPtr,
265*b67baf4cSchristos void (*wakeFunc)(void *, int),
26638a3987bSoster void *wakeArg,
26738a3987bSoster RF_AccTraceEntry_t * tracerec,
26838a3987bSoster RF_Etimer_t startTime)
26938a3987bSoster {
27038a3987bSoster RF_ParityLogData_t *data, *resultHead = NULL, *resultTail = NULL;
27138a3987bSoster RF_CommonLogData_t *common;
27238a3987bSoster RF_PhysDiskAddr_t *diskAddress;
27338a3987bSoster int boundary, offset = 0;
27438a3987bSoster
27500145885Soster /* Return an initialized struct of info to be logged. Build one item
27600145885Soster * per physical disk address, one item per region.
27700145885Soster *
27800145885Soster * NON-BLOCKING */
27938a3987bSoster
28038a3987bSoster diskAddress = pda;
28138a3987bSoster common = AllocParityLogCommonData(raidPtr);
28238a3987bSoster RF_ASSERT(common);
28338a3987bSoster
28438a3987bSoster common->operation = operation;
28538a3987bSoster common->bufPtr = bufPtr;
28638a3987bSoster common->raidPtr = raidPtr;
28738a3987bSoster common->wakeFunc = wakeFunc;
28838a3987bSoster common->wakeArg = wakeArg;
28938a3987bSoster common->tracerec = tracerec;
29038a3987bSoster common->startTime = startTime;
29138a3987bSoster common->cnt = 0;
29238a3987bSoster
29338a3987bSoster if (rf_parityLogDebug)
29438a3987bSoster printf("[entering CreateParityLogData]\n");
29500145885Soster while (diskAddress) {
29638a3987bSoster common->cnt++;
29738a3987bSoster data = AllocParityLogData(raidPtr);
29838a3987bSoster RF_ASSERT(data);
29938a3987bSoster data->common = common;
30038a3987bSoster data->next = NULL;
30138a3987bSoster data->prev = NULL;
30238a3987bSoster data->regionID = rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector);
30300145885Soster if (data->regionID == rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector + diskAddress->numSector - 1)) {
30438a3987bSoster /* disk address does not cross a region boundary */
30538a3987bSoster data->diskAddress = *diskAddress;
30638a3987bSoster data->bufOffset = offset;
30738a3987bSoster offset = offset + diskAddress->numSector;
30838a3987bSoster EnqueueParityLogData(data, &resultHead, &resultTail);
30938a3987bSoster /* adjust disk address */
31038a3987bSoster diskAddress = diskAddress->next;
31100145885Soster } else {
31238a3987bSoster /* disk address crosses a region boundary */
31338a3987bSoster /* find address where region is crossed */
31438a3987bSoster boundary = 0;
31538a3987bSoster while (data->regionID == rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector + boundary))
31638a3987bSoster boundary++;
31738a3987bSoster
31838a3987bSoster /* enter data before the boundary */
31938a3987bSoster data->diskAddress = *diskAddress;
32038a3987bSoster data->diskAddress.numSector = boundary;
32138a3987bSoster data->bufOffset = offset;
32238a3987bSoster offset += boundary;
32338a3987bSoster EnqueueParityLogData(data, &resultHead, &resultTail);
32438a3987bSoster /* adjust disk address */
32538a3987bSoster diskAddress->startSector += boundary;
32638a3987bSoster diskAddress->numSector -= boundary;
32738a3987bSoster }
32838a3987bSoster }
32938a3987bSoster if (rf_parityLogDebug)
33038a3987bSoster printf("[leaving CreateParityLogData]\n");
33138a3987bSoster return (resultHead);
33238a3987bSoster }
33338a3987bSoster
33438a3987bSoster
33500145885Soster RF_ParityLogData_t *
rf_SearchAndDequeueParityLogData(RF_Raid_t * raidPtr,int regionID,RF_ParityLogData_t ** head,RF_ParityLogData_t ** tail,int ignoreLocks)33600145885Soster rf_SearchAndDequeueParityLogData(
33738a3987bSoster RF_Raid_t * raidPtr,
33838a3987bSoster int regionID,
33938a3987bSoster RF_ParityLogData_t ** head,
34038a3987bSoster RF_ParityLogData_t ** tail,
34138a3987bSoster int ignoreLocks)
34238a3987bSoster {
34338a3987bSoster RF_ParityLogData_t *w;
34438a3987bSoster
34500145885Soster /* Remove and return an in-core parity log from a specified region
34600145885Soster * (regionID). If a matching log is not found, return NULL.
34700145885Soster *
34800145885Soster * NON-BLOCKING. */
34938a3987bSoster
35000145885Soster /* walk backward through a list, looking for an entry with a matching
35100145885Soster * region ID */
35238a3987bSoster if (!ignoreLocks)
35332ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
35438a3987bSoster w = (*tail);
35500145885Soster while (w) {
35600145885Soster if (w->regionID == regionID) {
35738a3987bSoster /* remove an element from the list */
35800145885Soster if (w == *tail) {
35900145885Soster if (*head == *tail) {
36038a3987bSoster /* removing only element in the list */
36138a3987bSoster *head = NULL;
36238a3987bSoster *tail = NULL;
36300145885Soster } else {
36438a3987bSoster /* removing last item in the list */
36538a3987bSoster *tail = (*tail)->prev;
36638a3987bSoster (*tail)->next = NULL;
36738a3987bSoster RF_ASSERT((*head)->prev == NULL);
36838a3987bSoster RF_ASSERT((*tail)->next == NULL);
36938a3987bSoster }
37000145885Soster } else {
37100145885Soster if (w == *head) {
37238a3987bSoster /* removing first item in the list */
37338a3987bSoster *head = (*head)->next;
37438a3987bSoster (*head)->prev = NULL;
37538a3987bSoster RF_ASSERT((*head)->prev == NULL);
37638a3987bSoster RF_ASSERT((*tail)->next == NULL);
37700145885Soster } else {
37800145885Soster /* removing an item from the middle of
37900145885Soster * the list */
38038a3987bSoster w->prev->next = w->next;
38138a3987bSoster w->next->prev = w->prev;
38238a3987bSoster RF_ASSERT((*head)->prev == NULL);
38338a3987bSoster RF_ASSERT((*tail)->next == NULL);
38438a3987bSoster }
38538a3987bSoster }
38638a3987bSoster w->prev = NULL;
38738a3987bSoster w->next = NULL;
38838a3987bSoster if (rf_parityLogDebug)
38938a3987bSoster printf("[dequeueing parity log data, region %d, raidAddress %d, numSector %d]\n", w->regionID, (int) w->diskAddress.raidAddress, (int) w->diskAddress.numSector);
39038a3987bSoster return (w);
39100145885Soster } else
39238a3987bSoster w = w->prev;
39338a3987bSoster }
39438a3987bSoster if (!ignoreLocks)
39532ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
39638a3987bSoster return (NULL);
39738a3987bSoster }
39838a3987bSoster
39900145885Soster static RF_ParityLogData_t *
DequeueMatchingLogData(RF_Raid_t * raidPtr,RF_ParityLogData_t ** head,RF_ParityLogData_t ** tail)40000145885Soster DequeueMatchingLogData(
40138a3987bSoster RF_Raid_t * raidPtr,
40238a3987bSoster RF_ParityLogData_t ** head,
40338a3987bSoster RF_ParityLogData_t ** tail)
40438a3987bSoster {
40538a3987bSoster RF_ParityLogData_t *logDataList, *logData;
40638a3987bSoster int regionID;
40738a3987bSoster
40800145885Soster /* Remove and return an in-core parity log from the tail of a disk
40900145885Soster * queue (*head, *tail). Then remove all matching (identical
41000145885Soster * regionIDs) logData and return as a linked list.
41100145885Soster *
41200145885Soster * NON-BLOCKING */
41338a3987bSoster
41438a3987bSoster logDataList = DequeueParityLogData(raidPtr, head, tail, RF_TRUE);
41500145885Soster if (logDataList) {
41638a3987bSoster regionID = logDataList->regionID;
41738a3987bSoster logData = logDataList;
41838a3987bSoster logData->next = rf_SearchAndDequeueParityLogData(raidPtr, regionID, head, tail, RF_TRUE);
41900145885Soster while (logData->next) {
42038a3987bSoster logData = logData->next;
42138a3987bSoster logData->next = rf_SearchAndDequeueParityLogData(raidPtr, regionID, head, tail, RF_TRUE);
42238a3987bSoster }
42338a3987bSoster }
42438a3987bSoster return (logDataList);
42538a3987bSoster }
42638a3987bSoster
42738a3987bSoster
42800145885Soster static RF_ParityLog_t *
AcquireParityLog(RF_ParityLogData_t * logData,int finish)42900145885Soster AcquireParityLog(
43038a3987bSoster RF_ParityLogData_t * logData,
43138a3987bSoster int finish)
43238a3987bSoster {
43338a3987bSoster RF_ParityLog_t *log = NULL;
43438a3987bSoster RF_Raid_t *raidPtr;
43538a3987bSoster
43600145885Soster /* Grab a log buffer from the pool and return it. If no buffers are
43700145885Soster * available, return NULL. NON-BLOCKING */
43838a3987bSoster raidPtr = logData->common->raidPtr;
439c57ca1d4Smrg rf_lock_mutex2(raidPtr->parityLogPool.mutex);
44000145885Soster if (raidPtr->parityLogPool.parityLogs) {
44138a3987bSoster log = raidPtr->parityLogPool.parityLogs;
44238a3987bSoster raidPtr->parityLogPool.parityLogs = raidPtr->parityLogPool.parityLogs->next;
44338a3987bSoster log->regionID = logData->regionID;
44438a3987bSoster log->numRecords = 0;
44538a3987bSoster log->next = NULL;
44638a3987bSoster raidPtr->logsInUse++;
44738a3987bSoster RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);
44800145885Soster } else {
44900145885Soster /* no logs available, so place ourselves on the queue of work
45000145885Soster * waiting on log buffers this is done while
45100145885Soster * parityLogPool.mutex is held, to ensure synchronization with
45200145885Soster * ReleaseParityLogs. */
45338a3987bSoster if (rf_parityLogDebug)
45438a3987bSoster printf("[blocked on log, region %d, finish %d]\n", logData->regionID, finish);
45538a3987bSoster if (finish)
45638a3987bSoster RequeueParityLogData(logData, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);
45738a3987bSoster else
45838a3987bSoster EnqueueParityLogData(logData, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);
45938a3987bSoster }
460c57ca1d4Smrg rf_unlock_mutex2(raidPtr->parityLogPool.mutex);
46138a3987bSoster return (log);
46238a3987bSoster }
46338a3987bSoster
46400145885Soster void
rf_ReleaseParityLogs(RF_Raid_t * raidPtr,RF_ParityLog_t * firstLog)46500145885Soster rf_ReleaseParityLogs(
46638a3987bSoster RF_Raid_t * raidPtr,
46738a3987bSoster RF_ParityLog_t * firstLog)
46838a3987bSoster {
46938a3987bSoster RF_ParityLogData_t *logDataList;
47038a3987bSoster RF_ParityLog_t *log, *lastLog;
47138a3987bSoster int cnt;
47238a3987bSoster
47300145885Soster /* Insert a linked list of parity logs (firstLog) to the free list
47400145885Soster * (parityLogPool.parityLogPool)
47500145885Soster *
47600145885Soster * NON-BLOCKING. */
47738a3987bSoster
47838a3987bSoster RF_ASSERT(firstLog);
47938a3987bSoster
48000145885Soster /* Before returning logs to global free list, service all requests
48100145885Soster * which are blocked on logs. Holding mutexes for parityLogPool and
48200145885Soster * parityLogDiskQueue forces synchronization with AcquireParityLog(). */
483c57ca1d4Smrg rf_lock_mutex2(raidPtr->parityLogPool.mutex);
48432ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
48538a3987bSoster logDataList = DequeueMatchingLogData(raidPtr, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);
48638a3987bSoster log = firstLog;
48738a3987bSoster if (firstLog)
48838a3987bSoster firstLog = firstLog->next;
48938a3987bSoster log->numRecords = 0;
49038a3987bSoster log->next = NULL;
49100145885Soster while (logDataList && log) {
492c57ca1d4Smrg rf_unlock_mutex2(raidPtr->parityLogPool.mutex);
49332ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
49438a3987bSoster rf_ParityLogAppend(logDataList, RF_TRUE, &log, RF_FALSE);
49538a3987bSoster if (rf_parityLogDebug)
49638a3987bSoster printf("[finishing up buf-blocked log data, region %d]\n", logDataList->regionID);
49700145885Soster if (log == NULL) {
49838a3987bSoster log = firstLog;
49900145885Soster if (firstLog) {
50038a3987bSoster firstLog = firstLog->next;
50138a3987bSoster log->numRecords = 0;
50238a3987bSoster log->next = NULL;
50338a3987bSoster }
50438a3987bSoster }
505c57ca1d4Smrg rf_lock_mutex2(raidPtr->parityLogPool.mutex);
50632ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
50738a3987bSoster if (log)
50838a3987bSoster logDataList = DequeueMatchingLogData(raidPtr, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);
50938a3987bSoster }
51038a3987bSoster /* return remaining logs to pool */
51100145885Soster if (log) {
51238a3987bSoster log->next = firstLog;
51338a3987bSoster firstLog = log;
51438a3987bSoster }
51500145885Soster if (firstLog) {
51638a3987bSoster lastLog = firstLog;
51738a3987bSoster raidPtr->logsInUse--;
51838a3987bSoster RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);
51900145885Soster while (lastLog->next) {
52038a3987bSoster lastLog = lastLog->next;
52138a3987bSoster raidPtr->logsInUse--;
52238a3987bSoster RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);
52338a3987bSoster }
52438a3987bSoster lastLog->next = raidPtr->parityLogPool.parityLogs;
52538a3987bSoster raidPtr->parityLogPool.parityLogs = firstLog;
52638a3987bSoster cnt = 0;
52738a3987bSoster log = raidPtr->parityLogPool.parityLogs;
52800145885Soster while (log) {
52938a3987bSoster cnt++;
53038a3987bSoster log = log->next;
53138a3987bSoster }
53238a3987bSoster RF_ASSERT(cnt + raidPtr->logsInUse == raidPtr->numParityLogs);
53338a3987bSoster }
534c57ca1d4Smrg rf_unlock_mutex2(raidPtr->parityLogPool.mutex);
53532ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
53638a3987bSoster }
53738a3987bSoster
53800145885Soster static void
ReintLog(RF_Raid_t * raidPtr,int regionID,RF_ParityLog_t * log)53900145885Soster ReintLog(
54038a3987bSoster RF_Raid_t * raidPtr,
54138a3987bSoster int regionID,
54238a3987bSoster RF_ParityLog_t * log)
54338a3987bSoster {
54438a3987bSoster RF_ASSERT(log);
54538a3987bSoster
54600145885Soster /* Insert an in-core parity log (log) into the disk queue of
54700145885Soster * reintegration work. Set the flag (reintInProgress) for the
54800145885Soster * specified region (regionID) to indicate that reintegration is in
54900145885Soster * progress for this region. NON-BLOCKING */
55038a3987bSoster
5513dd61769Smrg rf_lock_mutex2(raidPtr->regionInfo[regionID].reintMutex);
55200145885Soster raidPtr->regionInfo[regionID].reintInProgress = RF_TRUE; /* cleared when reint
55300145885Soster * complete */
55438a3987bSoster
55538a3987bSoster if (rf_parityLogDebug)
55638a3987bSoster printf("[requesting reintegration of region %d]\n", log->regionID);
55738a3987bSoster /* move record to reintegration queue */
55832ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
55938a3987bSoster log->next = raidPtr->parityLogDiskQueue.reintQueue;
56038a3987bSoster raidPtr->parityLogDiskQueue.reintQueue = log;
5613dd61769Smrg rf_unlock_mutex2(raidPtr->regionInfo[regionID].reintMutex);
56232ab76b9Smrg rf_signal_cond2(raidPtr->parityLogDiskQueue.cond);
56332ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
56438a3987bSoster }
56538a3987bSoster
56600145885Soster static void
FlushLog(RF_Raid_t * raidPtr,RF_ParityLog_t * log)56700145885Soster FlushLog(
56838a3987bSoster RF_Raid_t * raidPtr,
56938a3987bSoster RF_ParityLog_t * log)
57038a3987bSoster {
57100145885Soster /* insert a core log (log) into a list of logs
57200145885Soster * (parityLogDiskQueue.flushQueue) waiting to be written to disk.
57300145885Soster * NON-BLOCKING */
57438a3987bSoster
57538a3987bSoster RF_ASSERT(log);
57638a3987bSoster RF_ASSERT(log->numRecords == raidPtr->numSectorsPerLog);
57738a3987bSoster RF_ASSERT(log->next == NULL);
57838a3987bSoster /* move log to flush queue */
57932ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
58038a3987bSoster log->next = raidPtr->parityLogDiskQueue.flushQueue;
58138a3987bSoster raidPtr->parityLogDiskQueue.flushQueue = log;
58232ab76b9Smrg rf_signal_cond2(raidPtr->parityLogDiskQueue.cond);
58332ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
58438a3987bSoster }
58538a3987bSoster
58600145885Soster static int
DumpParityLogToDisk(int finish,RF_ParityLogData_t * logData)58700145885Soster DumpParityLogToDisk(
58838a3987bSoster int finish,
58938a3987bSoster RF_ParityLogData_t * logData)
59038a3987bSoster {
59138a3987bSoster int i, diskCount, regionID = logData->regionID;
59238a3987bSoster RF_ParityLog_t *log;
59338a3987bSoster RF_Raid_t *raidPtr;
59438a3987bSoster
59538a3987bSoster raidPtr = logData->common->raidPtr;
59638a3987bSoster
59738a3987bSoster /* Move a core log to disk. If the log disk is full, initiate
59800145885Soster * reintegration.
59900145885Soster *
60000145885Soster * Return (0) if we can enqueue the dump immediately, otherwise return
60100145885Soster * (1) to indicate we are blocked on reintegration and control of the
60200145885Soster * thread should be relinquished.
60300145885Soster *
60400145885Soster * Caller must hold regionInfo[regionID].mutex
60500145885Soster *
60600145885Soster * NON-BLOCKING */
60738a3987bSoster
608662e58c7Smrg RF_ASSERT(rf_owned_mutex2(raidPtr->regionInfo[regionID].mutex));
609662e58c7Smrg
61038a3987bSoster if (rf_parityLogDebug)
61138a3987bSoster printf("[dumping parity log to disk, region %d]\n", regionID);
61238a3987bSoster log = raidPtr->regionInfo[regionID].coreLog;
61338a3987bSoster RF_ASSERT(log->numRecords == raidPtr->numSectorsPerLog);
61438a3987bSoster RF_ASSERT(log->next == NULL);
61538a3987bSoster
61638a3987bSoster /* if reintegration is in progress, must queue work */
6173dd61769Smrg rf_lock_mutex2(raidPtr->regionInfo[regionID].reintMutex);
61800145885Soster if (raidPtr->regionInfo[regionID].reintInProgress) {
61900145885Soster /* Can not proceed since this region is currently being
62000145885Soster * reintegrated. We can not block, so queue remaining work and
62100145885Soster * return */
62238a3987bSoster if (rf_parityLogDebug)
62338a3987bSoster printf("[region %d waiting on reintegration]\n", regionID);
62400145885Soster /* XXX not sure about the use of finish - shouldn't this
62500145885Soster * always be "Enqueue"? */
62638a3987bSoster if (finish)
62738a3987bSoster RequeueParityLogData(logData, &raidPtr->parityLogDiskQueue.reintBlockHead, &raidPtr->parityLogDiskQueue.reintBlockTail);
62838a3987bSoster else
62938a3987bSoster EnqueueParityLogData(logData, &raidPtr->parityLogDiskQueue.reintBlockHead, &raidPtr->parityLogDiskQueue.reintBlockTail);
6303dd61769Smrg rf_unlock_mutex2(raidPtr->regionInfo[regionID].reintMutex);
63138a3987bSoster return (1); /* relenquish control of this thread */
63238a3987bSoster }
6333dd61769Smrg rf_unlock_mutex2(raidPtr->regionInfo[regionID].reintMutex);
63438a3987bSoster raidPtr->regionInfo[regionID].coreLog = NULL;
63538a3987bSoster if ((raidPtr->regionInfo[regionID].diskCount) < raidPtr->regionInfo[regionID].capacity)
63600145885Soster /* IMPORTANT!! this loop bound assumes region disk holds an
63700145885Soster * integral number of core logs */
63838a3987bSoster {
63938a3987bSoster /* update disk map for this region */
64038a3987bSoster diskCount = raidPtr->regionInfo[regionID].diskCount;
64100145885Soster for (i = 0; i < raidPtr->numSectorsPerLog; i++) {
64238a3987bSoster raidPtr->regionInfo[regionID].diskMap[i + diskCount].operation = log->records[i].operation;
64338a3987bSoster raidPtr->regionInfo[regionID].diskMap[i + diskCount].parityAddr = log->records[i].parityAddr;
64438a3987bSoster }
64538a3987bSoster log->diskOffset = diskCount;
64638a3987bSoster raidPtr->regionInfo[regionID].diskCount += raidPtr->numSectorsPerLog;
64738a3987bSoster FlushLog(raidPtr, log);
64800145885Soster } else {
64900145885Soster /* no room for log on disk, send it to disk manager and
65000145885Soster * request reintegration */
65138a3987bSoster RF_ASSERT(raidPtr->regionInfo[regionID].diskCount == raidPtr->regionInfo[regionID].capacity);
65238a3987bSoster ReintLog(raidPtr, regionID, log);
65338a3987bSoster }
65438a3987bSoster if (rf_parityLogDebug)
65538a3987bSoster printf("[finished dumping parity log to disk, region %d]\n", regionID);
65638a3987bSoster return (0);
65738a3987bSoster }
65838a3987bSoster
65900145885Soster int
rf_ParityLogAppend(RF_ParityLogData_t * logData,int finish,RF_ParityLog_t ** incomingLog,int clearReintFlag)66000145885Soster rf_ParityLogAppend(
66138a3987bSoster RF_ParityLogData_t * logData,
66238a3987bSoster int finish,
66338a3987bSoster RF_ParityLog_t ** incomingLog,
66438a3987bSoster int clearReintFlag)
66538a3987bSoster {
66638a3987bSoster int regionID, logItem, itemDone;
66738a3987bSoster RF_ParityLogData_t *item;
66838a3987bSoster int punt, done = RF_FALSE;
66938a3987bSoster RF_ParityLog_t *log;
67038a3987bSoster RF_Raid_t *raidPtr;
67138a3987bSoster RF_Etimer_t timer;
672*b67baf4cSchristos void (*wakeFunc) (void *, int);
67338a3987bSoster void *wakeArg;
67438a3987bSoster
67500145885Soster /* Add parity to the appropriate log, one sector at a time. This
67600145885Soster * routine is called is called by dag functions ParityLogUpdateFunc
67700145885Soster * and ParityLogOverwriteFunc and therefore MUST BE NONBLOCKING.
67800145885Soster *
67900145885Soster * Parity to be logged is contained in a linked-list (logData). When
68000145885Soster * this routine returns, every sector in the list will be in one of
68100145885Soster * three places: 1) entered into the parity log 2) queued, waiting on
68200145885Soster * reintegration 3) queued, waiting on a core log
68300145885Soster *
68400145885Soster * Blocked work is passed to the ParityLoggingDiskManager for completion.
68500145885Soster * Later, as conditions which required the block are removed, the work
68600145885Soster * reenters this routine with the "finish" parameter set to "RF_TRUE."
68700145885Soster *
68800145885Soster * NON-BLOCKING */
68938a3987bSoster
69038a3987bSoster raidPtr = logData->common->raidPtr;
69138a3987bSoster /* lock the region for the first item in logData */
69238a3987bSoster RF_ASSERT(logData != NULL);
69338a3987bSoster regionID = logData->regionID;
694662e58c7Smrg rf_lock_mutex2(raidPtr->regionInfo[regionID].mutex);
69538a3987bSoster RF_ASSERT(raidPtr->regionInfo[regionID].loggingEnabled);
69638a3987bSoster
69700145885Soster if (clearReintFlag) {
69800145885Soster /* Enable flushing for this region. Holding both locks
69900145885Soster * provides a synchronization barrier with DumpParityLogToDisk */
7003dd61769Smrg rf_lock_mutex2(raidPtr->regionInfo[regionID].reintMutex);
70132ab76b9Smrg /* XXXmrg need this? */
70232ab76b9Smrg rf_lock_mutex2(raidPtr->parityLogDiskQueue.mutex);
70338a3987bSoster RF_ASSERT(raidPtr->regionInfo[regionID].reintInProgress == RF_TRUE);
70438a3987bSoster raidPtr->regionInfo[regionID].diskCount = 0;
70538a3987bSoster raidPtr->regionInfo[regionID].reintInProgress = RF_FALSE;
7063dd61769Smrg rf_unlock_mutex2(raidPtr->regionInfo[regionID].reintMutex); /* flushing is now
70700145885Soster * enabled */
70832ab76b9Smrg /* XXXmrg need this? */
70932ab76b9Smrg rf_unlock_mutex2(raidPtr->parityLogDiskQueue.mutex);
71038a3987bSoster }
71138a3987bSoster /* process each item in logData */
71200145885Soster while (logData) {
71338a3987bSoster /* remove an item from logData */
71438a3987bSoster item = logData;
71538a3987bSoster logData = logData->next;
71638a3987bSoster item->next = NULL;
71738a3987bSoster item->prev = NULL;
71838a3987bSoster
71938a3987bSoster if (rf_parityLogDebug)
72038a3987bSoster printf("[appending parity log data, region %d, raidAddress %d, numSector %d]\n", item->regionID, (int) item->diskAddress.raidAddress, (int) item->diskAddress.numSector);
72138a3987bSoster
72238a3987bSoster /* see if we moved to a new region */
72300145885Soster if (regionID != item->regionID) {
724662e58c7Smrg rf_unlock_mutex2(raidPtr->regionInfo[regionID].mutex);
72538a3987bSoster regionID = item->regionID;
726662e58c7Smrg rf_lock_mutex2(raidPtr->regionInfo[regionID].mutex);
72738a3987bSoster RF_ASSERT(raidPtr->regionInfo[regionID].loggingEnabled);
72838a3987bSoster }
72900145885Soster punt = RF_FALSE;/* Set to RF_TRUE if work is blocked. This
73000145885Soster * can happen in one of two ways: 1) no core
73100145885Soster * log (AcquireParityLog) 2) waiting on
73200145885Soster * reintegration (DumpParityLogToDisk) If punt
73300145885Soster * is RF_TRUE, the dataItem was queued, so
73400145885Soster * skip to next item. */
73538a3987bSoster
73600145885Soster /* process item, one sector at a time, until all sectors
73700145885Soster * processed or we punt */
73838a3987bSoster if (item->diskAddress.numSector > 0)
73938a3987bSoster done = RF_FALSE;
74038a3987bSoster else
74138a3987bSoster RF_ASSERT(0);
74200145885Soster while (!punt && !done) {
74338a3987bSoster /* verify that a core log exists for this region */
74400145885Soster if (!raidPtr->regionInfo[regionID].coreLog) {
74500145885Soster /* Attempt to acquire a parity log. If
74600145885Soster * acquisition fails, queue remaining work in
74700145885Soster * data item and move to nextItem. */
74838a3987bSoster if (incomingLog)
74900145885Soster if (*incomingLog) {
75038a3987bSoster RF_ASSERT((*incomingLog)->next == NULL);
75138a3987bSoster raidPtr->regionInfo[regionID].coreLog = *incomingLog;
75238a3987bSoster raidPtr->regionInfo[regionID].coreLog->regionID = regionID;
75338a3987bSoster *incomingLog = NULL;
75400145885Soster } else
75538a3987bSoster raidPtr->regionInfo[regionID].coreLog = AcquireParityLog(item, finish);
75638a3987bSoster else
75738a3987bSoster raidPtr->regionInfo[regionID].coreLog = AcquireParityLog(item, finish);
75800145885Soster /* Note: AcquireParityLog either returns a log
75900145885Soster * or enqueues currentItem */
76038a3987bSoster }
76138a3987bSoster if (!raidPtr->regionInfo[regionID].coreLog)
76238a3987bSoster punt = RF_TRUE; /* failed to find a core log */
76300145885Soster else {
76438a3987bSoster RF_ASSERT(raidPtr->regionInfo[regionID].coreLog->next == NULL);
76500145885Soster /* verify that the log has room for new
76600145885Soster * entries */
76700145885Soster /* if log is full, dump it to disk and grab a
76800145885Soster * new log */
76900145885Soster if (raidPtr->regionInfo[regionID].coreLog->numRecords == raidPtr->numSectorsPerLog) {
77038a3987bSoster /* log is full, dump it to disk */
77138a3987bSoster if (DumpParityLogToDisk(finish, item))
77200145885Soster punt = RF_TRUE; /* dump unsuccessful,
77300145885Soster * blocked on
77400145885Soster * reintegration */
77500145885Soster else {
77638a3987bSoster /* dump was successful */
77738a3987bSoster if (incomingLog)
77800145885Soster if (*incomingLog) {
77938a3987bSoster RF_ASSERT((*incomingLog)->next == NULL);
78038a3987bSoster raidPtr->regionInfo[regionID].coreLog = *incomingLog;
78138a3987bSoster raidPtr->regionInfo[regionID].coreLog->regionID = regionID;
78238a3987bSoster *incomingLog = NULL;
78300145885Soster } else
78438a3987bSoster raidPtr->regionInfo[regionID].coreLog = AcquireParityLog(item, finish);
78538a3987bSoster else
78638a3987bSoster raidPtr->regionInfo[regionID].coreLog = AcquireParityLog(item, finish);
78700145885Soster /* if a core log is not
78800145885Soster * available, must queue work
78900145885Soster * and return */
79038a3987bSoster if (!raidPtr->regionInfo[regionID].coreLog)
79100145885Soster punt = RF_TRUE; /* blocked on log
79200145885Soster * availability */
79338a3987bSoster }
79438a3987bSoster }
79538a3987bSoster }
79600145885Soster /* if we didn't punt on this item, attempt to add a
79700145885Soster * sector to the core log */
79800145885Soster if (!punt) {
79938a3987bSoster RF_ASSERT(raidPtr->regionInfo[regionID].coreLog->next == NULL);
80000145885Soster /* at this point, we have a core log with
80100145885Soster * enough room for a sector */
80238a3987bSoster /* copy a sector into the log */
80338a3987bSoster log = raidPtr->regionInfo[regionID].coreLog;
80438a3987bSoster RF_ASSERT(log->numRecords < raidPtr->numSectorsPerLog);
80538a3987bSoster logItem = log->numRecords++;
80638a3987bSoster log->records[logItem].parityAddr = item->diskAddress;
80738a3987bSoster RF_ASSERT(log->records[logItem].parityAddr.startSector >= raidPtr->regionInfo[regionID].parityStartAddr);
80838a3987bSoster RF_ASSERT(log->records[logItem].parityAddr.startSector < raidPtr->regionInfo[regionID].parityStartAddr + raidPtr->regionInfo[regionID].numSectorsParity);
80938a3987bSoster log->records[logItem].parityAddr.numSector = 1;
81038a3987bSoster log->records[logItem].operation = item->common->operation;
81153524e44Schristos memcpy((char *)log->bufPtr + (logItem * (1 << item->common->raidPtr->logBytesPerSector)), ((char *)item->common->bufPtr + (item->bufOffset++ * (1 << item->common->raidPtr->logBytesPerSector))), (1 << item->common->raidPtr->logBytesPerSector));
81238a3987bSoster item->diskAddress.numSector--;
81338a3987bSoster item->diskAddress.startSector++;
81438a3987bSoster if (item->diskAddress.numSector == 0)
81538a3987bSoster done = RF_TRUE;
81638a3987bSoster }
81738a3987bSoster }
81838a3987bSoster
81900145885Soster if (!punt) {
82000145885Soster /* Processed this item completely, decrement count of
82100145885Soster * items to be processed. */
82238a3987bSoster RF_ASSERT(item->diskAddress.numSector == 0);
8231c0dbcb6Smrg rf_lock_mutex2(item->common->mutex);
82438a3987bSoster item->common->cnt--;
82538a3987bSoster if (item->common->cnt == 0)
82638a3987bSoster itemDone = RF_TRUE;
82738a3987bSoster else
82838a3987bSoster itemDone = RF_FALSE;
8291c0dbcb6Smrg rf_unlock_mutex2(item->common->mutex);
83000145885Soster if (itemDone) {
83100145885Soster /* Finished processing all log data for this
83200145885Soster * IO Return structs to free list and invoke
83300145885Soster * wakeup function. */
83400145885Soster timer = item->common->startTime; /* grab initial value of
83500145885Soster * timer */
83638a3987bSoster RF_ETIMER_STOP(timer);
83738a3987bSoster RF_ETIMER_EVAL(timer);
83838a3987bSoster item->common->tracerec->plog_us += RF_ETIMER_VAL_US(timer);
83938a3987bSoster if (rf_parityLogDebug)
84038a3987bSoster printf("[waking process for region %d]\n", item->regionID);
84138a3987bSoster wakeFunc = item->common->wakeFunc;
84238a3987bSoster wakeArg = item->common->wakeArg;
84338a3987bSoster FreeParityLogCommonData(item->common);
84438a3987bSoster FreeParityLogData(item);
84538a3987bSoster (wakeFunc) (wakeArg, 0);
84600145885Soster } else
84738a3987bSoster FreeParityLogData(item);
84838a3987bSoster }
84938a3987bSoster }
850662e58c7Smrg rf_unlock_mutex2(raidPtr->regionInfo[regionID].mutex);
85138a3987bSoster if (rf_parityLogDebug)
85238a3987bSoster printf("[exiting ParityLogAppend]\n");
85338a3987bSoster return (0);
85438a3987bSoster }
85538a3987bSoster
85638a3987bSoster
85700145885Soster void
rf_EnableParityLogging(RF_Raid_t * raidPtr)85800145885Soster rf_EnableParityLogging(RF_Raid_t * raidPtr)
85938a3987bSoster {
86038a3987bSoster int regionID;
86138a3987bSoster
86238a3987bSoster for (regionID = 0; regionID < rf_numParityRegions; regionID++) {
863662e58c7Smrg rf_lock_mutex2(raidPtr->regionInfo[regionID].mutex);
86438a3987bSoster raidPtr->regionInfo[regionID].loggingEnabled = RF_TRUE;
865662e58c7Smrg rf_unlock_mutex2(raidPtr->regionInfo[regionID].mutex);
86638a3987bSoster }
86738a3987bSoster if (rf_parityLogDebug)
86838a3987bSoster printf("[parity logging enabled]\n");
86938a3987bSoster }
87038a3987bSoster #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
871