From patchwork Thu May 30 10:00:21 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Wang X-Patchwork-Id: 247515 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 7AE412C0091 for ; Thu, 30 May 2013 20:01:58 +1000 (EST) Received: from localhost ([::1]:35562 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UhzgC-0004gd-KZ for incoming@patchwork.ozlabs.org; Thu, 30 May 2013 06:01:56 -0400 Received: from eggs.gnu.org ([208.118.235.92]:58084) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UhzfV-0004NA-0u for qemu-devel@nongnu.org; Thu, 30 May 2013 06:01:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UhzfM-0007au-SE for qemu-devel@nongnu.org; Thu, 30 May 2013 06:01:12 -0400 Received: from mail-gg0-x230.google.com ([2607:f8b0:4002:c02::230]:42737) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UhzfM-0007aA-L5 for qemu-devel@nongnu.org; Thu, 30 May 2013 06:01:04 -0400 Received: by mail-gg0-f176.google.com with SMTP id b1so5221ggm.7 for ; Thu, 30 May 2013 03:01:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=n8u9K+zod7kIbrKge1pbShczbjD8OgejnSavNUtE1Os=; b=ByDIg/zi/4/QsSCaxWCy188H480ld3O3txflrO1XyJYe3Mb8kVpxmc1pYEhwFUWf3l Xjr915oMU7WhOx5CSsMYzCGCNS/RDVnDZbD+XkL3GkG9AAE13r+zh9KlTXe1FL/Gdfw3 GMywqu8cAPdXFityJtJvwJC4S0N5XHRhA30zhYdgb7US8/ybFyNqNXuRbBzMfp1xy7Ev 7isVbLwW/AltBvDYjTDMBPdE0QtrRRVW5Yd7eINFoAP0Qkt5Fs3GctPAoCx9SuEbcp5v 5sR5mQ02GLnW6FloBzCFovKnYDeFh0nShJDN+YTxLjujW8DWvxxeqF782PqUlz+Vwm2j cN5w== X-Received: by 10.236.200.33 with SMTP id y21mr3093805yhn.175.1369908064167; Thu, 30 May 2013 03:01:04 -0700 (PDT) Received: from 11.wdongxu.kvm58 ([202.108.130.153]) by mx.google.com with ESMTPSA id j64sm58764867yhj.25.2013.05.30.03.01.00 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 30 May 2013 03:01:03 -0700 (PDT) From: Dongxu Wang To: qemu-devel@nongnu.org Date: Thu, 30 May 2013 18:00:21 +0800 Message-Id: <1369908025-9556-5-git-send-email-wdongxu@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.11.7 In-Reply-To: <1369908025-9556-1-git-send-email-wdongxu@linux.vnet.ibm.com> References: <1369908025-9556-1-git-send-email-wdongxu@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:4002:c02::230 Cc: kwolf@redhat.com, Dong Xu Wang , wdongxu@cn.ibm.com, stefanha@redhat.com Subject: [Qemu-devel] [PATCH V19 4/8] rename qcow2-cache.c to block-cache.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Dong Xu Wang Block layer will use qcow2-cache as common cache code, so rename it to block-cache.c. v18->v19: 1) only rename, did not touch other code. Signed-off-by: Dongxu Wang --- block/Makefile.objs | 3 +- block/block-cache.c | 323 +++++++++++++++++++++++++++++++++++++++++++++++++ block/qcow2-cache.c | 323 ------------------------------------------------- block/qcow2-cluster.c | 48 ++++---- block/qcow2-refcount.c | 42 +++---- block/qcow2.c | 18 +-- block/qcow2.h | 28 ++--- trace-events | 12 +- 8 files changed, 399 insertions(+), 398 deletions(-) create mode 100644 block/block-cache.c delete mode 100644 block/qcow2-cache.c diff --git a/block/Makefile.objs b/block/Makefile.objs index 5f0358a..16e574a 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -1,5 +1,6 @@ block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o -block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o +block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o +block-obj-y += block-cache.o block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o block-obj-y += vhdx.o diff --git a/block/block-cache.c b/block/block-cache.c new file mode 100644 index 0000000..bc057a8 --- /dev/null +++ b/block/block-cache.c @@ -0,0 +1,323 @@ +/* + * L2/refcount table cache for the QCOW2 format + * + * Copyright (c) 2010 Kevin Wolf + * + * 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. + */ + +#include "block/block_int.h" +#include "qemu-common.h" +#include "qcow2.h" +#include "trace.h" + +typedef struct BlockCachedTable { + void* table; + int64_t offset; + bool dirty; + int cache_hits; + int ref; +} BlockCachedTable; + +struct BlockCache { + BlockCachedTable* entries; + struct BlockCache* depends; + int size; + bool depends_on_flush; +}; + +BlockCache *block_cache_create(BlockDriverState *bs, int num_tables) +{ + 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); + + for (i = 0; i < c->size; i++) { + c->entries[i].table = qemu_blockalign(bs, s->cluster_size); + } + + return c; +} + +int block_cache_destroy(BlockDriverState* bs, BlockCache *c) +{ + int i; + + for (i = 0; i < c->size; i++) { + assert(c->entries[i].ref == 0); + qemu_vfree(c->entries[i].table); + } + + g_free(c->entries); + g_free(c); + + return 0; +} + +static int block_cache_flush_dependency(BlockDriverState *bs, BlockCache *c) +{ + int ret; + + ret = block_cache_flush(bs, c->depends); + if (ret < 0) { + return ret; + } + + c->depends = NULL; + c->depends_on_flush = false; + + return 0; +} + +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); + + if (c->depends) { + ret = block_cache_flush_dependency(bs, c); + } else if (c->depends_on_flush) { + ret = bdrv_flush(bs->file); + if (ret >= 0) { + c->depends_on_flush = false; + } + } + + if (ret < 0) { + return ret; + } + + if (c == s->refcount_block_cache) { + BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART); + } else if (c == s->l2_table_cache) { + BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE); + } + + ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->entries[i].table, + s->cluster_size); + if (ret < 0) { + return ret; + } + + c->entries[i].dirty = false; + + return 0; +} + +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); + + for (i = 0; i < c->size; i++) { + ret = block_cache_entry_flush(bs, c, i); + if (ret < 0 && result != -ENOSPC) { + result = ret; + } + } + + if (result == 0) { + ret = bdrv_flush(bs->file); + if (ret < 0) { + result = ret; + } + } + + return result; +} + +int block_cache_set_dependency(BlockDriverState *bs, BlockCache *c, + BlockCache *dependency) +{ + int ret; + + if (dependency->depends) { + ret = block_cache_flush_dependency(bs, dependency); + if (ret < 0) { + return ret; + } + } + + if (c->depends && (c->depends != dependency)) { + ret = block_cache_flush_dependency(bs, c); + if (ret < 0) { + return ret; + } + } + + c->depends = dependency; + return 0; +} + +void block_cache_depends_on_flush(BlockCache *c) +{ + c->depends_on_flush = true; +} + +static int block_cache_find_entry_to_replace(BlockCache *c) +{ + int i; + int min_count = INT_MAX; + int min_index = -1; + + + for (i = 0; i < c->size; i++) { + if (c->entries[i].ref) { + continue; + } + + if (c->entries[i].cache_hits < min_count) { + min_index = i; + min_count = c->entries[i].cache_hits; + } + + /* Give newer hits priority */ + /* TODO Check how to optimize the replacement strategy */ + c->entries[i].cache_hits /= 2; + } + + if (min_index == -1) { + /* This can't happen in current synchronous code, but leave the check + * here as a reminder for whoever starts using AIO with the cache */ + abort(); + } + return min_index; +} + +static int block_cache_do_get(BlockDriverState *bs, BlockCache *c, + 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, + offset, read_from_disk); + + /* Check if the table is already cached */ + for (i = 0; i < c->size; i++) { + if (c->entries[i].offset == offset) { + goto found; + } + } + + /* 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); + if (i < 0) { + return i; + } + + ret = block_cache_entry_flush(bs, c, i); + if (ret < 0) { + return ret; + } + + trace_block_cache_get_read(qemu_coroutine_self(), + c == s->l2_table_cache, i); + c->entries[i].offset = 0; + if (read_from_disk) { + if (c == s->l2_table_cache) { + BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD); + } + + ret = bdrv_pread(bs->file, offset, c->entries[i].table, s->cluster_size); + if (ret < 0) { + return ret; + } + } + + /* Give the table some hits for the start so that it won't be replaced + * immediately. The number 32 is completely arbitrary. */ + c->entries[i].cache_hits = 32; + c->entries[i].offset = offset; + + /* And return the right table */ +found: + c->entries[i].cache_hits++; + c->entries[i].ref++; + *table = c->entries[i].table; + + trace_block_cache_get_done(qemu_coroutine_self(), + c == s->l2_table_cache, i); + + return 0; +} + +int block_cache_get(BlockDriverState *bs, BlockCache *c, uint64_t offset, + 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) +{ + return block_cache_do_get(bs, c, offset, table, false); +} + +int block_cache_put(BlockDriverState *bs, BlockCache *c, void **table) +{ + int i; + + for (i = 0; i < c->size; i++) { + if (c->entries[i].table == *table) { + goto found; + } + } + return -ENOENT; + +found: + c->entries[i].ref--; + *table = NULL; + + assert(c->entries[i].ref >= 0); + return 0; +} + +void block_cache_entry_mark_dirty(BlockCache *c, void *table) +{ + int i; + + for (i = 0; i < c->size; i++) { + if (c->entries[i].table == table) { + goto found; + } + } + abort(); + +found: + c->entries[i].dirty = true; +} diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c deleted file mode 100644 index 2f3114e..0000000 --- a/block/qcow2-cache.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * L2/refcount table cache for the QCOW2 format - * - * Copyright (c) 2010 Kevin Wolf - * - * 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. - */ - -#include "block/block_int.h" -#include "qemu-common.h" -#include "qcow2.h" -#include "trace.h" - -typedef struct Qcow2CachedTable { - void* table; - int64_t offset; - bool dirty; - int cache_hits; - int ref; -} Qcow2CachedTable; - -struct Qcow2Cache { - Qcow2CachedTable* entries; - struct Qcow2Cache* depends; - int size; - bool depends_on_flush; -}; - -Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables) -{ - BDRVQcowState *s = bs->opaque; - Qcow2Cache *c; - int i; - - c = g_malloc0(sizeof(*c)); - c->size = num_tables; - c->entries = g_malloc0(sizeof(*c->entries) * num_tables); - - for (i = 0; i < c->size; i++) { - c->entries[i].table = qemu_blockalign(bs, s->cluster_size); - } - - return c; -} - -int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c) -{ - int i; - - for (i = 0; i < c->size; i++) { - assert(c->entries[i].ref == 0); - qemu_vfree(c->entries[i].table); - } - - g_free(c->entries); - g_free(c); - - return 0; -} - -static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c) -{ - int ret; - - ret = qcow2_cache_flush(bs, c->depends); - if (ret < 0) { - return ret; - } - - c->depends = NULL; - c->depends_on_flush = false; - - return 0; -} - -static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i) -{ - BDRVQcowState *s = bs->opaque; - int ret = 0; - - if (!c->entries[i].dirty || !c->entries[i].offset) { - return 0; - } - - trace_qcow2_cache_entry_flush(qemu_coroutine_self(), - c == s->l2_table_cache, i); - - if (c->depends) { - ret = qcow2_cache_flush_dependency(bs, c); - } else if (c->depends_on_flush) { - ret = bdrv_flush(bs->file); - if (ret >= 0) { - c->depends_on_flush = false; - } - } - - if (ret < 0) { - return ret; - } - - if (c == s->refcount_block_cache) { - BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART); - } else if (c == s->l2_table_cache) { - BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE); - } - - ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->entries[i].table, - s->cluster_size); - if (ret < 0) { - return ret; - } - - c->entries[i].dirty = false; - - return 0; -} - -int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c) -{ - BDRVQcowState *s = bs->opaque; - int result = 0; - int ret; - int i; - - trace_qcow2_cache_flush(qemu_coroutine_self(), c == s->l2_table_cache); - - for (i = 0; i < c->size; i++) { - ret = qcow2_cache_entry_flush(bs, c, i); - if (ret < 0 && result != -ENOSPC) { - result = ret; - } - } - - if (result == 0) { - ret = bdrv_flush(bs->file); - if (ret < 0) { - result = ret; - } - } - - return result; -} - -int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c, - Qcow2Cache *dependency) -{ - int ret; - - if (dependency->depends) { - ret = qcow2_cache_flush_dependency(bs, dependency); - if (ret < 0) { - return ret; - } - } - - if (c->depends && (c->depends != dependency)) { - ret = qcow2_cache_flush_dependency(bs, c); - if (ret < 0) { - return ret; - } - } - - c->depends = dependency; - return 0; -} - -void qcow2_cache_depends_on_flush(Qcow2Cache *c) -{ - c->depends_on_flush = true; -} - -static int qcow2_cache_find_entry_to_replace(Qcow2Cache *c) -{ - int i; - int min_count = INT_MAX; - int min_index = -1; - - - for (i = 0; i < c->size; i++) { - if (c->entries[i].ref) { - continue; - } - - if (c->entries[i].cache_hits < min_count) { - min_index = i; - min_count = c->entries[i].cache_hits; - } - - /* Give newer hits priority */ - /* TODO Check how to optimize the replacement strategy */ - c->entries[i].cache_hits /= 2; - } - - if (min_index == -1) { - /* This can't happen in current synchronous code, but leave the check - * here as a reminder for whoever starts using AIO with the cache */ - abort(); - } - return min_index; -} - -static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c, - uint64_t offset, void **table, bool read_from_disk) -{ - BDRVQcowState *s = bs->opaque; - int i; - int ret; - - trace_qcow2_cache_get(qemu_coroutine_self(), c == s->l2_table_cache, - offset, read_from_disk); - - /* Check if the table is already cached */ - for (i = 0; i < c->size; i++) { - if (c->entries[i].offset == offset) { - goto found; - } - } - - /* If not, write a table back and replace it */ - i = qcow2_cache_find_entry_to_replace(c); - trace_qcow2_cache_get_replace_entry(qemu_coroutine_self(), - c == s->l2_table_cache, i); - if (i < 0) { - return i; - } - - ret = qcow2_cache_entry_flush(bs, c, i); - if (ret < 0) { - return ret; - } - - trace_qcow2_cache_get_read(qemu_coroutine_self(), - c == s->l2_table_cache, i); - c->entries[i].offset = 0; - if (read_from_disk) { - if (c == s->l2_table_cache) { - BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD); - } - - ret = bdrv_pread(bs->file, offset, c->entries[i].table, s->cluster_size); - if (ret < 0) { - return ret; - } - } - - /* Give the table some hits for the start so that it won't be replaced - * immediately. The number 32 is completely arbitrary. */ - c->entries[i].cache_hits = 32; - c->entries[i].offset = offset; - - /* And return the right table */ -found: - c->entries[i].cache_hits++; - c->entries[i].ref++; - *table = c->entries[i].table; - - trace_qcow2_cache_get_done(qemu_coroutine_self(), - c == s->l2_table_cache, i); - - return 0; -} - -int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, - void **table) -{ - return qcow2_cache_do_get(bs, c, offset, table, true); -} - -int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, - void **table) -{ - return qcow2_cache_do_get(bs, c, offset, table, false); -} - -int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table) -{ - int i; - - for (i = 0; i < c->size; i++) { - if (c->entries[i].table == *table) { - goto found; - } - } - return -ENOENT; - -found: - c->entries[i].ref--; - *table = NULL; - - assert(c->entries[i].ref >= 0); - return 0; -} - -void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table) -{ - int i; - - for (i = 0; i < c->size; i++) { - if (c->entries[i].table == table) { - goto found; - } - } - abort(); - -found: - c->entries[i].dirty = true; -} diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 76f30e5..ede64af 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -75,7 +75,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, return new_l1_table_offset; } - ret = qcow2_cache_flush(bs, s->refcount_block_cache); + ret = block_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { goto fail; } @@ -125,7 +125,7 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset, BDRVQcowState *s = bs->opaque; int ret; - ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, (void**) l2_table); + ret = block_cache_get(bs, s->l2_table_cache, l2_offset, (void**) l2_table); return ret; } @@ -186,7 +186,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) return l2_offset; } - ret = qcow2_cache_flush(bs, s->refcount_block_cache); + ret = block_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { goto fail; } @@ -194,7 +194,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) /* allocate a new entry in the l2 cache */ trace_qcow2_l2_allocate_get_empty(bs, l1_index); - ret = qcow2_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table); + ret = block_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table); if (ret < 0) { return ret; } @@ -209,7 +209,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) /* if there was an old l2 table, read it from the disk */ BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ); - ret = qcow2_cache_get(bs, s->l2_table_cache, + ret = block_cache_get(bs, s->l2_table_cache, old_l2_offset & L1E_OFFSET_MASK, (void**) &old_table); if (ret < 0) { @@ -218,7 +218,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) memcpy(l2_table, old_table, s->cluster_size); - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &old_table); + ret = block_cache_put(bs, s->l2_table_cache, (void**) &old_table); if (ret < 0) { goto fail; } @@ -228,8 +228,8 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE); trace_qcow2_l2_allocate_write_l2(bs, l1_index); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); - ret = qcow2_cache_flush(bs, s->l2_table_cache); + block_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + ret = block_cache_flush(bs, s->l2_table_cache); if (ret < 0) { goto fail; } @@ -248,7 +248,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) fail: trace_qcow2_l2_allocate_done(bs, l1_index, ret); - qcow2_cache_put(bs, s->l2_table_cache, (void**) table); + block_cache_put(bs, s->l2_table_cache, (void**) table); s->l1_table[l1_index] = old_l2_offset; return ret; } @@ -484,7 +484,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, abort(); } - qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); nb_available = (c * s->cluster_sectors); @@ -594,13 +594,13 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, * allocated. */ cluster_offset = be64_to_cpu(l2_table[l2_index]); if (cluster_offset & L2E_OFFSET_MASK) { - qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); return 0; } cluster_offset = qcow2_alloc_bytes(bs, compressed_size); if (cluster_offset < 0) { - qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); return 0; } @@ -615,9 +615,9 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, /* compressed clusters never have the copied flag */ BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + block_cache_entry_mark_dirty(s->l2_table_cache, l2_table); l2_table[l2_index] = cpu_to_be64(cluster_offset); - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + ret = block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (ret < 0) { return 0; } @@ -649,7 +649,7 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m, Qcow2COWRegion *r) * need to be sure that the refcounts have been increased and COW was * handled. */ - qcow2_cache_depends_on_flush(s->l2_table_cache); + block_cache_depends_on_flush(s->l2_table_cache); return 0; } @@ -682,7 +682,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) qcow2_mark_dirty(bs); } if (qcow2_need_accurate_refcounts(s)) { - qcow2_cache_set_dependency(bs, s->l2_table_cache, + block_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache); } @@ -690,7 +690,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) if (ret < 0) { goto err; } - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + block_cache_entry_mark_dirty(s->l2_table_cache, l2_table); for (i = 0; i < m->nb_clusters; i++) { /* if two concurrent writes happen to the same unallocated cluster @@ -707,7 +707,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) } - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + ret = block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (ret < 0) { goto err; } @@ -916,7 +916,7 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset, /* Cleanup */ out: - pret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + pret = block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (pret < 0) { return pret; } @@ -1044,7 +1044,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, * wrong with our code. */ assert(nb_clusters > 0); - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + ret = block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (ret < 0) { return ret; } @@ -1335,14 +1335,14 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, } /* First remove L2 entries */ - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + block_cache_entry_mark_dirty(s->l2_table_cache, l2_table); l2_table[l2_index + i] = cpu_to_be64(0); /* Then decrease the refcount */ qcow2_free_any_clusters(bs, old_offset, 1); } - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + ret = block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (ret < 0) { return ret; } @@ -1412,7 +1412,7 @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset, old_offset = be64_to_cpu(l2_table[l2_index + i]); /* Update L2 entries */ - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + block_cache_entry_mark_dirty(s->l2_table_cache, l2_table); if (old_offset & QCOW_OFLAG_COMPRESSED) { l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO); qcow2_free_any_clusters(bs, old_offset, 1); @@ -1421,7 +1421,7 @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset, } } - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + ret = block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (ret < 0) { return ret; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index b32738f..332af27 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -71,7 +71,7 @@ static int load_refcount_block(BlockDriverState *bs, int ret; BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_LOAD); - ret = qcow2_cache_get(bs, s->refcount_block_cache, refcount_block_offset, + ret = block_cache_get(bs, s->refcount_block_cache, refcount_block_offset, refcount_block); return ret; @@ -98,7 +98,7 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index) if (!refcount_block_offset) return 0; - ret = qcow2_cache_get(bs, s->refcount_block_cache, refcount_block_offset, + ret = block_cache_get(bs, s->refcount_block_cache, refcount_block_offset, (void**) &refcount_block); if (ret < 0) { return ret; @@ -108,7 +108,7 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index) ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); refcount = be16_to_cpu(refcount_block[block_index]); - ret = qcow2_cache_put(bs, s->refcount_block_cache, + ret = block_cache_put(bs, s->refcount_block_cache, (void**) &refcount_block); if (ret < 0) { return ret; @@ -201,7 +201,7 @@ static int alloc_refcount_block(BlockDriverState *bs, *refcount_block = NULL; /* We write to the refcount table, so we might depend on L2 tables */ - ret = qcow2_cache_flush(bs, s->l2_table_cache); + ret = block_cache_flush(bs, s->l2_table_cache); if (ret < 0) { return ret; } @@ -220,7 +220,7 @@ static int alloc_refcount_block(BlockDriverState *bs, if (in_same_refcount_block(s, new_block, cluster_index << s->cluster_bits)) { /* Zero the new refcount block before updating it */ - ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block, + ret = block_cache_get_empty(bs, s->refcount_block_cache, new_block, (void**) refcount_block); if (ret < 0) { goto fail_block; @@ -240,14 +240,14 @@ static int alloc_refcount_block(BlockDriverState *bs, goto fail_block; } - ret = qcow2_cache_flush(bs, s->refcount_block_cache); + ret = block_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { goto fail_block; } /* Initialize the new refcount block only after updating its refcount, * update_refcount uses the refcount cache itself */ - ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block, + ret = block_cache_get_empty(bs, s->refcount_block_cache, new_block, (void**) refcount_block); if (ret < 0) { goto fail_block; @@ -258,8 +258,8 @@ static int alloc_refcount_block(BlockDriverState *bs, /* Now the new refcount block needs to be written to disk */ BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE); - qcow2_cache_entry_mark_dirty(s->refcount_block_cache, *refcount_block); - ret = qcow2_cache_flush(bs, s->refcount_block_cache); + block_cache_entry_mark_dirty(s->refcount_block_cache, *refcount_block); + ret = block_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { goto fail_block; } @@ -279,7 +279,7 @@ static int alloc_refcount_block(BlockDriverState *bs, return 0; } - ret = qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block); + ret = block_cache_put(bs, s->refcount_block_cache, (void**) refcount_block); if (ret < 0) { goto fail_block; } @@ -413,7 +413,7 @@ fail_table: g_free(new_table); fail_block: if (*refcount_block != NULL) { - qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block); + block_cache_put(bs, s->refcount_block_cache, (void**) refcount_block); } return ret; } @@ -439,7 +439,7 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, } if (addend < 0) { - qcow2_cache_set_dependency(bs, s->refcount_block_cache, + block_cache_set_dependency(bs, s->refcount_block_cache, s->l2_table_cache); } @@ -456,7 +456,7 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, /* Load the refcount block and allocate it if needed */ if (table_index != old_table_index) { if (refcount_block) { - ret = qcow2_cache_put(bs, s->refcount_block_cache, + ret = block_cache_put(bs, s->refcount_block_cache, (void**) &refcount_block); if (ret < 0) { goto fail; @@ -470,7 +470,7 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, } old_table_index = table_index; - qcow2_cache_entry_mark_dirty(s->refcount_block_cache, refcount_block); + block_cache_entry_mark_dirty(s->refcount_block_cache, refcount_block); /* we can update the count and save it */ block_index = cluster_index & @@ -493,7 +493,7 @@ fail: /* Write last changed block to disk */ if (refcount_block) { int wret; - wret = qcow2_cache_put(bs, s->refcount_block_cache, + wret = block_cache_put(bs, s->refcount_block_cache, (void**) &refcount_block); if (wret < 0) { return ret < 0 ? ret : wret; @@ -671,7 +671,7 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size) * or explicitly by update_cluster_refcount(). Refcount blocks must be * flushed before the caller's L2 table updates. */ - qcow2_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache); + block_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache); return offset; } @@ -767,7 +767,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, old_l2_offset = l2_offset; l2_offset &= L1E_OFFSET_MASK; - ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, + ret = block_cache_get(bs, s->l2_table_cache, l2_offset, (void**) &l2_table); if (ret < 0) { goto fail; @@ -811,16 +811,16 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } if (offset != old_offset) { if (addend > 0) { - qcow2_cache_set_dependency(bs, s->l2_table_cache, + block_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache); } l2_table[j] = cpu_to_be64(offset); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + block_cache_entry_mark_dirty(s->l2_table_cache, l2_table); } } } - ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + ret = block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); if (ret < 0) { goto fail; } @@ -847,7 +847,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, ret = bdrv_flush(bs); fail: if (l2_table) { - qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + block_cache_put(bs, s->l2_table_cache, (void**) &l2_table); } /* Update L1 only if it isn't deleted anyway (addend = -1) */ diff --git a/block/qcow2.c b/block/qcow2.c index dcd63d1..c3340ad 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -454,8 +454,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) } /* alloc L2 table/refcount block cache */ - s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE); - s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE); + s->l2_table_cache = block_cache_create(bs, L2_CACHE_SIZE); + s->refcount_block_cache = block_cache_create(bs, REFCOUNT_CACHE_SIZE); s->cluster_cache = g_malloc(s->cluster_size); /* one more sector for decompressed data alignment */ @@ -556,7 +556,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) qcow2_refcount_close(bs); g_free(s->l1_table); if (s->l2_table_cache) { - qcow2_cache_destroy(bs, s->l2_table_cache); + block_cache_destroy(bs, s->l2_table_cache); } g_free(s->cluster_cache); qemu_vfree(s->cluster_data); @@ -921,13 +921,13 @@ static void qcow2_close(BlockDriverState *bs) BDRVQcowState *s = bs->opaque; g_free(s->l1_table); - qcow2_cache_flush(bs, s->l2_table_cache); - qcow2_cache_flush(bs, s->refcount_block_cache); + block_cache_flush(bs, s->l2_table_cache); + block_cache_flush(bs, s->refcount_block_cache); qcow2_mark_clean(bs); - qcow2_cache_destroy(bs, s->l2_table_cache); - qcow2_cache_destroy(bs, s->refcount_block_cache); + block_cache_destroy(bs, s->l2_table_cache); + block_cache_destroy(bs, s->refcount_block_cache); g_free(s->unknown_header_fields); cleanup_unknown_header_ext(bs); @@ -1632,14 +1632,14 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs) int ret; qemu_co_mutex_lock(&s->lock); - ret = qcow2_cache_flush(bs, s->l2_table_cache); + ret = block_cache_flush(bs, s->l2_table_cache); if (ret < 0) { qemu_co_mutex_unlock(&s->lock); return ret; } if (qcow2_need_accurate_refcounts(s)) { - ret = qcow2_cache_flush(bs, s->refcount_block_cache); + ret = block_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { qemu_co_mutex_unlock(&s->lock); return ret; diff --git a/block/qcow2.h b/block/qcow2.h index 6959c6a..6e63217 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -97,8 +97,8 @@ typedef struct QCowSnapshot { uint64_t vm_clock_nsec; } QCowSnapshot; -struct Qcow2Cache; -typedef struct Qcow2Cache Qcow2Cache; +struct BlockCache; +typedef struct BlockCache BlockCache; typedef struct Qcow2UnknownHeaderExtension { uint32_t magic; @@ -149,8 +149,8 @@ typedef struct BDRVQcowState { uint64_t l1_table_offset; uint64_t *l1_table; - Qcow2Cache* l2_table_cache; - Qcow2Cache* refcount_block_cache; + BlockCache* l2_table_cache; + BlockCache* refcount_block_cache; uint8_t *cluster_cache; uint8_t *cluster_data; @@ -393,19 +393,19 @@ void qcow2_free_snapshots(BlockDriverState *bs); int qcow2_read_snapshots(BlockDriverState *bs); /* qcow2-cache.c functions */ -Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables); -int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c); +BlockCache *block_cache_create(BlockDriverState *bs, int num_tables); +int block_cache_destroy(BlockDriverState* bs, BlockCache *c); -void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table); -int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c); -int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c, - Qcow2Cache *dependency); -void qcow2_cache_depends_on_flush(Qcow2Cache *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 qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, +int block_cache_get(BlockDriverState *bs, BlockCache *c, uint64_t offset, void **table); -int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, +int block_cache_get_empty(BlockDriverState *bs, BlockCache *c, uint64_t offset, void **table); -int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table); +int block_cache_put(BlockDriverState *bs, BlockCache *c, void **table); #endif diff --git a/trace-events b/trace-events index c5f1ccb..b7edcc9 100644 --- a/trace-events +++ b/trace-events @@ -503,12 +503,12 @@ qcow2_l2_allocate_write_l2(void *bs, int l1_index) "bs %p l1_index %d" qcow2_l2_allocate_write_l1(void *bs, int l1_index) "bs %p l1_index %d" qcow2_l2_allocate_done(void *bs, int l1_index, int ret) "bs %p l1_index %d ret %d" -qcow2_cache_get(void *co, int c, uint64_t offset, bool read_from_disk) "co %p is_l2_cache %d offset %" PRIx64 " read_from_disk %d" -qcow2_cache_get_replace_entry(void *co, int c, int i) "co %p is_l2_cache %d index %d" -qcow2_cache_get_read(void *co, int c, int i) "co %p is_l2_cache %d index %d" -qcow2_cache_get_done(void *co, int c, int i) "co %p is_l2_cache %d index %d" -qcow2_cache_flush(void *co, int c) "co %p is_l2_cache %d" -qcow2_cache_entry_flush(void *co, int c, int i) "co %p is_l2_cache %d index %d" +block_cache_get(void *co, int c, uint64_t offset, bool read_from_disk) "co %p is_l2_cache %d offset %" PRIx64 " read_from_disk %d" +block_cache_get_replace_entry(void *co, int c, int i) "co %p is_l2_cache %d index %d" +block_cache_get_read(void *co, int c, int i) "co %p is_l2_cache %d index %d" +block_cache_get_done(void *co, int c, int i) "co %p is_l2_cache %d index %d" +block_cache_flush(void *co, int c) "co %p is_l2_cache %d" +block_cache_entry_flush(void *co, int c, int i) "co %p is_l2_cache %d index %d" # block/qed-l2-cache.c qed_alloc_l2_cache_entry(void *l2_cache, void *entry) "l2_cache %p entry %p"