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