⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cache.c

📁 be文件系统实现的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
static voidrelease_iovec_array(struct iovec *iov){    int i;    LOCK(iovec_lock);    for(i=0; i < MAX_IOVECS; i++) {        if (iov == iovec_pool[i])            break;    }    if (i < MAX_IOVECS)        iovec_used[i] = 0;    else                     /* uh-oh */        printf("cache: released an iovec I don't own (iov 0x%x)\n", iov);        UNLOCK(iovec_lock);}static voidreal_dump_cache_list(cache_ent_list *cel){    cache_ent *ce;        kprintf("starting from LRU end:\n");    for(ce=cel->lru; ce; ce=ce->next) {        kprintf("ce 0x%.8lx dev %2d bnum %6ld lock %d flag %d arg 0x%.8lx "               "clone 0x%.8lx\n", (ulong)ce, ce->dev, ce->block_num,ce->lock,               ce->flags, (ulong)ce->arg, (ulong)ce->clone);    }    kprintf("MRU end\n");}static voiddump_cache_list(void){    kprintf("NORMAL BLOCKS\n");    real_dump_cache_list(&bc.normal);    kprintf("LOCKED BLOCKS\n");    real_dump_cache_list(&bc.locked);    kprintf("cur blocks %d, max blocks %d ht @ 0x%lx\n", bc.cur_blocks,           bc.max_blocks, (ulong)&bc.ht);}static voidcheck_bcache(char *str){    int count = 0;    cache_ent *ce, *prev = NULL;    LOCK(bc.lock);    for(ce=bc.normal.lru; ce; prev=ce, ce=ce->next) {        count++;    }    for(ce=bc.locked.lru; ce; prev=ce, ce=ce->next) {        count++;    }    if (count != bc.cur_blocks) {        if (count < bc.cur_blocks - 16)            panic("%s: count == %d, cur_blocks %d, prev 0x%x\n",                    str, count, bc.cur_blocks, prev);        else            printf("%s: count == %d, cur_blocks %d, prev 0x%x\n",                    str, count, bc.cur_blocks, prev);    }    UNLOCK(bc.lock);}static voiddump_lists(void){    cache_ent *nce;        printf("LOCKED 0x%x  (tail 0x%x, head 0x%x)\n", &bc.locked,           bc.locked.lru, bc.locked.mru);    for(nce=bc.locked.lru; nce; nce=nce->next)        printf("nce @ 0x%x dev %d bnum %ld flags %d lock %d clone 0x%x func 0x%x\n",               nce, nce->dev, nce->block_num, nce->flags, nce->lock, nce->clone,               nce->func);    printf("NORMAL 0x%x  (tail 0x%x, head 0x%x)\n", &bc.normal,           bc.normal.lru, bc.normal.mru);    for(nce=bc.normal.lru; nce; nce=nce->next)        printf("nce @ 0x%x dev %d bnum %ld flags %d lock %d clone 0x%x func 0x%x\n",               nce, nce->dev, nce->block_num, nce->flags, nce->lock, nce->clone,               nce->func);}static voidcheck_lists(void){    cache_ent *ce, *prev, *oce;    cache_ent_list *cel;        cel = &bc.normal;    for(ce=cel->lru,prev=NULL; ce; prev=ce, ce=ce->next) {        for(oce=bc.locked.lru; oce; oce=oce->next) {            if (oce == ce) {                dump_lists();                panic("1:ce @ 0x%x is in two lists(cel 0x%x &LOCKED)\n",ce,cel);            }        }    }    if (prev && prev != cel->mru) {        dump_lists();        panic("*** last element in list != cel mru (ce 0x%x, cel 0x%x)\n",              prev, cel);    }    cel = &bc.locked;    for(ce=cel->lru,prev=NULL; ce; prev=ce, ce=ce->next) {        for(oce=bc.normal.lru; oce; oce=oce->next) {            if (oce == ce) {                dump_lists();                panic("3:ce @ 0x%x is in two lists(cel 0x%x & DIRTY)\n",ce,cel);            }        }    }    if (prev && prev != cel->mru) {        dump_lists();        panic("*** last element in list != cel mru (ce 0x%x, cel 0x%x)\n",              prev, cel);    }}#ifdef DEBUGstatic intdo_dump(int argc, char **argv){    dump_cache_list();    return 1;}static intdo_find_block(int argc, char **argv){    int        i;    fs_off_t  bnum;    cache_ent *ce;    if (argc < 2) {        kprintf("%s: needs a block # argument\n", argv[0]);        return 1;    }    for(i=1; i < argc; i++) {        bnum = strtoul(argv[i], NULL, 0);        for(ce=bc.normal.lru; ce; ce=ce->next) {            if (ce->block_num == bnum) {                kprintf("found clean bnum %ld @ 0x%lx (data @ 0x%lx)\n",                        bnum, ce, ce->data);            }        }        for(ce=bc.locked.lru; ce; ce=ce->next) {            if (ce->block_num == bnum) {                kprintf("found locked bnum %ld @ 0x%lx (data @ 0x%lx)\n",                        bnum, ce, ce->data);            }        }    }    return 0;}static intdo_find_data(int argc, char **argv){    int        i;    void      *data;    cache_ent *ce;    if (argc < 2) {        kprintf("%s: needs a block # argument\n", argv[0]);        return 1;    }    for(i=1; i < argc; i++) {        data = (void *)strtoul(argv[i], NULL, 0);        for(ce=bc.normal.lru; ce; ce=ce->next) {            if (ce->data == data) {                kprintf("found normal data ptr for bnum %ld @ ce 0x%lx\n",                        ce->block_num, ce);            }        }        for(ce=bc.locked.lru; ce; ce=ce->next) {            if (ce->data == data) {                kprintf("found locked data ptr for bnum %ld @ ce 0x%lx\n",                        ce->block_num, ce);            }        }    }    return 0;}#endif /* DEBUG *//*  this function detaches the cache_ent from the list.*/  static voiddelete_from_list(cache_ent_list *cel, cache_ent *ce){    if (ce->next)        ce->next->prev = ce->prev;    if (ce->prev)        ce->prev->next = ce->next;    if (cel->lru == ce)        cel->lru = ce->next;    if (cel->mru == ce)        cel->mru = ce->prev;    ce->next = NULL;    ce->prev = NULL;}/*  this function adds the cache_ent ce to the head of the  list (i.e. the MRU end).  the cache_ent should *not*  be in any lists.*/  static voidadd_to_head(cache_ent_list *cel, cache_ent *ce){if (ce->next != NULL || ce->prev != NULL) {    panic("*** ath: ce has non-null next/prev ptr (ce 0x%x nxt 0x%x, prv 0x%x)\n",           ce, ce->next, ce->prev);}       ce->next = NULL;    ce->prev = cel->mru;    if (cel->mru)        cel->mru->next = ce;    cel->mru = ce;    if (cel->lru == NULL)        cel->lru = ce;}/*  this function adds the cache_ent ce to the tail of the  list (i.e. the MRU end).  the cache_ent should *not*  be in any lists.*/  static voidadd_to_tail(cache_ent_list *cel, cache_ent *ce){if (ce->next != NULL || ce->prev != NULL) {    panic("*** att: ce has non-null next/prev ptr (ce 0x%x nxt 0x%x, prv 0x%x)\n",           ce, ce->next, ce->prev);}       ce->next = cel->lru;    ce->prev = NULL;    if (cel->lru)        cel->lru->prev = ce;    cel->lru = ce;    if (cel->mru == NULL)        cel->mru = ce;}static intcache_ent_cmp(const void *a, const void *b){    fs_off_t  diff;    cache_ent *p1 = *(cache_ent **)a, *p2 = *(cache_ent **)b;    if (p1 == NULL || p2 == NULL)        panic("cache_ent pointers are null?!? (a 0x%lx, b 0x%lx\n)\n", a, b);    if (p1->dev == p2->dev) {        diff = p1->block_num - p2->block_num;        return (int)diff;    } else {        return p1->dev - p2->dev;    }}static voidcache_flusher(void *arg, int phase){    int    i, num_ents, err;    bigtime_t now = system_time();    static cache_ent *ce = NULL;    static cache_ent *ents[NUM_FLUSH_BLOCKS];    /*       if someone else was in the cache recently then just bail out so       we don't lock them out unnecessarily    */    if ((now - last_cache_access) < 1000000)        return;    LOCK(bc.lock);    ce = bc.normal.lru;        for(num_ents=0; ce && num_ents < NUM_FLUSH_BLOCKS; ce=ce->next) {        if (ce->flags & CE_BUSY)            continue;        if ((ce->flags & CE_DIRTY) == 0 && ce->clone == NULL)            continue;        ents[num_ents] = ce;        ents[num_ents]->flags |= CE_BUSY;        num_ents++;    }    /* if we've got some room left over, look for cloned locked blocks */    if (num_ents < NUM_FLUSH_BLOCKS) {        ce = bc.locked.lru;        for(; num_ents < NUM_FLUSH_BLOCKS;) {            for(;                ce && ((ce->flags & CE_BUSY) || ce->clone == NULL);                ce=ce->next)                /* skip ents that meet the above criteria */;            if (ce == NULL)                break;            ents[num_ents] = ce;            ents[num_ents]->flags |= CE_BUSY;            ce = ce->next;            num_ents++;        }    }    UNLOCK(bc.lock);    if (num_ents == 0)        return;    qsort(ents, num_ents, sizeof(cache_ent **), cache_ent_cmp);    if ((err = flush_ents(ents, num_ents)) != 0) {        printf("flush ents failed (ents @ 0x%lx, num_ents %d!\n",               (ulong)ents, num_ents);    }    for(i=0; i < num_ents; i++) {       /* clear the busy bit on each of ent */        ents[i]->flags &= ~CE_BUSY;    }}static intflush_cache_ent(cache_ent *ce){    int   ret = 0;    void *data;        /* if true, then there's nothing to flush */    if ((ce->flags & CE_DIRTY) == 0 && ce->clone == NULL)        return 0;    /* same thing here */    if (ce->clone == NULL && ce->lock != 0)        return 0; restart:    if (ce->clone)        data = ce->clone;    else        data = ce->data;                /* printf("flush: %7d\n", ce->block_num); */    ret = write_phys_blocks(ce->dev, ce->block_num, data, 1, ce->bsize);    if (ce->func) {        ce->func(ce->logged_bnum, 1, ce->arg);        ce->func = NULL;    }    if (ce->clone) {        free(ce->clone);        ce->clone = NULL;        if (ce->lock == 0 && (ce->flags & CE_DIRTY))            goto restart;     /* also write the real data ptr */    } else {        ce->flags &= ~CE_DIRTY;    }    return ret;}static intflush_ents(cache_ent **ents, int n_ents){    int    i, j, k, ret = 0, bsize, iocnt, do_again = 0;    fs_off_t  start_bnum;    struct iovec *iov;        iov = get_iovec_array();    if (iov == NULL)        return ENOMEM;restart:    for(i=0; i < n_ents; i++) {        /* if true, then there's nothing to flush */        if ((ents[i]->flags & CE_DIRTY) == 0 && ents[i]->clone == NULL)            continue;        /* if true we can't touch the dirty data yet because it's locked */        if (ents[i]->clone == NULL && ents[i]->lock != 0)            continue;                bsize      = ents[i]->bsize;        start_bnum = ents[i]->block_num;        for(j=i+1; j < n_ents && (j - i) < NUM_FLUSH_BLOCKS; j++) {            if (ents[j]->dev != ents[i]->dev ||                ents[j]->block_num != start_bnum + (j - i))                break;            if (ents[j]->clone == NULL && ents[j]->lock != 0)                break;        }                if (j == i+1) {           /* only one block, just flush it directly */            if ((ret = flush_cache_ent(ents[i])) != 0)                break;            continue;        }        for(k=i,iocnt=0; k < j; k++,iocnt++) {            if (ents[k]->clone)                iov[iocnt].iov_base = ents[k]->clone;            else                iov[iocnt].iov_base = ents[k]->data;            iov[iocnt].iov_len = bsize;        }        /* printf("writev @ %ld for %d blocks", start_bnum, iocnt); */        ret = writev_pos(ents[i]->dev, start_bnum * (fs_off_t)bsize,                          &iov[0], iocnt);        if (ret != iocnt*bsize) {            int idx;            printf("flush_ents: writev failed: iocnt %d start bnum %ld "                   "bsize %d, ret %d\n", iocnt, start_bnum, bsize, ret);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -