return bdev->close(bdev);
}
-int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
- uint64_t lba)
+int ext4_block_get_noread(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;
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;
+ return EOK;
+}
+
+int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
+ uint64_t lba)
+{
+ uint64_t pba;
+ uint32_t pb_cnt;
+ int r = ext4_block_get_noread(bdev, b, lba);
+ if (r != EOK)
+ return r;
+
+ if (b->uptodate) {
+ /* Data in the cache is up-to-date.
+ * Reading from physical device is not required */
+ return EOK;
+ }
+
pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
return r;
}
+ /* Mark buffer up-to-date, since
+ * fresh data is read from physical device just now. */
+ ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_UPTODATE);
+ b->uptodate = true;
bdev->bread_ctr++;
return EOK;
}
if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
return EIO;
+ /*Buffer is not marked dirty and is stale*/
+ if (!b->uptodate && !b->dirty)
+ ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_UPTODATE);
+
/*No need to write.*/
- if (!b->dirty && !bdev->bc->dirty[b->cache_id]) {
+ if (!b->dirty &&
+ !ext4_bcache_test_flag(bdev->bc, b->cache_id, BC_DIRTY)) {
ext4_bcache_free(bdev->bc, b, 0);
return EOK;
}
+ /* Data is valid, so mark buffer up-to-date. */
+ ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_UPTODATE);
/*Free cache delay mode*/
if (bdev->cache_write_back) {
}
if (bdev->bc->refctr[b->cache_id] > 1) {
- bdev->bc->dirty[b->cache_id] = true;
+ ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_DIRTY);
return ext4_bcache_free(bdev->bc, b, 0);
}
pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
r = bdev->bwrite(bdev, b->data, pba, pb_cnt);
- bdev->bc->dirty[b->cache_id] = false;
+ ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_DIRTY);
if (r != EOK) {
b->dirty = false;
+ ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_UPTODATE);
ext4_bcache_free(bdev->bc, b, 0);
return r;
}
: (bdev->ph_bsize - unalg);
r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
-
if (r != EOK)
return r;
/*Aligned data*/
blen = len / bdev->ph_bsize;
r = bdev->bwrite(bdev, p, block_idx, blen);
-
if (r != EOK)
return r;
memcpy(bdev->ph_bbuf, p, len);
r = bdev->bwrite(bdev, bdev->ph_bbuf, block_idx, 1);
-
if (r != EOK)
return r;
}
blen = len / bdev->ph_bsize;
r = bdev->bread(bdev, p, block_idx, blen);
-
if (r != EOK)
return r;
if (!on_off && bdev->cache_write_back)
bdev->cache_write_back--;
+
+ if (bdev->cache_write_back)
+ return EOK;
+
/*Flush all delayed cache blocks*/
- if (!bdev->cache_write_back) {
- for (i = 0; i < bdev->bc->cnt; ++i) {
+ for (i = 0; i < bdev->bc->cnt; ++i) {
- /*Check if buffer free was delayed.*/
- if (!bdev->bc->free_delay[i])
- continue;
+ /*Check if buffer free was delayed.*/
+ if (!bdev->bc->free_delay[i])
+ continue;
- /*Check reference counter.*/
- if (bdev->bc->refctr[i])
- continue;
+ /*Check reference counter.*/
+ if (bdev->bc->refctr[i])
+ continue;
- /*Buffer free was delayed and have no reference. Flush
- * it.*/
- r = ext4_blocks_set_direct(
- bdev, bdev->bc->data + bdev->bc->itemsize * i,
- bdev->bc->lba[i], 1);
- if (r != EOK)
- return r;
+ /*Buffer free was delayed and have no reference. Flush
+ * it.*/
+ r = ext4_blocks_set_direct(bdev, bdev->bc->data +
+ bdev->bc->itemsize * i, bdev->bc->lba[i], 1);
+ if (r != EOK)
+ return r;
- /*No delayed anymore*/
- bdev->bc->free_delay[i] = 0;
+ /*No delayed anymore*/
+ bdev->bc->free_delay[i] = 0;
- /*Reduce reference counter*/
- bdev->bc->ref_blocks--;
- }
+ /*Reduce reference counter*/
+ bdev->bc->ref_blocks--;
}
+
return EOK;
}