Ejemplo n.º 1
0
/* look buffer up from buffer cache; dev is buffer-device ID, not system */
struct bufblk *
buffindblk(long dev, off_t num, long rel)
{
#if (BUFNEWHASH)
    bufval_t         val = bufmkhashkey(dev, num);
    bufval_t         key = bufhash(val);
    struct bufblk   *blk;
    struct bufchain *chain = &bufhash[key];
#else
    bufval_t         key = bufhash(num);
    long             dkey = dev & BUFDEVMASK;
    struct bufblk   *blk = NULL;
#endif

#if (BUFNEWHASH)
    fmtxlk(&chain->lk);
    blk = chain->list;
    while ((blk) && blk->num != num) {
        blk = blk->tabnext;
    }
    if ((blk) && (rel)) {
        /* remove block from buffer hash chain */
        if (blk->tabprev) {
            blk->tabprev->tabnext = blk->tabnext;
        } else {
            chain->list = blk->tabnext;
        }
        if (blk->tabnext) {
            blk->tabnext->tabprev = blk->tabprev;
        }
    }

    return blk;
#else
    fmtxlk(&buflktab[dkey]);
    blk = bufhash[dkey][key];
    while ((blk) && blk->num != num) {
        blk = blk->tabnext;
    }
    if ((blk) && (rel)) {
        /* remove block from buffer hash chain */
        if (blk->tabprev) {
            blk->tabprev->tabnext = blk->tabnext;
        } else {
            bufhash[dkey][key] = blk->tabnext;
        }
        if (blk->tabnext) {
            blk->tabnext->tabprev = blk->tabprev;
        }
    }
    fmtxunlk(&buflktab[dkey]);

    return blk;
#endif
}
Ejemplo n.º 2
0
static void insert_into_hashtable(struct bufpool *pool, struct buf *buf)
{
    int slot;

    slot = bufhash(buf->blkno) % BUFPOOL_HASHSIZE;
    if (pool->hashtable[slot]) pool->hashtable[slot]->bucket.prev = buf;
    buf->bucket.next = pool->hashtable[slot];
    buf->bucket.prev = NULL;
    pool->hashtable[slot] = buf;
}
Ejemplo n.º 3
0
static void remove_from_hashtable(struct bufpool *pool, struct buf *buf)
{
    int slot;

    slot = bufhash(buf->blkno) % BUFPOOL_HASHSIZE;
    if (buf->bucket.next) buf->bucket.next->bucket.prev = buf->bucket.prev;
    if (buf->bucket.prev) buf->bucket.prev->bucket.next = buf->bucket.next;
    if (pool->hashtable[slot] == buf) pool->hashtable[slot] = buf->bucket.next;
    buf->bucket.next = NULL;
    buf->bucket.prev = NULL;
}
Ejemplo n.º 4
0
void
bufaddblk(struct bufblk *blk)
{
#if (BUFNEWHASH)
    bufval_t         val = bufmkhashkey(blk->dev, blk->num);
    bufval_t         key = bufhash(val);
    struct bufblk   *buf;
    struct bufchain *chain = &bufhash[key];
#else
    buval_t          key = bufhash(blk->num);
    long             dkey = blk->dev & BUFDEVMASK;
    struct bufblk   *buf;
#endif

#if (BUFNEWHASH)
    fmtxlk(&chain->lk);
    buf = chain->list;
    buf->tabprev = NULL;
    if (buf) {
        buf->tabprev = blk;
    }
    blk->tabnext = buf;
    chain->list = buf;
    fmtxunlk(&chain->lk);
#else
    fmtxlk(&buflktab[dkey]);
    buf = bufhash[dkey][key];
    if (buf) {
        buf->tabprev = blk;
    }
    bufhash[dkey][key] = blk;
    fmtxunlk(&buflktab[dkey]);
#endif

    return;
}
Ejemplo n.º 5
0
static struct buf *lookup_buffer(struct bufpool *pool, vfs_blkno_t blkno)
{
    struct buf *buf;

    buf = pool->hashtable[bufhash(blkno) % BUFPOOL_HASHSIZE];
    while (buf && buf->blkno != blkno) buf = buf->bucket.next;
    if (!buf) return NULL;

    switch (buf->state)
    {
    case BUF_STATE_FREE:
        panic("free buffer in cache");
        break;

    case BUF_STATE_CLEAN:
        // Remove from clean list
        if (buf->chain.next) buf->chain.next->chain.prev = buf->chain.prev;
        if (buf->chain.prev) buf->chain.prev->chain.next = buf->chain.next;
        if (pool->clean.head == buf) pool->clean.head = buf->chain.next;
        if (pool->clean.tail == buf) pool->clean.tail = buf->chain.prev;

        // Set state to locked and add lock
        buf->chain.next = NULL;
        buf->chain.prev = NULL;
        buf->state = BUF_STATE_LOCKED;
        buf->locks++;
        break;

    case BUF_STATE_DIRTY:
        // Remove from dirty list
        if (buf->chain.next) buf->chain.next->chain.prev = buf->chain.prev;
        if (buf->chain.prev) buf->chain.prev->chain.next = buf->chain.next;
        if (pool->dirty.head == buf) pool->dirty.head = buf->chain.next;
        if (pool->dirty.tail == buf) pool->dirty.tail = buf->chain.prev;

        // Set state to updated and add lock
        buf->chain.next = NULL;
        buf->chain.prev = NULL;
        buf->state = BUF_STATE_UPDATED;
        buf->locks++;
        break;

    case BUF_STATE_READING:
    case BUF_STATE_WRITING:
        // Wait for buffer to become ready. Buffer is locked by reader/writer
        wait_for_buffer(buf);
        break;

    case BUF_STATE_LOCKED:
    case BUF_STATE_UPDATED:
        // Add lock
        buf->locks++;
        break;

    case BUF_STATE_INVALID:
        // Set state to locked, add lock and clear buffer
        buf->state = BUF_STATE_LOCKED;
        buf->locks++;
        memset(buf->data, 0, pool->bufsize);
        break;

    default:
        panic("invalid buffer state");
    }

    return buf;
}