rf_sstf.c revision 1.1 1 /* $NetBSD: rf_sstf.c,v 1.1 1998/11/13 04:20:34 oster Exp $ */
2 /*
3 * Copyright (c) 1995 Carnegie-Mellon University.
4 * All rights reserved.
5 *
6 * Author: Jim Zelenka
7 *
8 * Permission to use, copy, modify and distribute this software and
9 * its documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 */
28
29 /*******************************************************************************
30 *
31 * sstf.c -- prioritized shortest seek time first disk queueing code
32 *
33 ******************************************************************************/
34
35 /*
36 * :
37 * Log: rf_sstf.c,v
38 * Revision 1.7 1996/06/19 14:09:56 jimz
39 * SstfPeek wasn't calling closest_to_arm() properly- would bogart
40 * low priority I/Os
41 *
42 * Revision 1.6 1996/06/18 20:53:11 jimz
43 * fix up disk queueing (remove configure routine,
44 * add shutdown list arg to create routines)
45 *
46 * Revision 1.5 1996/06/13 20:42:13 jimz
47 * add scan, cscan
48 *
49 * Revision 1.4 1996/06/07 22:26:27 jimz
50 * type-ify which_ru (RF_ReconUnitNum_t)
51 *
52 * Revision 1.3 1996/06/07 21:33:04 jimz
53 * begin using consistent types for sector numbers,
54 * stripe numbers, row+col numbers, recon unit numbers
55 *
56 * Revision 1.2 1996/06/06 01:11:35 jimz
57 * fixed many priority-related bugs
58 *
59 * Revision 1.1 1996/06/05 19:17:40 jimz
60 * Initial revision
61 *
62 */
63
64 #include "rf_alloclist.h"
65 #include "rf_stripelocks.h"
66 #include "rf_layout.h"
67 #include "rf_diskqueue.h"
68 #include "rf_sstf.h"
69 #include "rf_debugMem.h"
70 #include "rf_general.h"
71 #include "rf_threadid.h"
72 #include "rf_options.h"
73
74 #define DIR_LEFT 1
75 #define DIR_RIGHT 2
76 #define DIR_EITHER 3
77
78 #define SNUM_DIFF(_a_,_b_) (((_a_)>(_b_))?((_a_)-(_b_)):((_b_)-(_a_)))
79
80 #define QSUM(_sstfq_) (((_sstfq_)->lopri.qlen)+((_sstfq_)->left.qlen)+((_sstfq_)->right.qlen))
81
82
83 static void do_sstf_ord_q(RF_DiskQueueData_t **,
84 RF_DiskQueueData_t **,
85 RF_DiskQueueData_t *);
86
87 static RF_DiskQueueData_t *closest_to_arm(RF_SstfQ_t *,
88 RF_SectorNum_t,
89 int *,
90 int);
91 static void do_dequeue(RF_SstfQ_t *, RF_DiskQueueData_t *);
92
93
94 static void do_sstf_ord_q(queuep, tailp, req)
95 RF_DiskQueueData_t **queuep;
96 RF_DiskQueueData_t **tailp;
97 RF_DiskQueueData_t *req;
98 {
99 RF_DiskQueueData_t *r, *s;
100
101 if (*queuep == NULL) {
102 *queuep = req;
103 *tailp = req;
104 req->next = NULL;
105 req->prev = NULL;
106 return;
107 }
108 if (req->sectorOffset <= (*queuep)->sectorOffset) {
109 req->next = *queuep;
110 req->prev = NULL;
111 (*queuep)->prev = req;
112 *queuep = req;
113 return;
114 }
115 if (req->sectorOffset > (*tailp)->sectorOffset) {
116 /* optimization */
117 r = NULL;
118 s = *tailp;
119 goto q_at_end;
120 }
121 for(s=NULL,r=*queuep;r;s=r,r=r->next) {
122 if (r->sectorOffset >= req->sectorOffset) {
123 /* insert after s, before r */
124 RF_ASSERT(s);
125 req->next = r;
126 r->prev = req;
127 s->next = req;
128 req->prev = s;
129 return;
130 }
131 }
132 q_at_end:
133 /* insert after s, at end of queue */
134 RF_ASSERT(r == NULL);
135 RF_ASSERT(s);
136 RF_ASSERT(s == (*tailp));
137 req->next = NULL;
138 req->prev = s;
139 s->next = req;
140 *tailp = req;
141 }
142
143 /* for removing from head-of-queue */
144 #define DO_HEAD_DEQ(_r_,_q_) { \
145 _r_ = (_q_)->queue; \
146 RF_ASSERT((_r_) != NULL); \
147 (_q_)->queue = (_r_)->next; \
148 (_q_)->qlen--; \
149 if ((_q_)->qlen == 0) { \
150 RF_ASSERT((_r_) == (_q_)->qtail); \
151 RF_ASSERT((_q_)->queue == NULL); \
152 (_q_)->qtail = NULL; \
153 } \
154 else { \
155 RF_ASSERT((_q_)->queue->prev == (_r_)); \
156 (_q_)->queue->prev = NULL; \
157 } \
158 }
159
160 /* for removing from end-of-queue */
161 #define DO_TAIL_DEQ(_r_,_q_) { \
162 _r_ = (_q_)->qtail; \
163 RF_ASSERT((_r_) != NULL); \
164 (_q_)->qtail = (_r_)->prev; \
165 (_q_)->qlen--; \
166 if ((_q_)->qlen == 0) { \
167 RF_ASSERT((_r_) == (_q_)->queue); \
168 RF_ASSERT((_q_)->qtail == NULL); \
169 (_q_)->queue = NULL; \
170 } \
171 else { \
172 RF_ASSERT((_q_)->qtail->next == (_r_)); \
173 (_q_)->qtail->next = NULL; \
174 } \
175 }
176
177 #define DO_BEST_DEQ(_l_,_r_,_q_) { \
178 if (SNUM_DIFF((_q_)->queue->sectorOffset,_l_) \
179 < SNUM_DIFF((_q_)->qtail->sectorOffset,_l_)) \
180 { \
181 DO_HEAD_DEQ(_r_,_q_); \
182 } \
183 else { \
184 DO_TAIL_DEQ(_r_,_q_); \
185 } \
186 }
187
188 static RF_DiskQueueData_t *closest_to_arm(queue, arm_pos, dir, allow_reverse)
189 RF_SstfQ_t *queue;
190 RF_SectorNum_t arm_pos;
191 int *dir;
192 int allow_reverse;
193 {
194 RF_SectorNum_t best_pos_l=0, this_pos_l=0, last_pos=0;
195 RF_SectorNum_t best_pos_r=0, this_pos_r=0;
196 RF_DiskQueueData_t *r, *best_l, *best_r;
197
198 best_r = best_l = NULL;
199 for(r=queue->queue;r;r=r->next) {
200 if (r->sectorOffset < arm_pos) {
201 if (best_l == NULL) {
202 best_l = r;
203 last_pos = best_pos_l = this_pos_l;
204 }
205 else {
206 this_pos_l = arm_pos - r->sectorOffset;
207 if (this_pos_l < best_pos_l) {
208 best_l = r;
209 last_pos = best_pos_l = this_pos_l;
210 }
211 else {
212 last_pos = this_pos_l;
213 }
214 }
215 }
216 else {
217 if (best_r == NULL) {
218 best_r = r;
219 last_pos = best_pos_r = this_pos_r;
220 }
221 else {
222 this_pos_r = r->sectorOffset - arm_pos;
223 if (this_pos_r < best_pos_r) {
224 best_r = r;
225 last_pos = best_pos_r = this_pos_r;
226 }
227 else {
228 last_pos = this_pos_r;
229 }
230 if (this_pos_r > last_pos) {
231 /* getting farther away */
232 break;
233 }
234 }
235 }
236 }
237 if ((best_r == NULL) && (best_l == NULL))
238 return(NULL);
239 if ((*dir == DIR_RIGHT) && best_r)
240 return(best_r);
241 if ((*dir == DIR_LEFT) && best_l)
242 return(best_l);
243 if (*dir == DIR_EITHER) {
244 if (best_l == NULL)
245 return(best_r);
246 if (best_r == NULL)
247 return(best_l);
248 if (best_pos_r < best_pos_l)
249 return(best_r);
250 else
251 return(best_l);
252 }
253 /*
254 * Nothing in the direction we want to go. Reverse or
255 * reset the arm. We know we have an I/O in the other
256 * direction.
257 */
258 if (allow_reverse) {
259 if (*dir == DIR_RIGHT) {
260 *dir = DIR_LEFT;
261 return(best_l);
262 }
263 else {
264 *dir = DIR_RIGHT;
265 return(best_r);
266 }
267 }
268 /*
269 * Reset (beginning of queue).
270 */
271 RF_ASSERT(*dir == DIR_RIGHT);
272 return(queue->queue);
273 }
274
275 void *rf_SstfCreate(sect_per_disk, cl_list, listp)
276 RF_SectorCount_t sect_per_disk;
277 RF_AllocListElem_t *cl_list;
278 RF_ShutdownList_t **listp;
279 {
280 RF_Sstf_t *sstfq;
281
282 RF_CallocAndAdd(sstfq, 1, sizeof(RF_Sstf_t), (RF_Sstf_t *), cl_list);
283 sstfq->dir = DIR_EITHER;
284 sstfq->allow_reverse = 1;
285 return((void *)sstfq);
286 }
287
288 void *rf_ScanCreate(sect_per_disk, cl_list, listp)
289 RF_SectorCount_t sect_per_disk;
290 RF_AllocListElem_t *cl_list;
291 RF_ShutdownList_t **listp;
292 {
293 RF_Sstf_t *scanq;
294
295 RF_CallocAndAdd(scanq, 1, sizeof(RF_Sstf_t), (RF_Sstf_t *), cl_list);
296 scanq->dir = DIR_RIGHT;
297 scanq->allow_reverse = 1;
298 return((void *)scanq);
299 }
300
301 void *rf_CscanCreate(sect_per_disk, cl_list, listp)
302 RF_SectorCount_t sect_per_disk;
303 RF_AllocListElem_t *cl_list;
304 RF_ShutdownList_t **listp;
305 {
306 RF_Sstf_t *cscanq;
307
308 RF_CallocAndAdd(cscanq, 1, sizeof(RF_Sstf_t), (RF_Sstf_t *), cl_list);
309 cscanq->dir = DIR_RIGHT;
310 return((void *)cscanq);
311 }
312
313 void rf_SstfEnqueue(qptr, req, priority)
314 void *qptr;
315 RF_DiskQueueData_t *req;
316 int priority;
317 {
318 RF_Sstf_t *sstfq;
319
320 sstfq = (RF_Sstf_t *)qptr;
321
322 if (priority == RF_IO_LOW_PRIORITY) {
323 if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
324 RF_DiskQueue_t *dq;
325 int tid;
326 rf_get_threadid(tid);
327 dq = (RF_DiskQueue_t *)req->queue;
328 printf("[%d] ENQ lopri %d,%d queues are %d,%d,%d\n",
329 tid, dq->row, dq->col, sstfq->left.qlen, sstfq->right.qlen,
330 sstfq->lopri.qlen);
331 }
332 do_sstf_ord_q(&sstfq->lopri.queue, &sstfq->lopri.qtail, req);
333 sstfq->lopri.qlen++;
334 }
335 else {
336 if (req->sectorOffset < sstfq->last_sector) {
337 do_sstf_ord_q(&sstfq->left.queue, &sstfq->left.qtail, req);
338 sstfq->left.qlen++;
339 }
340 else {
341 do_sstf_ord_q(&sstfq->right.queue, &sstfq->right.qtail, req);
342 sstfq->right.qlen++;
343 }
344 }
345 }
346
347 static void do_dequeue(queue, req)
348 RF_SstfQ_t *queue;
349 RF_DiskQueueData_t *req;
350 {
351 RF_DiskQueueData_t *req2;
352
353 if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
354 int tid;
355 rf_get_threadid(tid);
356 printf("[%d] do_dequeue\n", tid);
357 }
358 if (req == queue->queue) {
359 DO_HEAD_DEQ(req2,queue);
360 RF_ASSERT(req2 == req);
361 }
362 else if (req == queue->qtail) {
363 DO_TAIL_DEQ(req2,queue);
364 RF_ASSERT(req2 == req);
365 }
366 else {
367 /* dequeue from middle of list */
368 RF_ASSERT(req->next);
369 RF_ASSERT(req->prev);
370 queue->qlen--;
371 req->next->prev = req->prev;
372 req->prev->next = req->next;
373 req->next = req->prev = NULL;
374 }
375 }
376
377 RF_DiskQueueData_t *rf_SstfDequeue(qptr)
378 void *qptr;
379 {
380 RF_DiskQueueData_t *req=NULL;
381 RF_Sstf_t *sstfq;
382
383 sstfq = (RF_Sstf_t *)qptr;
384
385 if (rf_sstfDebug) {
386 RF_DiskQueue_t *dq;
387 int tid;
388 rf_get_threadid(tid);
389 dq = (RF_DiskQueue_t *)req->queue;
390 RF_ASSERT(QSUM(sstfq)==dq->queueLength);
391 printf("[%d] sstf: Dequeue %d,%d queues are %d,%d,%d\n", tid,
392 dq->row, dq->col, sstfq->left.qlen, sstfq->right.qlen,
393 sstfq->lopri.qlen);
394 }
395 if (sstfq->left.queue == NULL) {
396 RF_ASSERT(sstfq->left.qlen == 0);
397 if (sstfq->right.queue == NULL) {
398 RF_ASSERT(sstfq->right.qlen == 0);
399 if (sstfq->lopri.queue == NULL) {
400 RF_ASSERT(sstfq->lopri.qlen == 0);
401 return(NULL);
402 }
403 if (rf_sstfDebug) {
404 int tid;
405 rf_get_threadid(tid);
406 printf("[%d] sstf: check for close lopri", tid);
407 }
408 req = closest_to_arm(&sstfq->lopri, sstfq->last_sector,
409 &sstfq->dir, sstfq->allow_reverse);
410 if (rf_sstfDebug) {
411 int tid;
412 rf_get_threadid(tid);
413 printf("[%d] sstf: closest_to_arm said %lx", tid, (long)req);
414 }
415 if (req == NULL)
416 return(NULL);
417 do_dequeue(&sstfq->lopri, req);
418 }
419 else {
420 DO_BEST_DEQ(sstfq->last_sector,req,&sstfq->right);
421 }
422 }
423 else {
424 if (sstfq->right.queue == NULL) {
425 RF_ASSERT(sstfq->right.qlen == 0);
426 DO_BEST_DEQ(sstfq->last_sector,req,&sstfq->left);
427 }
428 else {
429 if (SNUM_DIFF(sstfq->last_sector,sstfq->right.queue->sectorOffset)
430 < SNUM_DIFF(sstfq->last_sector,sstfq->left.qtail->sectorOffset))
431 {
432 DO_HEAD_DEQ(req,&sstfq->right);
433 }
434 else {
435 DO_TAIL_DEQ(req,&sstfq->left);
436 }
437 }
438 }
439 RF_ASSERT(req);
440 sstfq->last_sector = req->sectorOffset;
441 return(req);
442 }
443
444 RF_DiskQueueData_t *rf_ScanDequeue(qptr)
445 void *qptr;
446 {
447 RF_DiskQueueData_t *req=NULL;
448 RF_Sstf_t *scanq;
449
450 scanq = (RF_Sstf_t *)qptr;
451
452 if (rf_scanDebug) {
453 RF_DiskQueue_t *dq;
454 int tid;
455 rf_get_threadid(tid);
456 dq = (RF_DiskQueue_t *)req->queue;
457 RF_ASSERT(QSUM(scanq)==dq->queueLength);
458 printf("[%d] scan: Dequeue %d,%d queues are %d,%d,%d\n", tid,
459 dq->row, dq->col, scanq->left.qlen, scanq->right.qlen,
460 scanq->lopri.qlen);
461 }
462 if (scanq->left.queue == NULL) {
463 RF_ASSERT(scanq->left.qlen == 0);
464 if (scanq->right.queue == NULL) {
465 RF_ASSERT(scanq->right.qlen == 0);
466 if (scanq->lopri.queue == NULL) {
467 RF_ASSERT(scanq->lopri.qlen == 0);
468 return(NULL);
469 }
470 req = closest_to_arm(&scanq->lopri, scanq->last_sector,
471 &scanq->dir, scanq->allow_reverse);
472 if (req == NULL)
473 return(NULL);
474 do_dequeue(&scanq->lopri, req);
475 }
476 else {
477 scanq->dir = DIR_RIGHT;
478 DO_HEAD_DEQ(req,&scanq->right);
479 }
480 }
481 else if (scanq->right.queue == NULL) {
482 RF_ASSERT(scanq->right.qlen == 0);
483 RF_ASSERT(scanq->left.queue);
484 scanq->dir = DIR_LEFT;
485 DO_TAIL_DEQ(req,&scanq->left);
486 }
487 else {
488 RF_ASSERT(scanq->right.queue);
489 RF_ASSERT(scanq->left.queue);
490 if (scanq->dir == DIR_RIGHT) {
491 DO_HEAD_DEQ(req,&scanq->right);
492 }
493 else {
494 DO_TAIL_DEQ(req,&scanq->left);
495 }
496 }
497 RF_ASSERT(req);
498 scanq->last_sector = req->sectorOffset;
499 return(req);
500 }
501
502 RF_DiskQueueData_t *rf_CscanDequeue(qptr)
503 void *qptr;
504 {
505 RF_DiskQueueData_t *req=NULL;
506 RF_Sstf_t *cscanq;
507
508 cscanq = (RF_Sstf_t *)qptr;
509
510 RF_ASSERT(cscanq->dir == DIR_RIGHT);
511 if (rf_cscanDebug) {
512 RF_DiskQueue_t *dq;
513 int tid;
514 rf_get_threadid(tid);
515 dq = (RF_DiskQueue_t *)req->queue;
516 RF_ASSERT(QSUM(cscanq)==dq->queueLength);
517 printf("[%d] scan: Dequeue %d,%d queues are %d,%d,%d\n", tid,
518 dq->row, dq->col, cscanq->left.qlen, cscanq->right.qlen,
519 cscanq->lopri.qlen);
520 }
521 if (cscanq->right.queue) {
522 DO_HEAD_DEQ(req,&cscanq->right);
523 }
524 else {
525 RF_ASSERT(cscanq->right.qlen == 0);
526 if (cscanq->left.queue == NULL) {
527 RF_ASSERT(cscanq->left.qlen == 0);
528 if (cscanq->lopri.queue == NULL) {
529 RF_ASSERT(cscanq->lopri.qlen == 0);
530 return(NULL);
531 }
532 req = closest_to_arm(&cscanq->lopri, cscanq->last_sector,
533 &cscanq->dir, cscanq->allow_reverse);
534 if (req == NULL)
535 return(NULL);
536 do_dequeue(&cscanq->lopri, req);
537 }
538 else {
539 /*
540 * There's I/Os to the left of the arm. Swing
541 * on back (swap queues).
542 */
543 cscanq->right = cscanq->left;
544 cscanq->left.qlen = 0;
545 cscanq->left.queue = cscanq->left.qtail = NULL;
546 DO_HEAD_DEQ(req,&cscanq->right);
547 }
548 }
549 RF_ASSERT(req);
550 cscanq->last_sector = req->sectorOffset;
551 return(req);
552 }
553
554 RF_DiskQueueData_t *rf_SstfPeek(qptr)
555 void *qptr;
556 {
557 RF_DiskQueueData_t *req;
558 RF_Sstf_t *sstfq;
559
560 sstfq = (RF_Sstf_t *)qptr;
561
562 if ((sstfq->left.queue == NULL) && (sstfq->right.queue == NULL)) {
563 req = closest_to_arm(&sstfq->lopri, sstfq->last_sector, &sstfq->dir,
564 sstfq->allow_reverse);
565 }
566 else {
567 if (sstfq->left.queue == NULL)
568 req = sstfq->right.queue;
569 else {
570 if (sstfq->right.queue == NULL)
571 req = sstfq->left.queue;
572 else {
573 if (SNUM_DIFF(sstfq->last_sector,sstfq->right.queue->sectorOffset)
574 <SNUM_DIFF(sstfq->last_sector,sstfq->left.qtail->sectorOffset))
575 {
576 req = sstfq->right.queue;
577 }
578 else {
579 req = sstfq->left.qtail;
580 }
581 }
582 }
583 }
584 if (req == NULL) {
585 RF_ASSERT(QSUM(sstfq) == 0);
586 }
587 return(req);
588 }
589
590 RF_DiskQueueData_t *rf_ScanPeek(qptr)
591 void *qptr;
592 {
593 RF_DiskQueueData_t *req;
594 RF_Sstf_t *scanq;
595 int dir;
596
597 scanq = (RF_Sstf_t *)qptr;
598 dir = scanq->dir;
599
600 if (scanq->left.queue == NULL) {
601 RF_ASSERT(scanq->left.qlen == 0);
602 if (scanq->right.queue == NULL) {
603 RF_ASSERT(scanq->right.qlen == 0);
604 if (scanq->lopri.queue == NULL) {
605 RF_ASSERT(scanq->lopri.qlen == 0);
606 return(NULL);
607 }
608 req = closest_to_arm(&scanq->lopri, scanq->last_sector,
609 &dir, scanq->allow_reverse);
610 }
611 else {
612 req = scanq->right.queue;
613 }
614 }
615 else if (scanq->right.queue == NULL) {
616 RF_ASSERT(scanq->right.qlen == 0);
617 RF_ASSERT(scanq->left.queue);
618 req = scanq->left.qtail;
619 }
620 else {
621 RF_ASSERT(scanq->right.queue);
622 RF_ASSERT(scanq->left.queue);
623 if (scanq->dir == DIR_RIGHT) {
624 req = scanq->right.queue;
625 }
626 else {
627 req = scanq->left.qtail;
628 }
629 }
630 if (req == NULL) {
631 RF_ASSERT(QSUM(scanq) == 0);
632 }
633 return(req);
634 }
635
636 RF_DiskQueueData_t *rf_CscanPeek(qptr)
637 void *qptr;
638 {
639 RF_DiskQueueData_t *req;
640 RF_Sstf_t *cscanq;
641
642 cscanq = (RF_Sstf_t *)qptr;
643
644 RF_ASSERT(cscanq->dir == DIR_RIGHT);
645 if (cscanq->right.queue) {
646 req = cscanq->right.queue;
647 }
648 else {
649 RF_ASSERT(cscanq->right.qlen == 0);
650 if (cscanq->left.queue == NULL) {
651 RF_ASSERT(cscanq->left.qlen == 0);
652 if (cscanq->lopri.queue == NULL) {
653 RF_ASSERT(cscanq->lopri.qlen == 0);
654 return(NULL);
655 }
656 req = closest_to_arm(&cscanq->lopri, cscanq->last_sector,
657 &cscanq->dir, cscanq->allow_reverse);
658 }
659 else {
660 /*
661 * There's I/Os to the left of the arm. We'll end
662 * up swinging on back.
663 */
664 req = cscanq->left.queue;
665 }
666 }
667 if (req == NULL) {
668 RF_ASSERT(QSUM(cscanq) == 0);
669 }
670 return(req);
671 }
672
673 int rf_SstfPromote(qptr, parityStripeID, which_ru)
674 void *qptr;
675 RF_StripeNum_t parityStripeID;
676 RF_ReconUnitNum_t which_ru;
677 {
678 RF_DiskQueueData_t *r, *next;
679 RF_Sstf_t *sstfq;
680 int n;
681
682 sstfq = (RF_Sstf_t *)qptr;
683
684 n = 0;
685 if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
686 int tid;
687 rf_get_threadid(tid);
688 printf("[%d] promote %ld %d queues are %d,%d,%d\n",
689 tid, (long)parityStripeID, (int)which_ru,
690 sstfq->left.qlen,
691 sstfq->right.qlen,
692 sstfq->lopri.qlen);
693 }
694 for(r=sstfq->lopri.queue;r;r=next) {
695 next = r->next;
696 if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
697 int tid;
698 rf_get_threadid(tid);
699 printf("[%d] check promote %lx\n", tid, (long)r);
700 }
701 if ((r->parityStripeID == parityStripeID)
702 && (r->which_ru == which_ru))
703 {
704 do_dequeue(&sstfq->lopri, r);
705 rf_SstfEnqueue(qptr, r, RF_IO_NORMAL_PRIORITY);
706 n++;
707 }
708 }
709 if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) {
710 int tid;
711 rf_get_threadid(tid);
712 printf("[%d] promoted %d matching I/Os queues are %d,%d,%d\n",
713 tid, n, sstfq->left.qlen, sstfq->right.qlen, sstfq->lopri.qlen);
714 }
715 return(n);
716 }
717