示例#1
0
int ext4_block_set(struct ext4_blockdev *bdev, struct ext4_block *b)
{
    uint64_t pba;
    uint32_t pb_cnt;
    int r;

    ext4_assert(bdev && b);

    if(!(bdev->flags & EXT4_BDEV_INITIALIZED))
        return EIO;

    /*Doesn,t need to write.*/
    if(!b->dirty && !bdev->bc->dirty[b->cache_id]){
        ext4_bcache_free(bdev->bc, b, 0);
        return EOK;
    }

    /*Free cache delay mode*/
    if(bdev->cache_write_back){

        /*Free cahe block and mark as free delayed*/
        return ext4_bcache_free(bdev->bc, b, bdev->cache_write_back);
    }

    if(bdev->bc->refctr[b->cache_id] > 1){
        bdev->bc->dirty[b->cache_id] = true;
        return ext4_bcache_free(bdev->bc, b, 0);
    }


    pba = (b->lb_id * bdev->lg_bsize) / bdev->ph_bsize;
    pb_cnt = bdev->lg_bsize / bdev->ph_bsize;

#if CONFIG_EXT4_READONLY
    r = EOK;
#else
    r = bdev->bwrite(bdev, b->data, pba, pb_cnt);
#endif
    bdev->bc->dirty[b->cache_id] = false;
    if(r != EOK){
        b->dirty = false;
        ext4_bcache_free(bdev->bc, b, 0);
        return r;
    }

    bdev->bwrite_ctr++;
    b->dirty = false;
    ext4_bcache_free(bdev->bc, b, 0);
    return EOK;
}
示例#2
0
int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
		   uint64_t lba)
{
	int r = ext4_block_get_noread(bdev, b, lba);
	if (r != EOK)
		return r;

	if (ext4_bcache_test_flag(b->buf, BC_UPTODATE)) {
		/* Data in the cache is up-to-date.
		 * Reading from physical device is not required */
		return EOK;
	}

	r = ext4_blocks_get_direct(bdev, b->data, lba, 1);
	if (r != EOK) {
		ext4_bcache_free(bdev->bc, b);
		b->lb_id = 0;
		return r;
	}

	/* Mark buffer up-to-date, since
	 * fresh data is read from physical device just now. */
	ext4_bcache_set_flag(b->buf, BC_UPTODATE);
	return EOK;
}
示例#3
0
int ext4_block_set(struct ext4_blockdev *bdev, struct ext4_block *b)
{
	ext4_assert(bdev && b);
	ext4_assert(b->buf);

	if (!bdev->bdif->ph_refctr)
		return EIO;

	return ext4_bcache_free(bdev->bc, b);
}
示例#4
0
int ext4_block_flush_lba(struct ext4_blockdev *bdev, uint64_t lba)
{
	int r = EOK;
	struct ext4_buf *buf;
	struct ext4_block b;
	buf = ext4_bcache_find_get(bdev->bc, &b, lba);
	if (buf) {
		r = ext4_block_flush_buf(bdev, buf);
		ext4_bcache_free(bdev->bc, &b);
	}
	return r;
}
示例#5
0
int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
    uint64_t lba)
{
    uint64_t pba;
    uint32_t pb_cnt;
    uint32_t i;
    bool is_new;
    int r;

    ext4_assert(bdev && b);

    if(!(bdev->flags & EXT4_BDEV_INITIALIZED))
        return EIO;

    if(!(lba < bdev->lg_bcnt))
        return ERANGE;

    b->dirty = 0;
    b->lb_id = lba;

    /*If cache is full we have to flush it anyway :(*/
    if(ext4_bcache_is_full(bdev->bc) && bdev->cache_write_back){

        uint32_t free_candidate = bdev->bc->cnt;
        uint32_t min_lru = 0xFFFFFFFF;

        for (i = 0; i < bdev->bc->cnt; ++i) {
            /*Check if buffer free was delayed.*/
            if(!bdev->bc->free_delay[i])
                continue;

            /*Check reference counter.*/
            if(bdev->bc->refctr[i])
                continue;

            if(bdev->bc->lru_id[i] < min_lru){
                min_lru = bdev->bc->lru_id[i];
                free_candidate = i;
                continue;
            }
        }

        if(free_candidate < bdev->bc->cnt){
            /*Buffer free was delayed and have no reference. Flush it.*/
            r = ext4_blocks_set_direct(bdev,
                    bdev->bc->data + bdev->bc->itemsize * free_candidate,
                    bdev->bc->lba[free_candidate], 1);
            if(r != EOK)
                return r;

            /*No delayed anymore*/
            bdev->bc->free_delay[free_candidate] = 0;

            /*Reduce refered block count*/
            bdev->bc->ref_blocks--;
        }
    }


    r = ext4_bcache_alloc(bdev->bc, b, &is_new);
    if(r != EOK)
        return r;


    if(!is_new){
        /*Block is in cache. Read from physical device is not required*/
        return EOK;
    }

    if(!b->data)
        return ENOMEM;

    pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
    pb_cnt = bdev->lg_bsize / bdev->ph_bsize;

    r = bdev->bread(bdev, b->data, pba, pb_cnt);

    if(r != EOK){
        ext4_bcache_free(bdev->bc, b, 0);
        b->lb_id = 0;
        return r;
    }

    bdev->bread_ctr++;
    return EOK;
}