Home | History | Annotate | Line # | Download | only in raidframe
rf_sstf.c revision 1.15.68.1
      1  1.15.68.1       jym /*	$NetBSD: rf_sstf.c,v 1.15.68.1 2009/05/13 17:21:16 jym 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: Jim Zelenka
      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.1     oster  * sstf.c --  prioritized shortest seek time first disk queueing code
     32        1.1     oster  *
     33        1.1     oster  ******************************************************************************/
     34        1.8     lukem 
     35        1.8     lukem #include <sys/cdefs.h>
     36  1.15.68.1       jym __KERNEL_RCSID(0, "$NetBSD: rf_sstf.c,v 1.15.68.1 2009/05/13 17:21:16 jym Exp $");
     37        1.8     lukem 
     38        1.7     oster #include <dev/raidframe/raidframevar.h>
     39        1.1     oster 
     40        1.1     oster #include "rf_alloclist.h"
     41        1.1     oster #include "rf_stripelocks.h"
     42        1.1     oster #include "rf_layout.h"
     43        1.1     oster #include "rf_diskqueue.h"
     44        1.1     oster #include "rf_sstf.h"
     45        1.1     oster #include "rf_debugMem.h"
     46        1.1     oster #include "rf_general.h"
     47        1.1     oster #include "rf_options.h"
     48        1.4     oster #include "rf_raid.h"
     49        1.1     oster 
     50        1.1     oster #define DIR_LEFT   1
     51        1.1     oster #define DIR_RIGHT  2
     52        1.1     oster #define DIR_EITHER 3
     53        1.1     oster 
     54        1.1     oster #define SNUM_DIFF(_a_,_b_) (((_a_)>(_b_))?((_a_)-(_b_)):((_b_)-(_a_)))
     55        1.1     oster 
     56        1.1     oster #define QSUM(_sstfq_) (((_sstfq_)->lopri.qlen)+((_sstfq_)->left.qlen)+((_sstfq_)->right.qlen))
     57        1.1     oster 
     58        1.1     oster 
     59       1.12     perry static void
     60        1.3     oster do_sstf_ord_q(RF_DiskQueueData_t **,
     61        1.3     oster     RF_DiskQueueData_t **,
     62        1.3     oster     RF_DiskQueueData_t *);
     63        1.3     oster 
     64        1.3     oster static RF_DiskQueueData_t *
     65        1.3     oster closest_to_arm(RF_SstfQ_t *,
     66        1.3     oster     RF_SectorNum_t,
     67        1.3     oster     int *,
     68        1.3     oster     int);
     69        1.3     oster static void do_dequeue(RF_SstfQ_t *, RF_DiskQueueData_t *);
     70        1.3     oster 
     71        1.3     oster 
     72       1.12     perry static void
     73  1.15.68.1       jym do_sstf_ord_q(RF_DiskQueueData_t **queuep, RF_DiskQueueData_t **tailp, RF_DiskQueueData_t *req)
     74        1.1     oster {
     75        1.1     oster 	RF_DiskQueueData_t *r, *s;
     76        1.1     oster 
     77        1.1     oster 	if (*queuep == NULL) {
     78        1.1     oster 		*queuep = req;
     79        1.1     oster 		*tailp = req;
     80        1.1     oster 		req->next = NULL;
     81        1.1     oster 		req->prev = NULL;
     82        1.1     oster 		return;
     83        1.1     oster 	}
     84        1.1     oster 	if (req->sectorOffset <= (*queuep)->sectorOffset) {
     85        1.1     oster 		req->next = *queuep;
     86        1.1     oster 		req->prev = NULL;
     87        1.1     oster 		(*queuep)->prev = req;
     88        1.1     oster 		*queuep = req;
     89        1.1     oster 		return;
     90        1.1     oster 	}
     91        1.1     oster 	if (req->sectorOffset > (*tailp)->sectorOffset) {
     92        1.1     oster 		/* optimization */
     93        1.1     oster 		r = NULL;
     94        1.1     oster 		s = *tailp;
     95        1.1     oster 		goto q_at_end;
     96        1.1     oster 	}
     97        1.3     oster 	for (s = NULL, r = *queuep; r; s = r, r = r->next) {
     98        1.1     oster 		if (r->sectorOffset >= req->sectorOffset) {
     99        1.1     oster 			/* insert after s, before r */
    100        1.1     oster 			RF_ASSERT(s);
    101        1.1     oster 			req->next = r;
    102        1.1     oster 			r->prev = req;
    103        1.1     oster 			s->next = req;
    104        1.1     oster 			req->prev = s;
    105        1.1     oster 			return;
    106        1.1     oster 		}
    107        1.1     oster 	}
    108        1.1     oster q_at_end:
    109        1.1     oster 	/* insert after s, at end of queue */
    110        1.1     oster 	RF_ASSERT(r == NULL);
    111        1.1     oster 	RF_ASSERT(s);
    112        1.1     oster 	RF_ASSERT(s == (*tailp));
    113        1.1     oster 	req->next = NULL;
    114        1.1     oster 	req->prev = s;
    115        1.1     oster 	s->next = req;
    116        1.1     oster 	*tailp = req;
    117        1.1     oster }
    118        1.1     oster /* for removing from head-of-queue */
    119        1.1     oster #define DO_HEAD_DEQ(_r_,_q_) { \
    120        1.1     oster 	_r_ = (_q_)->queue; \
    121        1.1     oster 	RF_ASSERT((_r_) != NULL); \
    122        1.1     oster 	(_q_)->queue = (_r_)->next; \
    123        1.1     oster 	(_q_)->qlen--; \
    124        1.1     oster 	if ((_q_)->qlen == 0) { \
    125        1.1     oster 		RF_ASSERT((_r_) == (_q_)->qtail); \
    126        1.1     oster 		RF_ASSERT((_q_)->queue == NULL); \
    127        1.1     oster 		(_q_)->qtail = NULL; \
    128        1.1     oster 	} \
    129        1.1     oster 	else { \
    130        1.1     oster 		RF_ASSERT((_q_)->queue->prev == (_r_)); \
    131        1.1     oster 		(_q_)->queue->prev = NULL; \
    132        1.1     oster 	} \
    133        1.1     oster }
    134        1.1     oster 
    135        1.1     oster /* for removing from end-of-queue */
    136        1.1     oster #define DO_TAIL_DEQ(_r_,_q_) { \
    137        1.1     oster 	_r_ = (_q_)->qtail; \
    138        1.1     oster 	RF_ASSERT((_r_) != NULL); \
    139        1.1     oster 	(_q_)->qtail = (_r_)->prev; \
    140        1.1     oster 	(_q_)->qlen--; \
    141        1.1     oster 	if ((_q_)->qlen == 0) { \
    142        1.1     oster 		RF_ASSERT((_r_) == (_q_)->queue); \
    143        1.1     oster 		RF_ASSERT((_q_)->qtail == NULL); \
    144        1.1     oster 		(_q_)->queue = NULL; \
    145        1.1     oster 	} \
    146        1.1     oster 	else { \
    147        1.1     oster 		RF_ASSERT((_q_)->qtail->next == (_r_)); \
    148        1.1     oster 		(_q_)->qtail->next = NULL; \
    149        1.1     oster 	} \
    150        1.1     oster }
    151        1.1     oster 
    152        1.1     oster #define DO_BEST_DEQ(_l_,_r_,_q_) { \
    153        1.1     oster 	if (SNUM_DIFF((_q_)->queue->sectorOffset,_l_) \
    154        1.1     oster 		< SNUM_DIFF((_q_)->qtail->sectorOffset,_l_)) \
    155        1.1     oster 	{ \
    156        1.1     oster 		DO_HEAD_DEQ(_r_,_q_); \
    157        1.1     oster 	} \
    158        1.1     oster 	else { \
    159        1.1     oster 		DO_TAIL_DEQ(_r_,_q_); \
    160        1.1     oster 	} \
    161        1.1     oster }
    162        1.1     oster 
    163        1.3     oster static RF_DiskQueueData_t *
    164  1.15.68.1       jym closest_to_arm(RF_SstfQ_t *queue, RF_SectorNum_t arm_pos, int *dir, int allow_reverse)
    165        1.1     oster {
    166        1.3     oster 	RF_SectorNum_t best_pos_l = 0, this_pos_l = 0, last_pos = 0;
    167        1.3     oster 	RF_SectorNum_t best_pos_r = 0, this_pos_r = 0;
    168        1.1     oster 	RF_DiskQueueData_t *r, *best_l, *best_r;
    169        1.1     oster 
    170        1.1     oster 	best_r = best_l = NULL;
    171        1.3     oster 	for (r = queue->queue; r; r = r->next) {
    172        1.1     oster 		if (r->sectorOffset < arm_pos) {
    173        1.1     oster 			if (best_l == NULL) {
    174        1.1     oster 				best_l = r;
    175        1.1     oster 				last_pos = best_pos_l = this_pos_l;
    176        1.3     oster 			} else {
    177        1.1     oster 				this_pos_l = arm_pos - r->sectorOffset;
    178        1.1     oster 				if (this_pos_l < best_pos_l) {
    179        1.1     oster 					best_l = r;
    180        1.1     oster 					last_pos = best_pos_l = this_pos_l;
    181        1.3     oster 				} else {
    182        1.1     oster 					last_pos = this_pos_l;
    183        1.1     oster 				}
    184        1.1     oster 			}
    185        1.3     oster 		} else {
    186        1.1     oster 			if (best_r == NULL) {
    187        1.1     oster 				best_r = r;
    188        1.1     oster 				last_pos = best_pos_r = this_pos_r;
    189        1.3     oster 			} else {
    190        1.1     oster 				this_pos_r = r->sectorOffset - arm_pos;
    191        1.1     oster 				if (this_pos_r < best_pos_r) {
    192        1.1     oster 					best_r = r;
    193        1.1     oster 					last_pos = best_pos_r = this_pos_r;
    194        1.3     oster 				} else {
    195        1.1     oster 					last_pos = this_pos_r;
    196        1.1     oster 				}
    197        1.1     oster 				if (this_pos_r > last_pos) {
    198        1.1     oster 					/* getting farther away */
    199        1.1     oster 					break;
    200        1.1     oster 				}
    201        1.1     oster 			}
    202        1.1     oster 		}
    203        1.1     oster 	}
    204        1.1     oster 	if ((best_r == NULL) && (best_l == NULL))
    205        1.3     oster 		return (NULL);
    206        1.1     oster 	if ((*dir == DIR_RIGHT) && best_r)
    207        1.3     oster 		return (best_r);
    208        1.1     oster 	if ((*dir == DIR_LEFT) && best_l)
    209        1.3     oster 		return (best_l);
    210        1.1     oster 	if (*dir == DIR_EITHER) {
    211        1.1     oster 		if (best_l == NULL)
    212        1.3     oster 			return (best_r);
    213        1.1     oster 		if (best_r == NULL)
    214        1.3     oster 			return (best_l);
    215        1.1     oster 		if (best_pos_r < best_pos_l)
    216        1.3     oster 			return (best_r);
    217        1.1     oster 		else
    218        1.3     oster 			return (best_l);
    219        1.1     oster 	}
    220        1.1     oster 	/*
    221        1.1     oster 	 * Nothing in the direction we want to go. Reverse or
    222        1.1     oster 	 * reset the arm. We know we have an I/O in the other
    223        1.1     oster 	 * direction.
    224        1.1     oster 	 */
    225        1.1     oster 	if (allow_reverse) {
    226        1.1     oster 		if (*dir == DIR_RIGHT) {
    227        1.1     oster 			*dir = DIR_LEFT;
    228        1.3     oster 			return (best_l);
    229        1.3     oster 		} else {
    230        1.1     oster 			*dir = DIR_RIGHT;
    231        1.3     oster 			return (best_r);
    232        1.1     oster 		}
    233        1.1     oster 	}
    234        1.1     oster 	/*
    235        1.1     oster 	 * Reset (beginning of queue).
    236        1.1     oster 	 */
    237        1.1     oster 	RF_ASSERT(*dir == DIR_RIGHT);
    238        1.3     oster 	return (queue->queue);
    239        1.1     oster }
    240        1.1     oster 
    241        1.3     oster void   *
    242       1.14  christos rf_SstfCreate(
    243       1.15  christos 	RF_SectorCount_t sect_per_disk,
    244       1.14  christos 	RF_AllocListElem_t *cl_list,
    245       1.15  christos 	RF_ShutdownList_t **listp)
    246        1.1     oster {
    247        1.1     oster 	RF_Sstf_t *sstfq;
    248        1.1     oster 
    249       1.10     oster 	RF_MallocAndAdd(sstfq, sizeof(RF_Sstf_t), (RF_Sstf_t *), cl_list);
    250        1.1     oster 	sstfq->dir = DIR_EITHER;
    251        1.1     oster 	sstfq->allow_reverse = 1;
    252        1.3     oster 	return ((void *) sstfq);
    253        1.1     oster }
    254        1.1     oster 
    255        1.3     oster void   *
    256       1.14  christos rf_ScanCreate(
    257       1.15  christos 	RF_SectorCount_t sect_per_disk,
    258       1.14  christos 	RF_AllocListElem_t *cl_list,
    259       1.15  christos 	RF_ShutdownList_t **listp)
    260        1.1     oster {
    261        1.1     oster 	RF_Sstf_t *scanq;
    262        1.1     oster 
    263       1.10     oster 	RF_MallocAndAdd(scanq, sizeof(RF_Sstf_t), (RF_Sstf_t *), cl_list);
    264        1.1     oster 	scanq->dir = DIR_RIGHT;
    265        1.1     oster 	scanq->allow_reverse = 1;
    266        1.3     oster 	return ((void *) scanq);
    267        1.1     oster }
    268        1.1     oster 
    269        1.3     oster void   *
    270       1.14  christos rf_CscanCreate(
    271       1.15  christos 	RF_SectorCount_t sect_per_disk,
    272       1.14  christos 	RF_AllocListElem_t *cl_list,
    273       1.15  christos 	RF_ShutdownList_t **listp)
    274        1.1     oster {
    275        1.1     oster 	RF_Sstf_t *cscanq;
    276        1.1     oster 
    277       1.10     oster 	RF_MallocAndAdd(cscanq, sizeof(RF_Sstf_t), (RF_Sstf_t *), cl_list);
    278        1.1     oster 	cscanq->dir = DIR_RIGHT;
    279        1.3     oster 	return ((void *) cscanq);
    280        1.1     oster }
    281        1.1     oster 
    282       1.12     perry void
    283  1.15.68.1       jym rf_SstfEnqueue(void *qptr, RF_DiskQueueData_t *req, int priority)
    284        1.1     oster {
    285        1.1     oster 	RF_Sstf_t *sstfq;
    286        1.1     oster 
    287        1.3     oster 	sstfq = (RF_Sstf_t *) qptr;
    288        1.1     oster 
    289        1.1     oster 	if (priority == RF_IO_LOW_PRIORITY) {
    290        1.9     oster #if RF_DEBUG_QUEUE
    291        1.1     oster 		if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
    292        1.1     oster 			RF_DiskQueue_t *dq;
    293        1.3     oster 			dq = (RF_DiskQueue_t *) req->queue;
    294       1.11     oster 			printf("raid%d: ENQ lopri %d queues are %d,%d,%d\n",
    295        1.4     oster 			       req->raidPtr->raidid,
    296       1.12     perry 			       dq->col,
    297        1.4     oster 			       sstfq->left.qlen, sstfq->right.qlen,
    298        1.4     oster 			       sstfq->lopri.qlen);
    299        1.1     oster 		}
    300        1.9     oster #endif
    301        1.1     oster 		do_sstf_ord_q(&sstfq->lopri.queue, &sstfq->lopri.qtail, req);
    302        1.1     oster 		sstfq->lopri.qlen++;
    303        1.3     oster 	} else {
    304        1.1     oster 		if (req->sectorOffset < sstfq->last_sector) {
    305        1.1     oster 			do_sstf_ord_q(&sstfq->left.queue, &sstfq->left.qtail, req);
    306        1.1     oster 			sstfq->left.qlen++;
    307        1.3     oster 		} else {
    308        1.1     oster 			do_sstf_ord_q(&sstfq->right.queue, &sstfq->right.qtail, req);
    309        1.1     oster 			sstfq->right.qlen++;
    310        1.1     oster 		}
    311        1.1     oster 	}
    312        1.1     oster }
    313        1.1     oster 
    314       1.12     perry static void
    315  1.15.68.1       jym do_dequeue(RF_SstfQ_t *queue, RF_DiskQueueData_t *req)
    316        1.1     oster {
    317        1.3     oster 	RF_DiskQueueData_t *req2;
    318        1.1     oster 
    319        1.9     oster #if RF_DEBUG_QUEUE
    320        1.1     oster 	if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
    321        1.4     oster 		printf("raid%d: do_dequeue\n", req->raidPtr->raidid);
    322        1.1     oster 	}
    323        1.9     oster #endif
    324        1.1     oster 	if (req == queue->queue) {
    325        1.3     oster 		DO_HEAD_DEQ(req2, queue);
    326        1.1     oster 		RF_ASSERT(req2 == req);
    327        1.3     oster 	} else
    328        1.3     oster 		if (req == queue->qtail) {
    329        1.3     oster 			DO_TAIL_DEQ(req2, queue);
    330        1.3     oster 			RF_ASSERT(req2 == req);
    331        1.3     oster 		} else {
    332        1.3     oster 			/* dequeue from middle of list */
    333        1.3     oster 			RF_ASSERT(req->next);
    334        1.3     oster 			RF_ASSERT(req->prev);
    335        1.3     oster 			queue->qlen--;
    336        1.3     oster 			req->next->prev = req->prev;
    337        1.3     oster 			req->prev->next = req->next;
    338        1.3     oster 			req->next = req->prev = NULL;
    339        1.3     oster 		}
    340        1.1     oster }
    341        1.1     oster 
    342        1.3     oster RF_DiskQueueData_t *
    343  1.15.68.1       jym rf_SstfDequeue(void *qptr)
    344        1.1     oster {
    345        1.3     oster 	RF_DiskQueueData_t *req = NULL;
    346        1.1     oster 	RF_Sstf_t *sstfq;
    347        1.1     oster 
    348        1.3     oster 	sstfq = (RF_Sstf_t *) qptr;
    349        1.1     oster 
    350        1.9     oster #if RF_DEBUG_QUEUE
    351        1.1     oster 	if (rf_sstfDebug) {
    352        1.1     oster 		RF_DiskQueue_t *dq;
    353        1.3     oster 		dq = (RF_DiskQueue_t *) req->queue;
    354        1.3     oster 		RF_ASSERT(QSUM(sstfq) == dq->queueLength);
    355       1.11     oster 		printf("raid%d: sstf: Dequeue %d queues are %d,%d,%d\n",
    356       1.12     perry 		       req->raidPtr->raidid, dq->col,
    357        1.4     oster 		       sstfq->left.qlen, sstfq->right.qlen, sstfq->lopri.qlen);
    358        1.1     oster 	}
    359        1.9     oster #endif
    360        1.1     oster 	if (sstfq->left.queue == NULL) {
    361        1.1     oster 		RF_ASSERT(sstfq->left.qlen == 0);
    362        1.1     oster 		if (sstfq->right.queue == NULL) {
    363        1.1     oster 			RF_ASSERT(sstfq->right.qlen == 0);
    364        1.1     oster 			if (sstfq->lopri.queue == NULL) {
    365        1.1     oster 				RF_ASSERT(sstfq->lopri.qlen == 0);
    366        1.3     oster 				return (NULL);
    367        1.1     oster 			}
    368        1.9     oster #if RF_DEBUG_QUEUE
    369        1.1     oster 			if (rf_sstfDebug) {
    370        1.4     oster 				printf("raid%d: sstf: check for close lopri",
    371        1.4     oster 				       req->raidPtr->raidid);
    372        1.1     oster 			}
    373        1.9     oster #endif
    374        1.1     oster 			req = closest_to_arm(&sstfq->lopri, sstfq->last_sector,
    375        1.3     oster 			    &sstfq->dir, sstfq->allow_reverse);
    376        1.9     oster #if RF_DEBUG_QUEUE
    377        1.1     oster 			if (rf_sstfDebug) {
    378        1.4     oster 				printf("raid%d: sstf: closest_to_arm said %lx",
    379        1.4     oster 				       req->raidPtr->raidid, (long) req);
    380        1.1     oster 			}
    381        1.9     oster #endif
    382        1.1     oster 			if (req == NULL)
    383        1.3     oster 				return (NULL);
    384        1.1     oster 			do_dequeue(&sstfq->lopri, req);
    385        1.3     oster 		} else {
    386        1.3     oster 			DO_BEST_DEQ(sstfq->last_sector, req, &sstfq->right);
    387        1.1     oster 		}
    388        1.3     oster 	} else {
    389        1.1     oster 		if (sstfq->right.queue == NULL) {
    390        1.1     oster 			RF_ASSERT(sstfq->right.qlen == 0);
    391        1.3     oster 			DO_BEST_DEQ(sstfq->last_sector, req, &sstfq->left);
    392        1.3     oster 		} else {
    393        1.3     oster 			if (SNUM_DIFF(sstfq->last_sector, sstfq->right.queue->sectorOffset)
    394        1.3     oster 			    < SNUM_DIFF(sstfq->last_sector, sstfq->left.qtail->sectorOffset)) {
    395        1.3     oster 				DO_HEAD_DEQ(req, &sstfq->right);
    396        1.3     oster 			} else {
    397        1.3     oster 				DO_TAIL_DEQ(req, &sstfq->left);
    398        1.1     oster 			}
    399        1.1     oster 		}
    400        1.1     oster 	}
    401        1.1     oster 	RF_ASSERT(req);
    402        1.1     oster 	sstfq->last_sector = req->sectorOffset;
    403        1.3     oster 	return (req);
    404        1.1     oster }
    405        1.1     oster 
    406        1.3     oster RF_DiskQueueData_t *
    407  1.15.68.1       jym rf_ScanDequeue(void *qptr)
    408        1.1     oster {
    409        1.3     oster 	RF_DiskQueueData_t *req = NULL;
    410        1.1     oster 	RF_Sstf_t *scanq;
    411        1.1     oster 
    412        1.3     oster 	scanq = (RF_Sstf_t *) qptr;
    413        1.1     oster 
    414        1.9     oster #if RF_DEBUG_QUEUE
    415        1.1     oster 	if (rf_scanDebug) {
    416        1.1     oster 		RF_DiskQueue_t *dq;
    417        1.3     oster 		dq = (RF_DiskQueue_t *) req->queue;
    418        1.3     oster 		RF_ASSERT(QSUM(scanq) == dq->queueLength);
    419       1.12     perry 		printf("raid%d: scan: Dequeue %d queues are %d,%d,%d\n",
    420       1.12     perry 		       req->raidPtr->raidid, dq->col,
    421        1.4     oster 		       scanq->left.qlen, scanq->right.qlen, scanq->lopri.qlen);
    422        1.1     oster 	}
    423        1.9     oster #endif
    424        1.1     oster 	if (scanq->left.queue == NULL) {
    425        1.1     oster 		RF_ASSERT(scanq->left.qlen == 0);
    426        1.1     oster 		if (scanq->right.queue == NULL) {
    427        1.1     oster 			RF_ASSERT(scanq->right.qlen == 0);
    428        1.1     oster 			if (scanq->lopri.queue == NULL) {
    429        1.1     oster 				RF_ASSERT(scanq->lopri.qlen == 0);
    430        1.3     oster 				return (NULL);
    431        1.1     oster 			}
    432        1.1     oster 			req = closest_to_arm(&scanq->lopri, scanq->last_sector,
    433        1.3     oster 			    &scanq->dir, scanq->allow_reverse);
    434        1.1     oster 			if (req == NULL)
    435        1.3     oster 				return (NULL);
    436        1.1     oster 			do_dequeue(&scanq->lopri, req);
    437        1.3     oster 		} else {
    438        1.1     oster 			scanq->dir = DIR_RIGHT;
    439        1.3     oster 			DO_HEAD_DEQ(req, &scanq->right);
    440        1.1     oster 		}
    441        1.3     oster 	} else
    442        1.3     oster 		if (scanq->right.queue == NULL) {
    443        1.3     oster 			RF_ASSERT(scanq->right.qlen == 0);
    444        1.3     oster 			RF_ASSERT(scanq->left.queue);
    445        1.3     oster 			scanq->dir = DIR_LEFT;
    446        1.3     oster 			DO_TAIL_DEQ(req, &scanq->left);
    447        1.3     oster 		} else {
    448        1.3     oster 			RF_ASSERT(scanq->right.queue);
    449        1.3     oster 			RF_ASSERT(scanq->left.queue);
    450        1.3     oster 			if (scanq->dir == DIR_RIGHT) {
    451        1.3     oster 				DO_HEAD_DEQ(req, &scanq->right);
    452        1.3     oster 			} else {
    453        1.3     oster 				DO_TAIL_DEQ(req, &scanq->left);
    454        1.3     oster 			}
    455        1.1     oster 		}
    456        1.1     oster 	RF_ASSERT(req);
    457        1.1     oster 	scanq->last_sector = req->sectorOffset;
    458        1.3     oster 	return (req);
    459        1.1     oster }
    460        1.1     oster 
    461        1.3     oster RF_DiskQueueData_t *
    462  1.15.68.1       jym rf_CscanDequeue(void *qptr)
    463        1.1     oster {
    464        1.3     oster 	RF_DiskQueueData_t *req = NULL;
    465        1.1     oster 	RF_Sstf_t *cscanq;
    466        1.1     oster 
    467        1.3     oster 	cscanq = (RF_Sstf_t *) qptr;
    468        1.1     oster 
    469        1.1     oster 	RF_ASSERT(cscanq->dir == DIR_RIGHT);
    470        1.9     oster #if RF_DEBUG_QUEUE
    471        1.1     oster 	if (rf_cscanDebug) {
    472        1.1     oster 		RF_DiskQueue_t *dq;
    473        1.3     oster 		dq = (RF_DiskQueue_t *) req->queue;
    474        1.3     oster 		RF_ASSERT(QSUM(cscanq) == dq->queueLength);
    475       1.12     perry 		printf("raid%d: scan: Dequeue %d queues are %d,%d,%d\n",
    476       1.11     oster 		       req->raidPtr->raidid, dq->col,
    477        1.4     oster 		       cscanq->left.qlen, cscanq->right.qlen,
    478        1.4     oster 		       cscanq->lopri.qlen);
    479        1.1     oster 	}
    480        1.9     oster #endif
    481        1.1     oster 	if (cscanq->right.queue) {
    482        1.3     oster 		DO_HEAD_DEQ(req, &cscanq->right);
    483        1.3     oster 	} else {
    484        1.1     oster 		RF_ASSERT(cscanq->right.qlen == 0);
    485        1.1     oster 		if (cscanq->left.queue == NULL) {
    486        1.1     oster 			RF_ASSERT(cscanq->left.qlen == 0);
    487        1.1     oster 			if (cscanq->lopri.queue == NULL) {
    488        1.1     oster 				RF_ASSERT(cscanq->lopri.qlen == 0);
    489        1.3     oster 				return (NULL);
    490        1.1     oster 			}
    491        1.1     oster 			req = closest_to_arm(&cscanq->lopri, cscanq->last_sector,
    492        1.3     oster 			    &cscanq->dir, cscanq->allow_reverse);
    493        1.1     oster 			if (req == NULL)
    494        1.3     oster 				return (NULL);
    495        1.1     oster 			do_dequeue(&cscanq->lopri, req);
    496        1.3     oster 		} else {
    497        1.1     oster 			/*
    498        1.1     oster 			 * There's I/Os to the left of the arm. Swing
    499        1.1     oster 			 * on back (swap queues).
    500        1.1     oster 			 */
    501        1.1     oster 			cscanq->right = cscanq->left;
    502        1.1     oster 			cscanq->left.qlen = 0;
    503        1.1     oster 			cscanq->left.queue = cscanq->left.qtail = NULL;
    504        1.3     oster 			DO_HEAD_DEQ(req, &cscanq->right);
    505        1.1     oster 		}
    506        1.1     oster 	}
    507        1.1     oster 	RF_ASSERT(req);
    508        1.1     oster 	cscanq->last_sector = req->sectorOffset;
    509        1.3     oster 	return (req);
    510        1.1     oster }
    511        1.1     oster 
    512        1.3     oster RF_DiskQueueData_t *
    513  1.15.68.1       jym rf_SstfPeek(void *qptr)
    514        1.1     oster {
    515        1.1     oster 	RF_DiskQueueData_t *req;
    516        1.1     oster 	RF_Sstf_t *sstfq;
    517        1.1     oster 
    518        1.3     oster 	sstfq = (RF_Sstf_t *) qptr;
    519        1.1     oster 
    520        1.1     oster 	if ((sstfq->left.queue == NULL) && (sstfq->right.queue == NULL)) {
    521        1.1     oster 		req = closest_to_arm(&sstfq->lopri, sstfq->last_sector, &sstfq->dir,
    522        1.3     oster 		    sstfq->allow_reverse);
    523        1.3     oster 	} else {
    524        1.1     oster 		if (sstfq->left.queue == NULL)
    525        1.1     oster 			req = sstfq->right.queue;
    526        1.1     oster 		else {
    527        1.1     oster 			if (sstfq->right.queue == NULL)
    528        1.1     oster 				req = sstfq->left.queue;
    529        1.1     oster 			else {
    530        1.3     oster 				if (SNUM_DIFF(sstfq->last_sector, sstfq->right.queue->sectorOffset)
    531        1.3     oster 				    < SNUM_DIFF(sstfq->last_sector, sstfq->left.qtail->sectorOffset)) {
    532        1.1     oster 					req = sstfq->right.queue;
    533        1.3     oster 				} else {
    534        1.1     oster 					req = sstfq->left.qtail;
    535        1.1     oster 				}
    536        1.1     oster 			}
    537        1.1     oster 		}
    538        1.1     oster 	}
    539        1.1     oster 	if (req == NULL) {
    540        1.1     oster 		RF_ASSERT(QSUM(sstfq) == 0);
    541        1.1     oster 	}
    542        1.3     oster 	return (req);
    543        1.1     oster }
    544        1.1     oster 
    545        1.3     oster RF_DiskQueueData_t *
    546  1.15.68.1       jym rf_ScanPeek(void *qptr)
    547        1.1     oster {
    548        1.1     oster 	RF_DiskQueueData_t *req;
    549        1.1     oster 	RF_Sstf_t *scanq;
    550        1.3     oster 	int     dir;
    551        1.1     oster 
    552        1.3     oster 	scanq = (RF_Sstf_t *) qptr;
    553        1.1     oster 	dir = scanq->dir;
    554        1.1     oster 
    555        1.1     oster 	if (scanq->left.queue == NULL) {
    556        1.1     oster 		RF_ASSERT(scanq->left.qlen == 0);
    557        1.1     oster 		if (scanq->right.queue == NULL) {
    558        1.1     oster 			RF_ASSERT(scanq->right.qlen == 0);
    559        1.1     oster 			if (scanq->lopri.queue == NULL) {
    560        1.1     oster 				RF_ASSERT(scanq->lopri.qlen == 0);
    561        1.3     oster 				return (NULL);
    562        1.1     oster 			}
    563        1.1     oster 			req = closest_to_arm(&scanq->lopri, scanq->last_sector,
    564        1.3     oster 			    &dir, scanq->allow_reverse);
    565        1.3     oster 		} else {
    566        1.1     oster 			req = scanq->right.queue;
    567        1.1     oster 		}
    568        1.3     oster 	} else
    569        1.3     oster 		if (scanq->right.queue == NULL) {
    570        1.3     oster 			RF_ASSERT(scanq->right.qlen == 0);
    571        1.3     oster 			RF_ASSERT(scanq->left.queue);
    572        1.1     oster 			req = scanq->left.qtail;
    573        1.3     oster 		} else {
    574        1.3     oster 			RF_ASSERT(scanq->right.queue);
    575        1.3     oster 			RF_ASSERT(scanq->left.queue);
    576        1.3     oster 			if (scanq->dir == DIR_RIGHT) {
    577        1.3     oster 				req = scanq->right.queue;
    578        1.3     oster 			} else {
    579        1.3     oster 				req = scanq->left.qtail;
    580        1.3     oster 			}
    581        1.1     oster 		}
    582        1.1     oster 	if (req == NULL) {
    583        1.1     oster 		RF_ASSERT(QSUM(scanq) == 0);
    584        1.1     oster 	}
    585        1.3     oster 	return (req);
    586        1.1     oster }
    587        1.1     oster 
    588        1.3     oster RF_DiskQueueData_t *
    589  1.15.68.1       jym rf_CscanPeek(void *qptr)
    590        1.1     oster {
    591        1.1     oster 	RF_DiskQueueData_t *req;
    592        1.1     oster 	RF_Sstf_t *cscanq;
    593        1.1     oster 
    594        1.3     oster 	cscanq = (RF_Sstf_t *) qptr;
    595        1.1     oster 
    596        1.1     oster 	RF_ASSERT(cscanq->dir == DIR_RIGHT);
    597        1.1     oster 	if (cscanq->right.queue) {
    598        1.1     oster 		req = cscanq->right.queue;
    599        1.3     oster 	} else {
    600        1.1     oster 		RF_ASSERT(cscanq->right.qlen == 0);
    601        1.1     oster 		if (cscanq->left.queue == NULL) {
    602        1.1     oster 			RF_ASSERT(cscanq->left.qlen == 0);
    603        1.1     oster 			if (cscanq->lopri.queue == NULL) {
    604        1.1     oster 				RF_ASSERT(cscanq->lopri.qlen == 0);
    605        1.3     oster 				return (NULL);
    606        1.1     oster 			}
    607        1.1     oster 			req = closest_to_arm(&cscanq->lopri, cscanq->last_sector,
    608        1.3     oster 			    &cscanq->dir, cscanq->allow_reverse);
    609        1.3     oster 		} else {
    610        1.1     oster 			/*
    611        1.1     oster 			 * There's I/Os to the left of the arm. We'll end
    612        1.1     oster 			 * up swinging on back.
    613        1.1     oster 			 */
    614        1.1     oster 			req = cscanq->left.queue;
    615        1.1     oster 		}
    616        1.1     oster 	}
    617        1.1     oster 	if (req == NULL) {
    618        1.1     oster 		RF_ASSERT(QSUM(cscanq) == 0);
    619        1.1     oster 	}
    620        1.3     oster 	return (req);
    621        1.1     oster }
    622        1.1     oster 
    623       1.12     perry int
    624  1.15.68.1       jym rf_SstfPromote(void *qptr, RF_StripeNum_t parityStripeID, RF_ReconUnitNum_t which_ru)
    625        1.1     oster {
    626        1.1     oster 	RF_DiskQueueData_t *r, *next;
    627        1.1     oster 	RF_Sstf_t *sstfq;
    628        1.3     oster 	int     n;
    629        1.1     oster 
    630        1.3     oster 	sstfq = (RF_Sstf_t *) qptr;
    631        1.1     oster 
    632        1.1     oster 	n = 0;
    633        1.3     oster 	for (r = sstfq->lopri.queue; r; r = next) {
    634        1.1     oster 		next = r->next;
    635        1.9     oster #if RF_DEBUG_QUEUE
    636        1.1     oster 		if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
    637        1.4     oster 			printf("raid%d: check promote %lx\n",
    638        1.4     oster 			       r->raidPtr->raidid, (long) r);
    639        1.1     oster 		}
    640        1.9     oster #endif
    641        1.1     oster 		if ((r->parityStripeID == parityStripeID)
    642        1.3     oster 		    && (r->which_ru == which_ru)) {
    643        1.1     oster 			do_dequeue(&sstfq->lopri, r);
    644        1.1     oster 			rf_SstfEnqueue(qptr, r, RF_IO_NORMAL_PRIORITY);
    645        1.1     oster 			n++;
    646        1.1     oster 		}
    647        1.1     oster 	}
    648        1.9     oster #if RF_DEBUG_QUEUE
    649        1.1     oster 	if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
    650        1.4     oster 		printf("raid%d: promoted %d matching I/Os queues are %d,%d,%d\n",
    651       1.12     perry 		       r->raidPtr->raidid, n, sstfq->left.qlen,
    652        1.4     oster 		       sstfq->right.qlen, sstfq->lopri.qlen);
    653        1.1     oster 	}
    654        1.9     oster #endif
    655        1.3     oster 	return (n);
    656        1.1     oster }
    657