[BACK]Return to rf_sstf.c CVS log [TXT][DIR] Up to [local] / sys / dev / raidframe

Annotation of sys/dev/raidframe/rf_sstf.c, Revision 1.1

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

CVSweb