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

📄 cache.c

📁 be文件系统实现的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    real_remove_cached_blocks(dev, allow_writes, &bc.normal);    real_remove_cached_blocks(dev, allow_writes, &bc.locked);    max_device_blocks[dev] = 0;    UNLOCK(bc.lock);    return 0;}intflush_blocks(int dev, fs_off_t bnum, int nblocks){    int        cur, i;    cache_ent *ce;    cache_ent *ents[NUM_FLUSH_BLOCKS];    if (nblocks == 0)   /* might as well check for this */        return 0;    LOCK(bc.lock);        cur = 0;    for(; nblocks > 0; nblocks--, bnum++) {        ce = block_lookup(dev, bnum);        if (ce == NULL)            continue;                    if (bnum != ce->block_num || dev != ce->dev) {            UNLOCK(bc.lock);            panic("error2: looked up dev %d block %ld but found %d %ld\n",                  dev, bnum, ce->dev, ce->block_num);            return EBADF;        }        if ((ce->flags & CE_DIRTY) == 0 && ce->clone == NULL)            continue;        ce->flags |= CE_BUSY;        ents[cur++] = ce;        if (cur >= NUM_FLUSH_BLOCKS) {            UNLOCK(bc.lock);            qsort(ents, cur, sizeof(cache_ent **), cache_ent_cmp);            flush_ents(ents, cur);            LOCK(bc.lock);            for(i=0; i < cur; i++) {                ents[i]->flags &= ~CE_BUSY;            }            cur = 0;        }    }    UNLOCK(bc.lock);    if (cur == 0)     /* nothing more to do */        return 0;    /* flush out the last few buggers */    qsort(ents, cur, sizeof(cache_ent **), cache_ent_cmp);    flush_ents(ents, cur);    for(i=0; i < cur; i++) {        ents[i]->flags &= ~CE_BUSY;    }    return 0;}intmark_blocks_dirty(int dev, fs_off_t bnum, int nblocks){    int        ret = 0;    cache_ent *ce;    LOCK(bc.lock);        while(nblocks > 0) {        ce = block_lookup(dev, bnum);        if (ce) {            ce->flags |= CE_DIRTY;            bnum      += 1;                     nblocks   -= 1;        } else {     /* hmmm, that's odd, didn't find it */            printf("** mark_blocks_diry couldn't find block %ld (len %d)\n",                   bnum, nblocks);            ret = ENOENT;            break;        }    }        UNLOCK(bc.lock);    return ret;}intrelease_block(int dev, fs_off_t bnum){    cache_ent *ce;    /* printf("rlsb: %ld\n", bnum); */    LOCK(bc.lock);        ce = block_lookup(dev, bnum);    if (ce) {        if (bnum != ce->block_num || dev != ce->dev) {            panic("*** error3: looked up dev %d block %ld but found %d %ld\n",                    dev, bnum, ce->dev, ce->block_num);            UNLOCK(bc.lock);            return EBADF;        }        ce->lock--;        if (ce->lock < 0) {            printf("rlsb: whoa nellie! ce %ld has lock == %d\n",                   ce->block_num, ce->lock);        }                    if (ce->lock == 0) {            delete_from_list(&bc.locked, ce);            add_to_head(&bc.normal, ce);        }    } else {     /* hmmm, that's odd, didn't find it */        panic("** release_block asked to find %ld but it's not here\n",               bnum);    }        UNLOCK(bc.lock);    return 0;}static cache_ent *new_cache_ent(int bsize){    cache_ent *ce;    ce = (cache_ent *)calloc(1, sizeof(cache_ent));    if (ce == NULL) {        panic("*** error: cache can't allocate memory!\n");        return NULL;    }                    ce->data = malloc(bsize);    if (ce->data == NULL) {        free(ce);        panic("** error cache can't allocate data memory\n");        UNLOCK(bc.lock);        return NULL;    }                    ce->dev       = -1;    ce->block_num = -1;    return ce;}static voidget_ents(cache_ent **ents, int num_needed, int max, int *num_gotten, int bsize){    int        cur, retry_counter = 0, max_retry = num_needed * 256;    cache_ent *ce;        if (num_needed > max)        panic("get_ents: num_needed %d but max %d (doh!)\n", num_needed, max);    /* if the cache isn't full yet, just allocate the blocks */    for(cur=0; bc.cur_blocks < bc.max_blocks && cur < num_needed; cur++) {        ents[cur] = new_cache_ent(bsize);        if (ents[cur] == NULL)            break;        bc.cur_blocks++;    }    /* pluck off blocks from the LRU end of the normal list, keep trying too */    while(cur < num_needed && retry_counter < max_retry) {        for(ce=bc.normal.lru; ce && cur < num_needed; ce=ce->next) {            if (ce->lock)                panic("get_ents: normal list has locked blocks (ce 0x%x)\n",ce);            if (ce->flags & CE_BUSY)   /* don't touch busy blocks */                continue;            ce->flags   |= CE_BUSY;            ents[cur++]  = ce;        }        if (cur < num_needed) {            UNLOCK(bc.lock);            snooze(10000);            LOCK(bc.lock);            retry_counter++;        }    }        if (cur < num_needed && retry_counter >= max_retry) {  /* oh shit! */        dump_cache_list();        UNLOCK(bc.lock);        panic("get_ents: waited too long; can't get enough ce's (c %d n %d)\n",              cur, num_needed);    }    /*      If the last block is a dirty one, try to get more of 'em so      that we can flush a bunch of blocks at once.    */    if (cur && cur < max &&        ((ents[cur-1]->flags & CE_DIRTY) || ents[cur-1]->clone)) {        for(ce=ents[cur-1]->next; ce && cur < max; ce=ce->next) {            if (ce->flags & CE_BUSY)   /* don't touch busy blocks */                continue;            if (ce->lock)                panic("get_ents:2 dirty list has locked blocks (ce 0x%x)\n",ce);                            ce->flags   |= CE_BUSY;            ents[cur++]  = ce;        }    }    *num_gotten = cur;}static intread_into_ents(int dev, fs_off_t bnum, cache_ent **ents, int num, int bsize){    int    i, ret;    struct iovec *iov;    iov = get_iovec_array();    for(i=0; i < num; i++) {        iov[i].iov_base = ents[i]->data;        iov[i].iov_len  = bsize;    }    /* printf("readv @ %ld for %d blocks\n", bnum, num); */    ret = readv_pos(dev, bnum*bsize, iov, num);    release_iovec_array(iov);    if (ret != num*bsize) {        printf("read_into_ents: asked to read %d bytes but got %d\n",               num*bsize, ret);        printf("*** iov @ 0x%x (num %d)\n", iov, num);        return EINVAL;    } else        return 0;}#define CACHE_READ          0x0001#define CACHE_WRITE         0x0002#define CACHE_NOOP          0x0004     /* for getting empty blocks */#define CACHE_LOCKED        0x0008#define CACHE_READ_AHEAD_OK 0x0010     /* it's ok to do read-ahead */static char *op_to_str(int op){    static char buff[128];    if (op & CACHE_READ)        strcpy(buff, "RD");    else if (op & CACHE_WRITE)        strcpy(buff, "WR");     else if (op & CACHE_NOOP)        strcpy(buff, "NOP");    if (op & CACHE_LOCKED)        strcat(buff, " LOCKED");    if (op & CACHE_READ_AHEAD_OK)        strcat(buff, " (AHEAD)");    return buff;}static intcache_block_io(int dev, fs_off_t bnum, void *data, fs_off_t num_blocks, int bsize,               int op, void **dataptr){    size_t          err = 0;    cache_ent      *ce;    cache_ent_list *cel;        if (chatty_io > 1)        printf("cbio: bnum %ld nblock %ld bsize %d op %s\n", bnum, num_blocks,               bsize, op_to_str(op));    /* some sanity checks first */    if (bsize == 0)        panic("cache_io: block size == 0 for bnum %ld?!?\n", bnum);    if (num_blocks == 0)        panic("cache_io: bnum %ld has num_blocks == 0!\n", bnum);        if (data == NULL && dataptr == NULL) {        printf("major butthead move: null data and dataptr! bnum %ld:%ld\n",                bnum, num_blocks);        return ENOMEM;    }            if (data == NULL) {        if (num_blocks != 1)    /* get_block() should never do that */            panic("cache_io: num_blocks %ld but should be 1\n",                  num_blocks);        if (op & CACHE_WRITE)            panic("cache_io: get_block() asked to write?!?\n");    }    if (bnum + num_blocks > max_device_blocks[dev]) {        printf("dev %d: access to blocks %ld:%ld but max_dev_blocks is %ld\n",               dev, bnum, num_blocks, max_device_blocks[dev]);*(int *)0x3100 = 0xc0debabe;        return EINVAL;    }    last_cache_access = system_time();    /* if the i/o is greater than 64k, do it directly */    if (num_blocks * bsize >= 64 * 1024) {        char  *ptr;        fs_off_t  tmp;        if (data == NULL || (op & CACHE_LOCKED)) {            panic("*** asked to do a large locked io that's too hard!\n");        }        if (op & CACHE_READ) {            if (read_phys_blocks(dev, bnum, data, num_blocks, bsize) != 0) {                printf("cache read:read_phys_blocks failed (%s on blocks %ld:%ld)!\n",                        strerror(errno), bnum, num_blocks);                return EINVAL;            }            LOCK(bc.lock);            /* if any of the blocks are in the cache, grab them instead */            ptr = data;            for(tmp=bnum; tmp < bnum+num_blocks; tmp++, ptr+=bsize) {                ce = block_lookup(dev, tmp);                /*                    if we find a block in the cache we have to copy its                    data just in case it is more recent than what we just                    read from disk (which could happen if someone wrote                     these blocks after we did the read but before we locked                    the cache and entered this loop).                */                if (ce) {                    if (tmp != ce->block_num || dev != ce->dev) {                        UNLOCK(bc.lock);                        panic("*** error4: looked up dev %d block %ld but "                                "found %d %ld\n", dev, tmp, ce->dev,                                ce->block_num);                    }                                        memcpy(ptr, ce->data, bsize);                }            }            UNLOCK(bc.lock);        } else if (op & CACHE_WRITE) {            LOCK(bc.lock);            /* if any of the blocks are in the cache, update them too */            ptr = data;            for(tmp=bnum; tmp < bnum+num_blocks; tmp++, ptr+=bsize) {                ce = block_lookup(dev, tmp);                if (ce) {                    if (tmp != ce->block_num || dev != ce->dev) {                        UNLOCK(bc.lock);                        panic("*** error5: looked up dev %d block %ld but "                                "found %d %ld\n", dev, tmp, ce->dev,                                ce->block_num);                        return EBADF;                    }                    /* XXXdbg -- this isn't strictly necessary */                    if (ce->clone) {                        printf("over-writing cloned data (ce 0x%x bnum %ld)...\n", ce,tmp);                        flush_cache_ent(ce);                    }                    /* copy the data into the cache */                    memcpy(ce->data, ptr, bsize);                }            }                        UNLOCK(bc.lock);            if (write_phys_blocks(dev, bnum, data, num_blocks, bsize) != 0) {                printf("cache write: write_phys_blocks failed (%s on blocks "                       "%ld:%ld)!\n", strerror(errno), bnum, num_blocks);                return EINVAL;            }        } else {            printf("bad cache op %d (bnum %ld nblocks %ld)\n", op, bnum,                   num_blocks);            return EINVAL;        }        return 0;    }    LOCK(bc.lock);    while(num_blocks) {            ce = block_lookup(dev, bnum);        if (ce) {            if (bnum != ce->block_num || dev != ce->dev) {                UNLOCK(bc.lock);                panic("*** error6: looked up dev %d block %ld but found "                        "%d %ld\n", dev, bnum, ce->dev, ce->block_num);                return EBADF;            }            if (bsize != ce->bsize) {                panic("*** requested bsize %d but ce->bsize %d ce @ 0x%x\n",                        bsize, ce->bsize, ce);            }            /* delete this ent from the list it is in because it may change */            if (ce->lock)                cel = &bc.locked;            else                cel = &bc.normal;                            delete_from_list(cel, ce);            if (op & CACHE_READ) {                if (data && data != ce->data) {                    memcpy(data, ce->data, bsize);                } else if (dataptr) {                     *dataptr = ce->data;                } else {                    printf("cbio:data 0x%x dptr 0x%x ce @ 0x%x ce->data 0x%x\n",                           data, dataptr, ce, ce->data);                }            } else if (op & CACHE_WRITE) {                if (data && data != ce->data)                    memcpy(ce->data, data, bsize);                ce->flags |= CE_DIRTY;            } else if (op & CACHE_NOOP) {                memset(ce->data, 0, bsize);                if (data)                    memset(data, 0, bsize);                                if (dataptr)                    *dataptr = ce->data;                ce->flags |= CE_DIRTY;            } else {                panic("cached_block_io: bogus op %d\n", op);            }            if (op & CACHE_LOCKED)                ce->lock++;

⌨️ 快捷键说明

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