To use block-cache.c be common cache interface, we need to add some parameter to identify cache's type.
Define a struct named BlockTableType, pass BlockTableType and table size parameters to block cache initialization function. v17-v18: 1) move struct to source file. 2) cluster_size->table_size. Signed-off-by: Dong Xu Wang <wdon...@linux.vnet.ibm.com> --- block/block-cache.c | 85 +++++++++++++++++++++++++++++++-------------------- block/block-cache.h | 59 +++++++++++++++++++++++++++++++++++ block/qcow2.c | 7 +++-- block/qcow2.h | 25 ++------------- include/block/block.h | 3 ++ 5 files changed, 122 insertions(+), 57 deletions(-) create mode 100644 block/block-cache.h diff --git a/block/block-cache.c b/block/block-cache.c index bc057a8..a05418f 100644 --- a/block/block-cache.c +++ b/block/block-cache.c @@ -1,4 +1,8 @@ /* + * QEMU Block Layer Cache + * + * This file is based on qcow2-cache.c, see its copyrights below: + * * L2/refcount table cache for the QCOW2 format * * Copyright (c) 2010 Kevin Wolf <kw...@redhat.com> @@ -24,11 +28,11 @@ #include "block/block_int.h" #include "qemu-common.h" -#include "qcow2.h" #include "trace.h" +#include "block/block-cache.h" typedef struct BlockCachedTable { - void* table; + void *table; int64_t offset; bool dirty; int cache_hits; @@ -36,30 +40,34 @@ typedef struct BlockCachedTable { } BlockCachedTable; struct BlockCache { - BlockCachedTable* entries; - struct BlockCache* depends; - int size; - bool depends_on_flush; + BlockCachedTable *entries; + struct BlockCache *depends; + int size; + size_t table_size; + BlockTableType table_type; + bool depends_on_flush; }; -BlockCache *block_cache_create(BlockDriverState *bs, int num_tables) +BlockCache *block_cache_create(BlockDriverState *bs, int num_tables, + size_t table_size, BlockTableType type) { - BDRVQcowState *s = bs->opaque; BlockCache *c; int i; c = g_malloc0(sizeof(*c)); c->size = num_tables; c->entries = g_malloc0(sizeof(*c->entries) * num_tables); + c->table_type = type; + c->table_size = table_size; for (i = 0; i < c->size; i++) { - c->entries[i].table = qemu_blockalign(bs, s->cluster_size); + c->entries[i].table = qemu_blockalign(bs, table_size); } return c; } -int block_cache_destroy(BlockDriverState* bs, BlockCache *c) +int block_cache_destroy(BlockDriverState *bs, BlockCache *c) { int i; @@ -91,15 +99,13 @@ static int block_cache_flush_dependency(BlockDriverState *bs, BlockCache *c) static int block_cache_entry_flush(BlockDriverState *bs, BlockCache *c, int i) { - BDRVQcowState *s = bs->opaque; int ret = 0; if (!c->entries[i].dirty || !c->entries[i].offset) { return 0; } - trace_block_cache_entry_flush(qemu_coroutine_self(), - c == s->l2_table_cache, i); + trace_block_cache_entry_flush(qemu_coroutine_self(), c->table_type, i); if (c->depends) { ret = block_cache_flush_dependency(bs, c); @@ -114,14 +120,16 @@ static int block_cache_entry_flush(BlockDriverState *bs, BlockCache *c, int i) return ret; } - if (c == s->refcount_block_cache) { + if (c->table_type == BLOCK_TABLE_REF) { BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART); - } else if (c == s->l2_table_cache) { + } else if (c->table_type == BLOCK_TABLE_L2) { BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE); + } else if (c->table_type == BLOCK_TABLE_BITMAP) { + BLKDBG_EVENT(bs->file, BLKDBG_ADDCOW_WRITE); } - ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->entries[i].table, - s->cluster_size); + ret = bdrv_pwrite(bs->file, c->entries[i].offset, + c->entries[i].table, c->table_size); if (ret < 0) { return ret; } @@ -133,12 +141,11 @@ static int block_cache_entry_flush(BlockDriverState *bs, BlockCache *c, int i) int block_cache_flush(BlockDriverState *bs, BlockCache *c) { - BDRVQcowState *s = bs->opaque; int result = 0; int ret; int i; - trace_block_cache_flush(qemu_coroutine_self(), c == s->l2_table_cache); + trace_block_cache_flush(qemu_coroutine_self(), c->table_type); for (i = 0; i < c->size; i++) { ret = block_cache_entry_flush(bs, c, i); @@ -157,13 +164,15 @@ int block_cache_flush(BlockDriverState *bs, BlockCache *c) return result; } -int block_cache_set_dependency(BlockDriverState *bs, BlockCache *c, - BlockCache *dependency) +int block_cache_set_dependency_two_bs(BlockDriverState *bs, + BlockCache *c, + BlockDriverState *depend_bs, + BlockCache *dependency) { int ret; if (dependency->depends) { - ret = block_cache_flush_dependency(bs, dependency); + ret = block_cache_flush_dependency(depend_bs, dependency); if (ret < 0) { return ret; } @@ -180,6 +189,13 @@ int block_cache_set_dependency(BlockDriverState *bs, BlockCache *c, return 0; } +int block_cache_set_dependency(BlockDriverState *bs, + BlockCache *c, + BlockCache *dependency) +{ + return block_cache_set_dependency_two_bs(bs, c, bs, dependency); +} + void block_cache_depends_on_flush(BlockCache *c) { c->depends_on_flush = true; @@ -216,13 +232,13 @@ static int block_cache_find_entry_to_replace(BlockCache *c) } static int block_cache_do_get(BlockDriverState *bs, BlockCache *c, - uint64_t offset, void **table, bool read_from_disk) + uint64_t offset, void **table, + bool read_from_disk) { - BDRVQcowState *s = bs->opaque; int i; int ret; - trace_block_cache_get(qemu_coroutine_self(), c == s->l2_table_cache, + trace_block_cache_get(qemu_coroutine_self(), c->table_type, offset, read_from_disk); /* Check if the table is already cached */ @@ -235,7 +251,7 @@ static int block_cache_do_get(BlockDriverState *bs, BlockCache *c, /* If not, write a table back and replace it */ i = block_cache_find_entry_to_replace(c); trace_block_cache_get_replace_entry(qemu_coroutine_self(), - c == s->l2_table_cache, i); + c->table_type, i); if (i < 0) { return i; } @@ -246,14 +262,17 @@ static int block_cache_do_get(BlockDriverState *bs, BlockCache *c, } trace_block_cache_get_read(qemu_coroutine_self(), - c == s->l2_table_cache, i); + c->table_type, i); c->entries[i].offset = 0; if (read_from_disk) { - if (c == s->l2_table_cache) { + if (c->table_type == BLOCK_TABLE_L2) { BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD); + } else if (c->table_type == BLOCK_TABLE_BITMAP) { + BLKDBG_EVENT(bs->file, BLKDBG_ADDCOW_READ); } - ret = bdrv_pread(bs->file, offset, c->entries[i].table, s->cluster_size); + ret = bdrv_pread(bs->file, offset, c->entries[i].table, + c->table_size); if (ret < 0) { return ret; } @@ -271,19 +290,19 @@ found: *table = c->entries[i].table; trace_block_cache_get_done(qemu_coroutine_self(), - c == s->l2_table_cache, i); + c->table_type, i); return 0; } int block_cache_get(BlockDriverState *bs, BlockCache *c, uint64_t offset, - void **table) + void **table) { return block_cache_do_get(bs, c, offset, table, true); } -int block_cache_get_empty(BlockDriverState *bs, BlockCache *c, uint64_t offset, - void **table) +int block_cache_get_empty(BlockDriverState *bs, BlockCache *c, + uint64_t offset, void **table) { return block_cache_do_get(bs, c, offset, table, false); } diff --git a/block/block-cache.h b/block/block-cache.h new file mode 100644 index 0000000..d057d9e --- /dev/null +++ b/block/block-cache.h @@ -0,0 +1,59 @@ +/* + * QEMU Block Layer Cache + * + * This file is based on qcow2-cache.c, see its copyrights below: + * + * L2/refcount table cache for the QCOW2 format + * + * Copyright (c) 2010 Kevin Wolf <kw...@redhat.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef BLOCK_CACHE_H +#define BLOCK_CACHE_H + +typedef enum { + BLOCK_TABLE_REF, + BLOCK_TABLE_L2, + BLOCK_TABLE_BITMAP, +} BlockTableType; + +struct BlockCache; +typedef struct BlockCache BlockCache; + +BlockCache *block_cache_create(BlockDriverState *bs, int num_tables, + size_t table_size, BlockTableType type); +int block_cache_destroy(BlockDriverState *bs, BlockCache *c); +int block_cache_flush(BlockDriverState *bs, BlockCache *c); +int block_cache_set_dependency(BlockDriverState *bs, + BlockCache *c, + BlockCache *dependency); +int block_cache_set_dependency_two_bs(BlockDriverState *bs, + BlockCache *c, + BlockDriverState *depend_bs, + BlockCache *dependency); +void block_cache_depends_on_flush(BlockCache *c); +int block_cache_get(BlockDriverState *bs, BlockCache *c, uint64_t offset, + void **table); +int block_cache_get_empty(BlockDriverState *bs, BlockCache *c, + uint64_t offset, void **table); +int block_cache_put(BlockDriverState *bs, BlockCache *c, void **table); +void block_cache_entry_mark_dirty(BlockCache *c, void *table); +#endif /* BLOCK_CACHE_H */ diff --git a/block/qcow2.c b/block/qcow2.c index a93df45..be4a1c3 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -470,8 +470,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) } /* alloc L2 table/refcount block cache */ - s->l2_table_cache = block_cache_create(bs, L2_CACHE_SIZE); - s->refcount_block_cache = block_cache_create(bs, REFCOUNT_CACHE_SIZE); + s->l2_table_cache = block_cache_create(bs, L2_CACHE_SIZE, + s->cluster_size, BLOCK_TABLE_L2); + s->refcount_block_cache = block_cache_create(bs, REFCOUNT_CACHE_SIZE, + s->cluster_size, + BLOCK_TABLE_REF); s->cluster_cache = g_malloc(s->cluster_size); /* one more sector for decompressed data alignment */ diff --git a/block/qcow2.h b/block/qcow2.h index 8cc851a..1ed91fc 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -27,6 +27,7 @@ #include "qemu/aes.h" #include "block/coroutine.h" +#include "block/block-cache.h" //#define DEBUG_ALLOC //#define DEBUG_ALLOC2 @@ -100,9 +101,6 @@ typedef struct QCowSnapshot { uint64_t vm_clock_nsec; } QCowSnapshot; -struct BlockCache; -typedef struct BlockCache BlockCache; - typedef struct Qcow2UnknownHeaderExtension { uint32_t magic; uint32_t len; @@ -168,8 +166,8 @@ typedef struct BDRVQcowState { uint64_t l1_table_offset; uint64_t *l1_table; - BlockCache* l2_table_cache; - BlockCache* refcount_block_cache; + BlockCache *l2_table_cache; + BlockCache *refcount_block_cache; uint8_t *cluster_cache; uint8_t *cluster_data; @@ -417,21 +415,4 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name); void qcow2_free_snapshots(BlockDriverState *bs); int qcow2_read_snapshots(BlockDriverState *bs); - -/* block-cache.c functions */ -BlockCache *block_cache_create(BlockDriverState *bs, int num_tables); -int block_cache_destroy(BlockDriverState* bs, BlockCache *c); - -void block_cache_entry_mark_dirty(BlockCache *c, void *table); -int block_cache_flush(BlockDriverState *bs, BlockCache *c); -int block_cache_set_dependency(BlockDriverState *bs, BlockCache *c, - BlockCache *dependency); -void block_cache_depends_on_flush(BlockCache *c); - -int block_cache_get(BlockDriverState *bs, BlockCache *c, uint64_t offset, - void **table); -int block_cache_get_empty(BlockDriverState *bs, BlockCache *c, uint64_t offset, - void **table); -int block_cache_put(BlockDriverState *bs, BlockCache *c, void **table); - #endif diff --git a/include/block/block.h b/include/block/block.h index 30c8e1a..709b5b6 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -413,6 +413,9 @@ typedef enum { BLKDBG_COW_READ, BLKDBG_COW_WRITE, + BLKDBG_ADDCOW_READ, + BLKDBG_ADDCOW_WRITE, + BLKDBG_REFTABLE_LOAD, BLKDBG_REFTABLE_GROW, -- 1.7.11.7