Home | History | Annotate | Line # | Download | only in raidframe
rf_cvscan.c revision 1.12
      1  1.12    perry /*	$NetBSD: rf_cvscan.c,v 1.12 2005/02/27 00:27:44 perry Exp $	*/
      2   1.1    oster /*
      3   1.1    oster  * Copyright (c) 1995 Carnegie-Mellon University.
      4   1.1    oster  * All rights reserved.
      5   1.1    oster  *
      6   1.1    oster  * Author: Mark Holland
      7   1.1    oster  *
      8   1.1    oster  * Permission to use, copy, modify and distribute this software and
      9   1.1    oster  * its documentation is hereby granted, provided that both the copyright
     10   1.1    oster  * notice and this permission notice appear in all copies of the
     11   1.1    oster  * software, derivative works or modified versions, and any portions
     12   1.1    oster  * thereof, and that both notices appear in supporting documentation.
     13   1.1    oster  *
     14   1.1    oster  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     15   1.1    oster  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     16   1.1    oster  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17   1.1    oster  *
     18   1.1    oster  * Carnegie Mellon requests users of this software to return to
     19   1.1    oster  *
     20   1.1    oster  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21   1.1    oster  *  School of Computer Science
     22   1.1    oster  *  Carnegie Mellon University
     23   1.1    oster  *  Pittsburgh PA 15213-3890
     24   1.1    oster  *
     25   1.1    oster  * any improvements or extensions that they make and grant Carnegie the
     26   1.1    oster  * rights to redistribute these changes.
     27   1.1    oster  */
     28   1.1    oster 
     29   1.1    oster /*******************************************************************************
     30   1.1    oster  *
     31   1.4    oster  * cvscan.c --  prioritized cvscan disk queueing code.
     32   1.1    oster  *
     33   1.1    oster  * Nov 9, 1994, adapted from raidSim version (MCH)
     34   1.1    oster  *
     35   1.1    oster  ******************************************************************************/
     36   1.8    lukem 
     37   1.8    lukem #include <sys/cdefs.h>
     38  1.12    perry __KERNEL_RCSID(0, "$NetBSD: rf_cvscan.c,v 1.12 2005/02/27 00:27:44 perry Exp $");
     39   1.1    oster 
     40   1.7    oster #include <dev/raidframe/raidframevar.h>
     41   1.1    oster #include "rf_alloclist.h"
     42   1.1    oster #include "rf_stripelocks.h"
     43   1.1    oster #include "rf_layout.h"
     44   1.1    oster #include "rf_diskqueue.h"
     45   1.1    oster #include "rf_cvscan.h"
     46   1.1    oster #include "rf_debugMem.h"
     47   1.1    oster #include "rf_general.h"
     48   1.1    oster 
     49  1.10    oster #define DO_CHECK_STATE(_hdr_) CheckCvscanState((_hdr_))
     50   1.1    oster 
     51   1.1    oster #define pri_ok(p)  ( ((p) == RF_IO_NORMAL_PRIORITY) || ((p) == RF_IO_LOW_PRIORITY))
     52   1.1    oster 
     53  1.12    perry static void
     54  1.11    oster CheckCvscanState(RF_CvscanHeader_t *hdr)
     55   1.1    oster {
     56   1.4    oster 	long    i, key;
     57   1.1    oster 	RF_DiskQueueData_t *tmp;
     58   1.1    oster 
     59   1.4    oster 	if (hdr->left != (RF_DiskQueueData_t *) NULL)
     60   1.4    oster 		RF_ASSERT(hdr->left->sectorOffset < hdr->cur_block);
     61   1.4    oster 	for (key = hdr->cur_block, i = 0, tmp = hdr->left;
     62   1.4    oster 	    tmp != (RF_DiskQueueData_t *) NULL;
     63   1.4    oster 	    key = tmp->sectorOffset, i++, tmp = tmp->next)
     64   1.4    oster 		RF_ASSERT(tmp->sectorOffset <= key
     65   1.4    oster 		    && tmp->priority == hdr->nxt_priority && pri_ok(tmp->priority));
     66   1.4    oster 	RF_ASSERT(i == hdr->left_cnt);
     67   1.4    oster 
     68   1.4    oster 	for (key = hdr->cur_block, i = 0, tmp = hdr->right;
     69   1.4    oster 	    tmp != (RF_DiskQueueData_t *) NULL;
     70   1.4    oster 	    key = tmp->sectorOffset, i++, tmp = tmp->next) {
     71   1.1    oster 		RF_ASSERT(key <= tmp->sectorOffset);
     72   1.1    oster 		RF_ASSERT(tmp->priority == hdr->nxt_priority);
     73   1.1    oster 		RF_ASSERT(pri_ok(tmp->priority));
     74   1.1    oster 	}
     75   1.4    oster 	RF_ASSERT(i == hdr->right_cnt);
     76   1.1    oster 
     77   1.4    oster 	for (key = hdr->nxt_priority - 1, tmp = hdr->burner;
     78   1.4    oster 	    tmp != (RF_DiskQueueData_t *) NULL;
     79   1.4    oster 	    key = tmp->priority, tmp = tmp->next) {
     80   1.1    oster 		RF_ASSERT(tmp);
     81   1.1    oster 		RF_ASSERT(hdr);
     82   1.1    oster 		RF_ASSERT(pri_ok(tmp->priority));
     83   1.1    oster 		RF_ASSERT(key >= tmp->priority);
     84   1.1    oster 		RF_ASSERT(tmp->priority < hdr->nxt_priority);
     85   1.1    oster 	}
     86   1.1    oster }
     87   1.1    oster 
     88   1.1    oster 
     89   1.1    oster 
     90  1.12    perry static void
     91  1.11    oster PriorityInsert(RF_DiskQueueData_t **list_ptr, RF_DiskQueueData_t *req)
     92   1.1    oster {
     93   1.4    oster 	/* * insert block pointed to by req in to list whose first * entry is
     94   1.4    oster 	 * pointed to by the pointer that list_ptr points to * ie., list_ptr
     95   1.4    oster 	 * is a grandparent of the first entry */
     96   1.4    oster 
     97   1.4    oster 	for (; (*list_ptr) != (RF_DiskQueueData_t *) NULL &&
     98   1.4    oster 	    (*list_ptr)->priority > req->priority;
     99   1.4    oster 	    list_ptr = &((*list_ptr)->next)) {
    100   1.4    oster 	}
    101   1.1    oster 	req->next = (*list_ptr);
    102   1.1    oster 	(*list_ptr) = req;
    103   1.1    oster }
    104   1.1    oster 
    105   1.1    oster 
    106   1.1    oster 
    107  1.12    perry static void
    108  1.11    oster ReqInsert(RF_DiskQueueData_t **list_ptr, RF_DiskQueueData_t *req, RF_CvscanArmDir_t order)
    109   1.1    oster {
    110   1.4    oster 	/* * insert block pointed to by req in to list whose first * entry is
    111   1.4    oster 	 * pointed to by the pointer that list_ptr points to * ie., list_ptr
    112   1.4    oster 	 * is a grandparent of the first entry */
    113   1.4    oster 
    114   1.4    oster 	for (; (*list_ptr) != (RF_DiskQueueData_t *) NULL &&
    115   1.4    oster 
    116   1.4    oster 	    ((order == rf_cvscan_RIGHT && (*list_ptr)->sectorOffset <= req->sectorOffset)
    117   1.4    oster 		|| (order == rf_cvscan_LEFT && (*list_ptr)->sectorOffset > req->sectorOffset));
    118   1.4    oster 	    list_ptr = &((*list_ptr)->next)) {
    119   1.4    oster 	}
    120   1.1    oster 	req->next = (*list_ptr);
    121   1.1    oster 	(*list_ptr) = req;
    122   1.1    oster }
    123   1.1    oster 
    124   1.1    oster 
    125   1.1    oster 
    126   1.4    oster static RF_DiskQueueData_t *
    127  1.11    oster ReqDequeue(RF_DiskQueueData_t **list_ptr)
    128   1.1    oster {
    129   1.4    oster 	RF_DiskQueueData_t *ret = (*list_ptr);
    130   1.4    oster 	if ((*list_ptr) != (RF_DiskQueueData_t *) NULL) {
    131   1.1    oster 		(*list_ptr) = (*list_ptr)->next;
    132   1.1    oster 	}
    133   1.4    oster 	return (ret);
    134   1.1    oster }
    135   1.1    oster 
    136   1.1    oster 
    137   1.1    oster 
    138  1.12    perry static void
    139  1.11    oster ReBalance(RF_CvscanHeader_t *hdr)
    140   1.1    oster {
    141   1.1    oster 	/* DO_CHECK_STATE(hdr); */
    142   1.4    oster 	while (hdr->right != (RF_DiskQueueData_t *) NULL
    143   1.4    oster 	    && hdr->right->sectorOffset < hdr->cur_block) {
    144   1.1    oster 		hdr->right_cnt--;
    145   1.1    oster 		hdr->left_cnt++;
    146   1.4    oster 		ReqInsert(&hdr->left, ReqDequeue(&hdr->right), rf_cvscan_LEFT);
    147   1.1    oster 	}
    148   1.1    oster 	/* DO_CHECK_STATE(hdr); */
    149   1.1    oster }
    150   1.1    oster 
    151   1.1    oster 
    152   1.1    oster 
    153  1.12    perry static void
    154  1.11    oster Transfer(RF_DiskQueueData_t **to_list_ptr, RF_DiskQueueData_t **from_list_ptr)
    155   1.1    oster {
    156   1.1    oster 	RF_DiskQueueData_t *gp;
    157   1.4    oster 	for (gp = (*from_list_ptr); gp != (RF_DiskQueueData_t *) NULL;) {
    158   1.1    oster 		RF_DiskQueueData_t *p = gp->next;
    159   1.4    oster 		PriorityInsert(to_list_ptr, gp);
    160   1.1    oster 		gp = p;
    161   1.1    oster 	}
    162   1.1    oster 	(*from_list_ptr) = (RF_DiskQueueData_t *) NULL;
    163   1.1    oster }
    164   1.1    oster 
    165   1.1    oster 
    166   1.1    oster 
    167  1.12    perry static void
    168  1.11    oster RealEnqueue(RF_CvscanHeader_t *hdr, RF_DiskQueueData_t *req)
    169   1.1    oster {
    170   1.1    oster 	RF_ASSERT(req->priority == RF_IO_NORMAL_PRIORITY || req->priority == RF_IO_LOW_PRIORITY);
    171   1.4    oster 
    172   1.1    oster 	DO_CHECK_STATE(hdr);
    173   1.4    oster 	if (hdr->left_cnt == 0 && hdr->right_cnt == 0) {
    174   1.1    oster 		hdr->nxt_priority = req->priority;
    175   1.1    oster 	}
    176   1.4    oster 	if (req->priority > hdr->nxt_priority) {
    177   1.1    oster 		/*
    178   1.1    oster 		** dump all other outstanding requests on the back burner
    179   1.1    oster 		*/
    180   1.4    oster 		Transfer(&hdr->burner, &hdr->left);
    181   1.4    oster 		Transfer(&hdr->burner, &hdr->right);
    182   1.1    oster 		hdr->left_cnt = 0;
    183   1.1    oster 		hdr->right_cnt = 0;
    184   1.1    oster 		hdr->nxt_priority = req->priority;
    185   1.1    oster 	}
    186   1.4    oster 	if (req->priority < hdr->nxt_priority) {
    187   1.1    oster 		/*
    188   1.1    oster 		** yet another low priority task!
    189   1.1    oster 		*/
    190   1.4    oster 		PriorityInsert(&hdr->burner, req);
    191   1.1    oster 	} else {
    192   1.4    oster 		if (req->sectorOffset < hdr->cur_block) {
    193   1.1    oster 			/* this request is to the left of the current arms */
    194   1.4    oster 			ReqInsert(&hdr->left, req, rf_cvscan_LEFT);
    195   1.1    oster 			hdr->left_cnt++;
    196   1.1    oster 		} else {
    197   1.1    oster 			/* this request is to the right of the current arms */
    198   1.4    oster 			ReqInsert(&hdr->right, req, rf_cvscan_RIGHT);
    199   1.1    oster 			hdr->right_cnt++;
    200   1.1    oster 		}
    201   1.1    oster 	}
    202   1.1    oster 	DO_CHECK_STATE(hdr);
    203   1.1    oster }
    204   1.1    oster 
    205   1.1    oster 
    206   1.1    oster 
    207  1.12    perry void
    208   1.4    oster rf_CvscanEnqueue(void *q_in, RF_DiskQueueData_t * elem, int priority)
    209   1.1    oster {
    210   1.4    oster 	RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
    211   1.4    oster 	RealEnqueue(hdr, elem /* req */ );
    212   1.1    oster }
    213   1.1    oster 
    214   1.1    oster 
    215   1.1    oster 
    216   1.4    oster RF_DiskQueueData_t *
    217   1.4    oster rf_CvscanDequeue(void *q_in)
    218   1.1    oster {
    219   1.4    oster 	RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
    220   1.4    oster 	long    range, i, sum_dist_left, sum_dist_right;
    221   1.1    oster 	RF_DiskQueueData_t *ret;
    222   1.1    oster 	RF_DiskQueueData_t *tmp;
    223   1.1    oster 
    224   1.1    oster 	DO_CHECK_STATE(hdr);
    225   1.1    oster 
    226   1.4    oster 	if (hdr->left_cnt == 0 && hdr->right_cnt == 0)
    227   1.4    oster 		return ((RF_DiskQueueData_t *) NULL);
    228   1.4    oster 
    229   1.4    oster 	range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt, hdr->right_cnt));
    230   1.4    oster 	for (i = 0, tmp = hdr->left, sum_dist_left =
    231   1.4    oster 	    ((hdr->direction == rf_cvscan_RIGHT) ? range * hdr->change_penalty : 0);
    232   1.4    oster 	    tmp != (RF_DiskQueueData_t *) NULL && i < range;
    233   1.4    oster 	    tmp = tmp->next, i++) {
    234   1.1    oster 		sum_dist_left += hdr->cur_block - tmp->sectorOffset;
    235   1.1    oster 	}
    236   1.4    oster 	for (i = 0, tmp = hdr->right, sum_dist_right =
    237   1.4    oster 	    ((hdr->direction == rf_cvscan_LEFT) ? range * hdr->change_penalty : 0);
    238   1.4    oster 	    tmp != (RF_DiskQueueData_t *) NULL && i < range;
    239   1.4    oster 	    tmp = tmp->next, i++) {
    240   1.1    oster 		sum_dist_right += tmp->sectorOffset - hdr->cur_block;
    241   1.1    oster 	}
    242   1.1    oster 
    243   1.4    oster 	if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right) {
    244   1.1    oster 		hdr->direction = rf_cvscan_LEFT;
    245   1.1    oster 		hdr->cur_block = hdr->left->sectorOffset + hdr->left->numSector;
    246   1.4    oster 		hdr->left_cnt = RF_MAX(hdr->left_cnt - 1, 0);
    247   1.1    oster 		tmp = hdr->left;
    248   1.4    oster 		ret = (ReqDequeue(&hdr->left)) /*->parent*/ ;
    249   1.1    oster 	} else {
    250   1.1    oster 		hdr->direction = rf_cvscan_RIGHT;
    251   1.1    oster 		hdr->cur_block = hdr->right->sectorOffset + hdr->right->numSector;
    252   1.4    oster 		hdr->right_cnt = RF_MAX(hdr->right_cnt - 1, 0);
    253   1.1    oster 		tmp = hdr->right;
    254   1.4    oster 		ret = (ReqDequeue(&hdr->right)) /*->parent*/ ;
    255   1.1    oster 	}
    256   1.4    oster 	ReBalance(hdr);
    257   1.1    oster 
    258   1.4    oster 	if (hdr->left_cnt == 0 && hdr->right_cnt == 0
    259   1.4    oster 	    && hdr->burner != (RF_DiskQueueData_t *) NULL) {
    260   1.1    oster 		/*
    261   1.1    oster 		** restore low priority requests for next dequeue
    262   1.1    oster 		*/
    263   1.1    oster 		RF_DiskQueueData_t *burner = hdr->burner;
    264   1.1    oster 		hdr->nxt_priority = burner->priority;
    265   1.4    oster 		while (burner != (RF_DiskQueueData_t *) NULL
    266   1.4    oster 		    && burner->priority == hdr->nxt_priority) {
    267   1.1    oster 			RF_DiskQueueData_t *next = burner->next;
    268   1.4    oster 			RealEnqueue(hdr, burner);
    269   1.1    oster 			burner = next;
    270   1.1    oster 		}
    271   1.1    oster 		hdr->burner = burner;
    272   1.1    oster 	}
    273   1.1    oster 	DO_CHECK_STATE(hdr);
    274   1.4    oster 	return (ret);
    275   1.1    oster }
    276   1.1    oster 
    277   1.1    oster 
    278   1.1    oster 
    279   1.4    oster RF_DiskQueueData_t *
    280   1.4    oster rf_CvscanPeek(void *q_in)
    281   1.1    oster {
    282   1.4    oster 	RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
    283   1.4    oster 	long    range, i, sum_dist_left, sum_dist_right;
    284   1.4    oster 	RF_DiskQueueData_t *tmp, *headElement;
    285   1.4    oster 
    286   1.4    oster 	DO_CHECK_STATE(hdr);
    287   1.4    oster 
    288   1.4    oster 	if (hdr->left_cnt == 0 && hdr->right_cnt == 0)
    289   1.4    oster 		headElement = NULL;
    290   1.4    oster 	else {
    291   1.4    oster 		range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt, hdr->right_cnt));
    292   1.4    oster 		for (i = 0, tmp = hdr->left, sum_dist_left =
    293   1.4    oster 		    ((hdr->direction == rf_cvscan_RIGHT) ? range * hdr->change_penalty : 0);
    294   1.4    oster 		    tmp != (RF_DiskQueueData_t *) NULL && i < range;
    295   1.4    oster 		    tmp = tmp->next, i++) {
    296   1.4    oster 			sum_dist_left += hdr->cur_block - tmp->sectorOffset;
    297   1.4    oster 		}
    298   1.4    oster 		for (i = 0, tmp = hdr->right, sum_dist_right =
    299   1.4    oster 		    ((hdr->direction == rf_cvscan_LEFT) ? range * hdr->change_penalty : 0);
    300   1.4    oster 		    tmp != (RF_DiskQueueData_t *) NULL && i < range;
    301   1.4    oster 		    tmp = tmp->next, i++) {
    302   1.4    oster 			sum_dist_right += tmp->sectorOffset - hdr->cur_block;
    303   1.4    oster 		}
    304   1.4    oster 
    305   1.4    oster 		if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right)
    306   1.4    oster 			headElement = hdr->left;
    307   1.4    oster 		else
    308   1.4    oster 			headElement = hdr->right;
    309   1.4    oster 	}
    310   1.4    oster 	return (headElement);
    311   1.1    oster }
    312   1.1    oster 
    313   1.1    oster 
    314   1.1    oster 
    315   1.1    oster /*
    316   1.1    oster ** CVSCAN( 1, 0 ) is Shortest Seek Time First (SSTF)
    317   1.1    oster **				lowest average response time
    318   1.1    oster ** CVSCAN( 1, infinity ) is SCAN
    319   1.1    oster **				lowest response time standard deviation
    320   1.1    oster */
    321   1.1    oster 
    322   1.4    oster void   *
    323   1.4    oster rf_CvscanCreate(RF_SectorCount_t sectPerDisk,
    324  1.11    oster     RF_AllocListElem_t *clList,
    325  1.11    oster     RF_ShutdownList_t **listp)
    326   1.1    oster {
    327   1.1    oster 	RF_CvscanHeader_t *hdr;
    328   1.4    oster 	long    range = 2;	/* Currently no mechanism to change these */
    329   1.4    oster 	long    penalty = sectPerDisk / 5;
    330   1.1    oster 
    331   1.1    oster 	RF_MallocAndAdd(hdr, sizeof(RF_CvscanHeader_t), (RF_CvscanHeader_t *), clList);
    332   1.6  thorpej 	memset((char *) hdr, 0, sizeof(RF_CvscanHeader_t));
    333   1.4    oster 	hdr->range_for_avg = RF_MAX(range, 1);
    334   1.4    oster 	hdr->change_penalty = RF_MAX(penalty, 0);
    335   1.1    oster 	hdr->direction = rf_cvscan_RIGHT;
    336   1.1    oster 	hdr->cur_block = 0;
    337   1.1    oster 	hdr->left_cnt = hdr->right_cnt = 0;
    338   1.1    oster 	hdr->left = hdr->right = (RF_DiskQueueData_t *) NULL;
    339   1.1    oster 	hdr->burner = (RF_DiskQueueData_t *) NULL;
    340   1.1    oster 	DO_CHECK_STATE(hdr);
    341   1.1    oster 
    342   1.4    oster 	return ((void *) hdr);
    343   1.1    oster }
    344   1.1    oster 
    345   1.1    oster 
    346   1.1    oster #if defined(__NetBSD__) && defined(_KERNEL)
    347   1.1    oster /* PrintCvscanQueue is not used, so we ignore it... */
    348   1.1    oster #else
    349  1.12    perry static void
    350  1.11    oster PrintCvscanQueue(RF_CvscanHeader_t *hdr)
    351   1.1    oster {
    352   1.1    oster 	RF_DiskQueueData_t *tmp;
    353   1.1    oster 
    354   1.4    oster 	printf("CVSCAN(%d,%d) at %d going %s\n",
    355   1.4    oster 	    (int) hdr->range_for_avg,
    356   1.4    oster 	    (int) hdr->change_penalty,
    357   1.4    oster 	    (int) hdr->cur_block,
    358   1.4    oster 	    (hdr->direction == rf_cvscan_LEFT) ? "LEFT" : "RIGHT");
    359   1.4    oster 	printf("\tLeft(%d): ", hdr->left_cnt);
    360   1.4    oster 	for (tmp = hdr->left; tmp != (RF_DiskQueueData_t *) NULL; tmp = tmp->next)
    361   1.4    oster 		printf("(%d,%ld,%d) ",
    362   1.4    oster 		    (int) tmp->sectorOffset,
    363   1.4    oster 		    (long) (tmp->sectorOffset + tmp->numSector),
    364   1.4    oster 		    tmp->priority);
    365   1.4    oster 	printf("\n");
    366   1.4    oster 	printf("\tRight(%d): ", hdr->right_cnt);
    367   1.4    oster 	for (tmp = hdr->right; tmp != (RF_DiskQueueData_t *) NULL; tmp = tmp->next)
    368   1.4    oster 		printf("(%d,%ld,%d) ",
    369   1.4    oster 		    (int) tmp->sectorOffset,
    370   1.4    oster 		    (long) (tmp->sectorOffset + tmp->numSector),
    371   1.4    oster 		    tmp->priority);
    372   1.4    oster 	printf("\n");
    373   1.4    oster 	printf("\tBurner: ");
    374   1.4    oster 	for (tmp = hdr->burner; tmp != (RF_DiskQueueData_t *) NULL; tmp = tmp->next)
    375   1.4    oster 		printf("(%d,%ld,%d) ",
    376   1.4    oster 		    (int) tmp->sectorOffset,
    377   1.4    oster 		    (long) (tmp->sectorOffset + tmp->numSector),
    378   1.4    oster 		    tmp->priority);
    379   1.4    oster 	printf("\n");
    380   1.1    oster }
    381   1.1    oster #endif
    382   1.1    oster 
    383   1.1    oster 
    384   1.1    oster /* promotes reconstruction accesses for the given stripeID to normal priority.
    385   1.1    oster  * returns 1 if an access was found and zero otherwise.  Normally, we should
    386   1.1    oster  * only have one or zero entries in the burner queue, so execution time should
    387   1.1    oster  * be short.
    388   1.1    oster  */
    389  1.12    perry int
    390  1.12    perry rf_CvscanPromote(void *q_in, RF_StripeNum_t parityStripeID,
    391  1.11    oster 		 RF_ReconUnitNum_t which_ru)
    392   1.1    oster {
    393   1.4    oster 	RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
    394   1.4    oster 	RF_DiskQueueData_t *trailer = NULL, *tmp = hdr->burner, *tlist = NULL;
    395   1.4    oster 	int     retval = 0;
    396   1.1    oster 
    397   1.1    oster 	DO_CHECK_STATE(hdr);
    398   1.4    oster 	while (tmp) {		/* handle entries at the front of the list */
    399   1.4    oster 		if (tmp->parityStripeID == parityStripeID && tmp->which_ru == which_ru) {
    400   1.4    oster 			hdr->burner = tmp->next;
    401   1.4    oster 			tmp->priority = RF_IO_NORMAL_PRIORITY;
    402   1.4    oster 			tmp->next = tlist;
    403   1.4    oster 			tlist = tmp;
    404   1.4    oster 			tmp = hdr->burner;
    405   1.4    oster 		} else
    406   1.4    oster 			break;
    407   1.4    oster 	}
    408   1.4    oster 	if (tmp) {
    409   1.4    oster 		trailer = tmp;
    410   1.4    oster 		tmp = tmp->next;
    411   1.4    oster 	}
    412   1.4    oster 	while (tmp) {		/* handle entries on the rest of the list */
    413   1.4    oster 		if (tmp->parityStripeID == parityStripeID && tmp->which_ru == which_ru) {
    414   1.4    oster 			trailer->next = tmp->next;
    415   1.4    oster 			tmp->priority = RF_IO_NORMAL_PRIORITY;
    416   1.4    oster 			tmp->next = tlist;
    417   1.4    oster 			tlist = tmp;	/* insert on a temp queue */
    418   1.4    oster 			tmp = trailer->next;
    419   1.4    oster 		} else {
    420   1.4    oster 			trailer = tmp;
    421   1.4    oster 			tmp = tmp->next;
    422   1.4    oster 		}
    423   1.1    oster 	}
    424   1.4    oster 	while (tlist) {
    425   1.4    oster 		retval++;
    426   1.4    oster 		tmp = tlist->next;
    427   1.4    oster 		RealEnqueue(hdr, tlist);
    428   1.4    oster 		tlist = tmp;
    429   1.4    oster 	}
    430   1.4    oster 	RF_ASSERT(retval == 0 || retval == 1);
    431   1.4    oster 	DO_CHECK_STATE((RF_CvscanHeader_t *) q_in);
    432   1.4    oster 	return (retval);
    433   1.1    oster }
    434