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

Annotation of sys/dev/raidframe/rf_cvscan.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: rf_cvscan.c,v 1.5 2002/12/16 07:01:03 tdeval Exp $    */
                      2: /*     $NetBSD: rf_cvscan.c,v 1.5 1999/08/13 03:41:53 oster Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1995 Carnegie-Mellon University.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Author: Mark Holland
                      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:  * cvscan.c --  prioritized cvscan disk queueing code.
                     34:  *
                     35:  * Nov 9, 1994, adapted from raidSim version (MCH)
                     36:  *
                     37:  *****************************************************************************/
                     38:
                     39: #include "rf_types.h"
                     40: #include "rf_alloclist.h"
                     41: #include "rf_stripelocks.h"
                     42: #include "rf_layout.h"
                     43: #include "rf_diskqueue.h"
                     44: #include "rf_cvscan.h"
                     45: #include "rf_debugMem.h"
                     46: #include "rf_general.h"
                     47:
                     48: void rf_CheckCvscanState(RF_CvscanHeader_t *, char *, int);
                     49: void rf_PriorityInsert(RF_DiskQueueData_t **, RF_DiskQueueData_t *);
                     50: void rf_ReqInsert(RF_DiskQueueData_t **, RF_DiskQueueData_t *,
                     51:        RF_CvscanArmDir_t);
                     52: RF_DiskQueueData_t *rf_ReqDequeue(RF_DiskQueueData_t **);
                     53: void rf_ReBalance(RF_CvscanHeader_t *);
                     54: void rf_Transfer(RF_DiskQueueData_t **, RF_DiskQueueData_t **);
                     55: void rf_RealEnqueue(RF_CvscanHeader_t *, RF_DiskQueueData_t *);
                     56:
                     57: #define        DO_CHECK_STATE(_hdr_)   rf_CheckCvscanState((_hdr_), __FILE__, __LINE__)
                     58:
                     59: #define        pri_ok(p)       (((p) == RF_IO_NORMAL_PRIORITY) ||              \
                     60:                         ((p) == RF_IO_LOW_PRIORITY))
                     61:
                     62:
                     63: void
                     64: rf_CheckCvscanState(RF_CvscanHeader_t *hdr, char *file, int line)
                     65: {
                     66:        long i, key;
                     67:        RF_DiskQueueData_t *tmp;
                     68:
                     69:        if (hdr->left != (RF_DiskQueueData_t *) NULL)
                     70:                RF_ASSERT(hdr->left->sectorOffset < hdr->cur_block);
                     71:        for (key = hdr->cur_block, i = 0, tmp = hdr->left;
                     72:             tmp != (RF_DiskQueueData_t *) NULL;
                     73:             key = tmp->sectorOffset, i++, tmp = tmp->next)
                     74:                RF_ASSERT(tmp->sectorOffset <= key
                     75:                    && tmp->priority == hdr->nxt_priority &&
                     76:                    pri_ok(tmp->priority));
                     77:        RF_ASSERT(i == hdr->left_cnt);
                     78:
                     79:        for (key = hdr->cur_block, i = 0, tmp = hdr->right;
                     80:             tmp != (RF_DiskQueueData_t *) NULL;
                     81:             key = tmp->sectorOffset, i++, tmp = tmp->next) {
                     82:                RF_ASSERT(key <= tmp->sectorOffset);
                     83:                RF_ASSERT(tmp->priority == hdr->nxt_priority);
                     84:                RF_ASSERT(pri_ok(tmp->priority));
                     85:        }
                     86:        RF_ASSERT(i == hdr->right_cnt);
                     87:
                     88:        for (key = hdr->nxt_priority - 1, tmp = hdr->burner;
                     89:             tmp != (RF_DiskQueueData_t *) NULL;
                     90:             key = tmp->priority, tmp = tmp->next) {
                     91:                RF_ASSERT(tmp);
                     92:                RF_ASSERT(hdr);
                     93:                RF_ASSERT(pri_ok(tmp->priority));
                     94:                RF_ASSERT(key >= tmp->priority);
                     95:                RF_ASSERT(tmp->priority < hdr->nxt_priority);
                     96:        }
                     97: }
                     98:
                     99:
                    100: void
                    101: rf_PriorityInsert(RF_DiskQueueData_t **list_ptr, RF_DiskQueueData_t *req)
                    102: {
                    103:        /*
                    104:         * Insert block pointed to by req into list whose first entry is
                    105:         * pointed to by the pointer that list_ptr points to.
                    106:         * i.e. list_ptr is a grandparent of the first entry.
                    107:         */
                    108:
                    109:        for (; (*list_ptr) != (RF_DiskQueueData_t *) NULL &&
                    110:               (*list_ptr)->priority > req->priority;
                    111:             list_ptr = &((*list_ptr)->next)) {
                    112:        }
                    113:        req->next = (*list_ptr);
                    114:        (*list_ptr) = req;
                    115: }
                    116:
                    117:
                    118: void
                    119: rf_ReqInsert(RF_DiskQueueData_t **list_ptr, RF_DiskQueueData_t *req,
                    120:     RF_CvscanArmDir_t order)
                    121: {
                    122:        /*
                    123:         * Insert block pointed to by req into list whose first entry is
                    124:         * pointed to by the pointer that list_ptr points to.
                    125:         * i.e. list_ptr is a grandparent of the first entry.
                    126:         */
                    127:
                    128:        for (; (*list_ptr) != (RF_DiskQueueData_t *) NULL &&
                    129:               ((order == rf_cvscan_RIGHT && (*list_ptr)->sectorOffset <=
                    130:               req->sectorOffset) || (order == rf_cvscan_LEFT &&
                    131:               (*list_ptr)->sectorOffset > req->sectorOffset));
                    132:             list_ptr = &((*list_ptr)->next)) {
                    133:        }
                    134:        req->next = (*list_ptr);
                    135:        (*list_ptr) = req;
                    136: }
                    137:
                    138:
                    139: RF_DiskQueueData_t *
                    140: rf_ReqDequeue(RF_DiskQueueData_t **list_ptr)
                    141: {
                    142:        RF_DiskQueueData_t *ret = (*list_ptr);
                    143:        if ((*list_ptr) != (RF_DiskQueueData_t *) NULL) {
                    144:                (*list_ptr) = (*list_ptr)->next;
                    145:        }
                    146:        return (ret);
                    147: }
                    148:
                    149:
                    150: void
                    151: rf_ReBalance(RF_CvscanHeader_t *hdr)
                    152: {
                    153:        /* DO_CHECK_STATE(hdr); */
                    154:        while (hdr->right != (RF_DiskQueueData_t *) NULL
                    155:            && hdr->right->sectorOffset < hdr->cur_block) {
                    156:                hdr->right_cnt--;
                    157:                hdr->left_cnt++;
                    158:                rf_ReqInsert(&hdr->left, rf_ReqDequeue(&hdr->right),
                    159:                    rf_cvscan_LEFT);
                    160:        }
                    161:        /* DO_CHECK_STATE(hdr); */
                    162: }
                    163:
                    164:
                    165: void
                    166: rf_Transfer(RF_DiskQueueData_t **to_list_ptr, RF_DiskQueueData_t **from_list_ptr)
                    167: {
                    168:        RF_DiskQueueData_t *gp;
                    169:        for (gp = (*from_list_ptr); gp != (RF_DiskQueueData_t *) NULL;) {
                    170:                RF_DiskQueueData_t *p = gp->next;
                    171:                rf_PriorityInsert(to_list_ptr, gp);
                    172:                gp = p;
                    173:        }
                    174:        (*from_list_ptr) = (RF_DiskQueueData_t *) NULL;
                    175: }
                    176:
                    177:
                    178: void
                    179: rf_RealEnqueue(RF_CvscanHeader_t *hdr, RF_DiskQueueData_t *req)
                    180: {
                    181:        RF_ASSERT(req->priority == RF_IO_NORMAL_PRIORITY ||
                    182:            req->priority == RF_IO_LOW_PRIORITY);
                    183:
                    184:        DO_CHECK_STATE(hdr);
                    185:        if (hdr->left_cnt == 0 && hdr->right_cnt == 0) {
                    186:                hdr->nxt_priority = req->priority;
                    187:        }
                    188:        if (req->priority > hdr->nxt_priority) {
                    189:                /*
                    190:                 * Dump all other outstanding requests on the back burner.
                    191:                 */
                    192:                rf_Transfer(&hdr->burner, &hdr->left);
                    193:                rf_Transfer(&hdr->burner, &hdr->right);
                    194:                hdr->left_cnt = 0;
                    195:                hdr->right_cnt = 0;
                    196:                hdr->nxt_priority = req->priority;
                    197:        }
                    198:        if (req->priority < hdr->nxt_priority) {
                    199:                /*
                    200:                 * Yet another low priority task !
                    201:                 */
                    202:                rf_PriorityInsert(&hdr->burner, req);
                    203:        } else {
                    204:                if (req->sectorOffset < hdr->cur_block) {
                    205:                        /* This request is to the left of the current arms. */
                    206:                        rf_ReqInsert(&hdr->left, req, rf_cvscan_LEFT);
                    207:                        hdr->left_cnt++;
                    208:                } else {
                    209:                        /* This request is to the right of the current arms. */
                    210:                        rf_ReqInsert(&hdr->right, req, rf_cvscan_RIGHT);
                    211:                        hdr->right_cnt++;
                    212:                }
                    213:        }
                    214:        DO_CHECK_STATE(hdr);
                    215: }
                    216:
                    217:
                    218: void
                    219: rf_CvscanEnqueue(void *q_in, RF_DiskQueueData_t *elem, int priority)
                    220: {
                    221:        RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
                    222:        rf_RealEnqueue(hdr, elem /* req */ );
                    223: }
                    224:
                    225:
                    226: RF_DiskQueueData_t *
                    227: rf_CvscanDequeue(void *q_in)
                    228: {
                    229:        RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
                    230:        long    range, i, sum_dist_left, sum_dist_right;
                    231:        RF_DiskQueueData_t *ret;
                    232:        RF_DiskQueueData_t *tmp;
                    233:
                    234:        DO_CHECK_STATE(hdr);
                    235:
                    236:        if (hdr->left_cnt == 0 && hdr->right_cnt == 0)
                    237:                return ((RF_DiskQueueData_t *) NULL);
                    238:
                    239:        range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt,
                    240:            hdr->right_cnt));
                    241:        for (i = 0, tmp = hdr->left, sum_dist_left =
                    242:             ((hdr->direction == rf_cvscan_RIGHT) ?
                    243:              range * hdr->change_penalty : 0);
                    244:             tmp != (RF_DiskQueueData_t *) NULL && i < range;
                    245:             tmp = tmp->next, i++) {
                    246:                sum_dist_left += hdr->cur_block - tmp->sectorOffset;
                    247:        }
                    248:        for (i = 0, tmp = hdr->right, sum_dist_right =
                    249:             ((hdr->direction == rf_cvscan_LEFT) ?
                    250:              range * hdr->change_penalty : 0);
                    251:             tmp != (RF_DiskQueueData_t *) NULL && i < range;
                    252:             tmp = tmp->next, i++) {
                    253:                sum_dist_right += tmp->sectorOffset - hdr->cur_block;
                    254:        }
                    255:
                    256:        if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right) {
                    257:                hdr->direction = rf_cvscan_LEFT;
                    258:                hdr->cur_block = hdr->left->sectorOffset + hdr->left->numSector;
                    259:                hdr->left_cnt = RF_MAX(hdr->left_cnt - 1, 0);
                    260:                tmp = hdr->left;
                    261:                ret = (rf_ReqDequeue(&hdr->left)) /*->parent*/ ;
                    262:        } else {
                    263:                hdr->direction = rf_cvscan_RIGHT;
                    264:                hdr->cur_block = hdr->right->sectorOffset +
                    265:                    hdr->right->numSector;
                    266:                hdr->right_cnt = RF_MAX(hdr->right_cnt - 1, 0);
                    267:                tmp = hdr->right;
                    268:                ret = (rf_ReqDequeue(&hdr->right)) /*->parent*/ ;
                    269:        }
                    270:        rf_ReBalance(hdr);
                    271:
                    272:        if (hdr->left_cnt == 0 && hdr->right_cnt == 0
                    273:            && hdr->burner != (RF_DiskQueueData_t *) NULL) {
                    274:                /*
                    275:                 * Restore low priority requests for next dequeue.
                    276:                 */
                    277:                RF_DiskQueueData_t *burner = hdr->burner;
                    278:                hdr->nxt_priority = burner->priority;
                    279:                while (burner != (RF_DiskQueueData_t *) NULL &&
                    280:                    burner->priority == hdr->nxt_priority) {
                    281:                        RF_DiskQueueData_t *next = burner->next;
                    282:                        rf_RealEnqueue(hdr, burner);
                    283:                        burner = next;
                    284:                }
                    285:                hdr->burner = burner;
                    286:        }
                    287:        DO_CHECK_STATE(hdr);
                    288:        return (ret);
                    289: }
                    290:
                    291:
                    292: RF_DiskQueueData_t *
                    293: rf_CvscanPeek(void *q_in)
                    294: {
                    295:        RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
                    296:        long    range, i, sum_dist_left, sum_dist_right;
                    297:        RF_DiskQueueData_t *tmp, *headElement;
                    298:
                    299:        DO_CHECK_STATE(hdr);
                    300:
                    301:        if (hdr->left_cnt == 0 && hdr->right_cnt == 0)
                    302:                headElement = NULL;
                    303:        else {
                    304:                range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt,
                    305:                    hdr->right_cnt));
                    306:                for (i = 0, tmp = hdr->left, sum_dist_left =
                    307:                     ((hdr->direction == rf_cvscan_RIGHT) ?
                    308:                      range * hdr->change_penalty : 0);
                    309:                     tmp != (RF_DiskQueueData_t *) NULL && i < range;
                    310:                     tmp = tmp->next, i++) {
                    311:                        sum_dist_left += hdr->cur_block - tmp->sectorOffset;
                    312:                }
                    313:                for (i = 0, tmp = hdr->right, sum_dist_right =
                    314:                     ((hdr->direction == rf_cvscan_LEFT) ?
                    315:                      range * hdr->change_penalty : 0);
                    316:                     tmp != (RF_DiskQueueData_t *) NULL && i < range;
                    317:                     tmp = tmp->next, i++) {
                    318:                        sum_dist_right += tmp->sectorOffset - hdr->cur_block;
                    319:                }
                    320:
                    321:                if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right)
                    322:                        headElement = hdr->left;
                    323:                else
                    324:                        headElement = hdr->right;
                    325:        }
                    326:        return (headElement);
                    327: }
                    328:
                    329:
                    330: /*
                    331:  * CVSCAN( 1, 0 ) is Shortest Seek Time First (SSTF)
                    332:  *                             lowest average response time
                    333:  * CVSCAN( 1, infinity ) is SCAN
                    334:  *                             lowest response time standard deviation
                    335:  */
                    336:
                    337:
                    338: int
                    339: rf_CvscanConfigure(void)
                    340: {
                    341:        return (0);
                    342: }
                    343:
                    344:
                    345: void   *
                    346: rf_CvscanCreate(RF_SectorCount_t sectPerDisk, RF_AllocListElem_t *clList,
                    347:     RF_ShutdownList_t **listp)
                    348: {
                    349:        RF_CvscanHeader_t *hdr;
                    350:        long range = 2;         /* Currently no mechanism to change these. */
                    351:        long penalty = sectPerDisk / 5;
                    352:
                    353:        RF_MallocAndAdd(hdr, sizeof(RF_CvscanHeader_t), (RF_CvscanHeader_t *),
                    354:            clList);
                    355:        bzero((char *) hdr, sizeof(RF_CvscanHeader_t));
                    356:        hdr->range_for_avg = RF_MAX(range, 1);
                    357:        hdr->change_penalty = RF_MAX(penalty, 0);
                    358:        hdr->direction = rf_cvscan_RIGHT;
                    359:        hdr->cur_block = 0;
                    360:        hdr->left_cnt = hdr->right_cnt = 0;
                    361:        hdr->left = hdr->right = (RF_DiskQueueData_t *) NULL;
                    362:        hdr->burner = (RF_DiskQueueData_t *) NULL;
                    363:        DO_CHECK_STATE(hdr);
                    364:
                    365:        return ((void *) hdr);
                    366: }
                    367:
                    368:
                    369: #if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(_KERNEL)
                    370: /* rf_PrintCvscanQueue is not used, so we ignore it... */
                    371: #else
                    372: void
                    373: rf_PrintCvscanQueue(RF_CvscanHeader_t *hdr)
                    374: {
                    375:        RF_DiskQueueData_t *tmp;
                    376:
                    377:        printf("CVSCAN(%d,%d) at %d going %s\n",
                    378:            (int) hdr->range_for_avg,
                    379:            (int) hdr->change_penalty,
                    380:            (int) hdr->cur_block,
                    381:            (hdr->direction == rf_cvscan_LEFT) ? "LEFT" : "RIGHT");
                    382:        printf("\tLeft(%d): ", hdr->left_cnt);
                    383:        for (tmp = hdr->left; tmp != (RF_DiskQueueData_t *) NULL;
                    384:             tmp = tmp->next)
                    385:                printf("(%d,%ld,%d) ",
                    386:                    (int) tmp->sectorOffset,
                    387:                    (long) (tmp->sectorOffset + tmp->numSector),
                    388:                    tmp->priority);
                    389:        printf("\n");
                    390:        printf("\tRight(%d): ", hdr->right_cnt);
                    391:        for (tmp = hdr->right; tmp != (RF_DiskQueueData_t *) NULL;
                    392:             tmp = tmp->next)
                    393:                printf("(%d,%ld,%d) ",
                    394:                    (int) tmp->sectorOffset,
                    395:                    (long) (tmp->sectorOffset + tmp->numSector),
                    396:                    tmp->priority);
                    397:        printf("\n");
                    398:        printf("\tBurner: ");
                    399:        for (tmp = hdr->burner; tmp != (RF_DiskQueueData_t *) NULL;
                    400:             tmp = tmp->next)
                    401:                printf("(%d,%ld,%d) ",
                    402:                    (int) tmp->sectorOffset,
                    403:                    (long) (tmp->sectorOffset + tmp->numSector),
                    404:                    tmp->priority);
                    405:        printf("\n");
                    406: }
                    407: #endif
                    408:
                    409:
                    410: /*
                    411:  * Promote reconstruction accesses for the given stripeID to normal priority.
                    412:  * Return 1 if an access was found and zero otherwise.
                    413:  * Normally, we should only have one or zero entries in the burner queue,
                    414:  * so execution time should be short.
                    415:  */
                    416: int
                    417: rf_CvscanPromote(void *q_in, RF_StripeNum_t parityStripeID,
                    418:     RF_ReconUnitNum_t which_ru)
                    419: {
                    420:        RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
                    421:        RF_DiskQueueData_t *trailer = NULL, *tmp = hdr->burner, *tlist = NULL;
                    422:        int retval = 0;
                    423:
                    424:        DO_CHECK_STATE(hdr);
                    425:        while (tmp) {           /* Handle entries at the front of the list. */
                    426:                if (tmp->parityStripeID == parityStripeID &&
                    427:                    tmp->which_ru == which_ru) {
                    428:                        hdr->burner = tmp->next;
                    429:                        tmp->priority = RF_IO_NORMAL_PRIORITY;
                    430:                        tmp->next = tlist;
                    431:                        tlist = tmp;
                    432:                        tmp = hdr->burner;
                    433:                } else
                    434:                        break;
                    435:        }
                    436:        if (tmp) {
                    437:                trailer = tmp;
                    438:                tmp = tmp->next;
                    439:        }
                    440:        while (tmp) {           /* Handle entries on the rest of the list. */
                    441:                if (tmp->parityStripeID == parityStripeID &&
                    442:                    tmp->which_ru == which_ru) {
                    443:                        trailer->next = tmp->next;
                    444:                        tmp->priority = RF_IO_NORMAL_PRIORITY;
                    445:                        tmp->next = tlist;
                    446:                        tlist = tmp;    /* Insert on a temp queue. */
                    447:                        tmp = trailer->next;
                    448:                } else {
                    449:                        trailer = tmp;
                    450:                        tmp = tmp->next;
                    451:                }
                    452:        }
                    453:        while (tlist) {
                    454:                retval++;
                    455:                tmp = tlist->next;
                    456:                rf_RealEnqueue(hdr, tlist);
                    457:                tlist = tmp;
                    458:        }
                    459:        RF_ASSERT(retval == 0 || retval == 1);
                    460:        DO_CHECK_STATE((RF_CvscanHeader_t *) q_in);
                    461:        return (retval);
                    462: }

CVSweb