X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=lwext4%2Fext4_blockdev.c;h=23ad9ee3467368699090a6c921ad5186a3c17cab;hb=e1bbe336d1736703a6b1565cfa5565fb276643a1;hp=cc209dd5e4a290a347e7aa3e176cd2bc098a1afa;hpb=e69f4b3ad8c1b56035b669e10072054ae2939695;p=lwext4.git diff --git a/lwext4/ext4_blockdev.c b/lwext4/ext4_blockdev.c index cc209dd..23ad9ee 100644 --- a/lwext4/ext4_blockdev.c +++ b/lwext4/ext4_blockdev.c @@ -65,6 +65,7 @@ static int ext4_bdif_bread(struct ext4_blockdev *bdev, void *buf, { ext4_bdif_lock(bdev); int r = bdev->bdif->bread(bdev, buf, blk_id, blk_cnt); + bdev->bdif->bread_ctr++; ext4_bdif_unlock(bdev); return r; } @@ -74,6 +75,7 @@ static int ext4_bdif_bwrite(struct ext4_blockdev *bdev, const void *buf, { ext4_bdif_lock(bdev); int r = bdev->bdif->bwrite(bdev, buf, blk_id, blk_cnt); + bdev->bdif->bwrite_ctr++; ext4_bdif_unlock(bdev); return r; } @@ -138,46 +140,66 @@ int ext4_block_flush_buf(struct ext4_blockdev *bdev, struct ext4_buf *buf) { int r; struct ext4_bcache *bc = bdev->bc; - /*Only flushing unreferenced buffer is allowed.*/ - ext4_assert(!buf->refctr); - if (ext4_bcache_test_flag(buf, BC_DIRTY)) { + if (ext4_bcache_test_flag(buf, BC_DIRTY) && + ext4_bcache_test_flag(buf, BC_UPTODATE)) { r = ext4_blocks_set_direct(bdev, buf->data, buf->lba, 1); - if (r) { - if (buf->end_write) + if (buf->end_write) { + bc->dont_shake = true; buf->end_write(bc, buf, r, buf->end_write_arg); + bc->dont_shake = false; + } return r; } ext4_bcache_remove_dirty_node(bc, buf); ext4_bcache_clear_flag(buf, BC_DIRTY); - if (buf->end_write) + if (buf->end_write) { + bc->dont_shake = true; buf->end_write(bc, buf, r, buf->end_write_arg); - + bc->dont_shake = false; + } } return EOK; } +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; +} + int ext4_block_cache_shake(struct ext4_blockdev *bdev) { + int r = EOK; struct ext4_buf *buf; + if (bdev->bc->dont_shake) + return EOK; + while (!RB_EMPTY(&bdev->bc->lru_root) && ext4_bcache_is_full(bdev->bc)) { buf = ext4_buf_lowest_lru(bdev->bc); ext4_assert(buf); if (ext4_bcache_test_flag(buf, BC_DIRTY)) { - int r = ext4_block_flush_buf(bdev, buf); + r = ext4_block_flush_buf(bdev, buf); if (r != EOK) - return r; + break; } ext4_bcache_drop_buf(bdev->bc, buf); } - return EOK; + return r; } int ext4_block_get_noread(struct ext4_blockdev *bdev, struct ext4_block *b, @@ -259,7 +281,6 @@ int ext4_blocks_get_direct(struct ext4_blockdev *bdev, void *buf, uint64_t lba, pba = (lba * bdev->lg_bsize + bdev->part_offset) / bdev->bdif->ph_bsize; pb_cnt = bdev->lg_bsize / bdev->bdif->ph_bsize; - bdev->bread_ctr++; return ext4_bdif_bread(bdev, buf, pba, pb_cnt * cnt); } @@ -274,7 +295,6 @@ int ext4_blocks_set_direct(struct ext4_blockdev *bdev, const void *buf, pba = (lba * bdev->lg_bsize + bdev->part_offset) / bdev->bdif->ph_bsize; pb_cnt = bdev->lg_bsize / bdev->bdif->ph_bsize; - bdev->bwrite_ctr++; return ext4_bdif_bwrite(bdev, buf, pba, pb_cnt * cnt); } @@ -409,11 +429,22 @@ int ext4_block_readbytes(struct ext4_blockdev *bdev, uint64_t off, void *buf, return r; } -int ext4_block_cache_write_back(struct ext4_blockdev *bdev, uint8_t on_off) +int ext4_block_cache_flush(struct ext4_blockdev *bdev) { - int r; - struct ext4_buf *buf; + while (!SLIST_EMPTY(&bdev->bc->dirty_list)) { + int r; + struct ext4_buf *buf = SLIST_FIRST(&bdev->bc->dirty_list); + ext4_assert(buf); + r = ext4_block_flush_buf(bdev, buf); + if (r != EOK) + return r; + + } + return EOK; +} +int ext4_block_cache_write_back(struct ext4_blockdev *bdev, uint8_t on_off) +{ if (on_off) bdev->cache_write_back++; @@ -423,17 +454,8 @@ int ext4_block_cache_write_back(struct ext4_blockdev *bdev, uint8_t on_off) if (bdev->cache_write_back) return EOK; - /*Flush all delayed cache blocks*/ - while (!SLIST_EMPTY(&bdev->bc->dirty_list)) { - - buf = SLIST_FIRST(&bdev->bc->dirty_list); - ext4_assert(buf); - r = ext4_block_flush_buf(bdev, buf); - if (r != EOK) - return r; - - } - return EOK; + /*Flush data in all delayed cache blocks*/ + return ext4_block_cache_flush(bdev); } /**