Typically, data for unallocated clusters is filled with zeros, so it makes no sense to store it in the cache.
Signed-off-by: Pavel Butsykin <pbutsy...@virtuozzo.com> --- block/pcache.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/block/pcache.c b/block/pcache.c index 3717037..1f3800d 100644 --- a/block/pcache.c +++ b/block/pcache.c @@ -223,6 +223,28 @@ static RBCacheNode *pcache_node_alloc(uint64_t offset, uint64_t bytes, return &node->common; } +static bool check_allocated_clusters(BlockDriverState *bs, uint64_t offset, + uint64_t bytes) +{ + int64_t sector_num = offset >> BDRV_SECTOR_BITS; + int32_t nb_sectors = bytes >> BDRV_SECTOR_BITS; + + assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); + assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + + do { + int num, ret = bdrv_is_allocated(bs, sector_num, nb_sectors, &num); + if (ret <= 0) { + return false; + } + sector_num += num; + nb_sectors -= num; + + } while (nb_sectors); + + return true; +} + #define PCACHE_STEPS_FORWARD 2 static PCacheNode *get_readahead_node(BlockDriverState *bs, RBCache *rbcache, @@ -242,6 +264,10 @@ static PCacheNode *get_readahead_node(BlockDriverState *bs, RBCache *rbcache, break; } + if (!check_allocated_clusters(bs, offset, bytes)) { + break; + } + node = rbcache_search_and_insert(rbcache, offset, bytes); if (node->status == NODE_STATUS_NEW) { return node; -- 2.10.1