Home | History | Annotate | Line # | Download | only in raidframe
rf_cvscan.c revision 1.11.10.1
      1  1.11.10.1     yamt /*	$NetBSD: rf_cvscan.c,v 1.11.10.1 2005/03/19 08:35:41 yamt 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.11.10.1     yamt __KERNEL_RCSID(0, "$NetBSD: rf_cvscan.c,v 1.11.10.1 2005/03/19 08:35:41 yamt 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.11.10.1     yamt 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.11.10.1     yamt 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.11.10.1     yamt 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.11.10.1     yamt 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.11.10.1     yamt 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.11.10.1     yamt 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.11.10.1     yamt 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.11.10.1     yamt 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.11.10.1     yamt int
    390  1.11.10.1     yamt 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