1 1.18 oster /* $NetBSD: rf_sstf.c,v 1.18 2021/07/23 20:18:24 oster 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.18 oster __KERNEL_RCSID(0, "$NetBSD: rf_sstf.c,v 1.18 2021/07/23 20:18:24 oster 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.16 dsl 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.16 dsl 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.17 christos sstfq = RF_MallocAndAdd(sizeof(*sstfq), 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.17 christos scanq = RF_MallocAndAdd(sizeof(*scanq), 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.17 christos cscanq = RF_MallocAndAdd(sizeof(*cscanq), 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.16 dsl 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.16 dsl 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.16 dsl 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.16 dsl 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.16 dsl 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.12 perry int 513 1.16 dsl rf_SstfPromote(void *qptr, RF_StripeNum_t parityStripeID, RF_ReconUnitNum_t which_ru) 514 1.1 oster { 515 1.1 oster RF_DiskQueueData_t *r, *next; 516 1.1 oster RF_Sstf_t *sstfq; 517 1.3 oster int n; 518 1.1 oster 519 1.3 oster sstfq = (RF_Sstf_t *) qptr; 520 1.1 oster 521 1.1 oster n = 0; 522 1.3 oster for (r = sstfq->lopri.queue; r; r = next) { 523 1.1 oster next = r->next; 524 1.9 oster #if RF_DEBUG_QUEUE 525 1.1 oster if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) { 526 1.4 oster printf("raid%d: check promote %lx\n", 527 1.4 oster r->raidPtr->raidid, (long) r); 528 1.1 oster } 529 1.9 oster #endif 530 1.1 oster if ((r->parityStripeID == parityStripeID) 531 1.3 oster && (r->which_ru == which_ru)) { 532 1.1 oster do_dequeue(&sstfq->lopri, r); 533 1.1 oster rf_SstfEnqueue(qptr, r, RF_IO_NORMAL_PRIORITY); 534 1.1 oster n++; 535 1.1 oster } 536 1.1 oster } 537 1.9 oster #if RF_DEBUG_QUEUE 538 1.1 oster if (rf_sstfDebug || rf_scanDebug || rf_cscanDebug) { 539 1.4 oster printf("raid%d: promoted %d matching I/Os queues are %d,%d,%d\n", 540 1.12 perry r->raidPtr->raidid, n, sstfq->left.qlen, 541 1.4 oster sstfq->right.qlen, sstfq->lopri.qlen); 542 1.1 oster } 543 1.9 oster #endif 544 1.3 oster return (n); 545 1.1 oster } 546