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