From patchwork Fri Dec 18 15:07:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 559006 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 0D97D1402BD for ; Sat, 19 Dec 2015 04:09:29 +1100 (AEDT) Received: from localhost ([::1]:33889 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a9yWz-0001Ii-FA for incoming@patchwork.ozlabs.org; Fri, 18 Dec 2015 12:09:25 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58696) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a9wdg-0000Na-Sg for qemu-devel@nongnu.org; Fri, 18 Dec 2015 10:08:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a9wdf-0004JN-JF for qemu-devel@nongnu.org; Fri, 18 Dec 2015 10:08:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38891) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a9wdY-0004Gt-3P; Fri, 18 Dec 2015 10:08:04 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (Postfix) with ESMTPS id CD4F0C0AEE2B; Fri, 18 Dec 2015 15:08:03 +0000 (UTC) Received: from noname.redhat.com (ovpn-116-99.ams2.redhat.com [10.36.116.99]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tBIF7uCs003029; Fri, 18 Dec 2015 10:08:02 -0500 From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 18 Dec 2015 16:07:10 +0100 Message-Id: <1450451274-7472-5-git-send-email-kwolf@redhat.com> In-Reply-To: <1450451274-7472-1-git-send-email-kwolf@redhat.com> References: <1450451274-7472-1-git-send-email-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, qemu-devel@nongnu.org Subject: [Qemu-devel] [PULL 04/48] qcow2: Add .bdrv_join_options callback 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 qcow2 accepts a few driver-specific options that overlap semantically (e.g. "overlap-check" is an alias of "overlap-check.template", and any missing cache size option is derived from the given ones). When bdrv_reopen() merges the set of updated options with left out options that should be kept at their old value, we need to consider this and filter out any duplicates (which would generally cause errors because new and old value would contradict each other). This patch adds a .bdrv_join_options callback to BlockDriver and implements it for qcow2. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Reviewed-by: Alberto Garcia --- block/qcow2.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ include/block/block_int.h | 1 + 2 files changed, 48 insertions(+) diff --git a/block/qcow2.c b/block/qcow2.c index 5b59fa3..fda1562 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1282,6 +1282,52 @@ static void qcow2_reopen_abort(BDRVReopenState *state) g_free(state->opaque); } +static void qcow2_join_options(QDict *options, QDict *old_options) +{ + bool has_new_overlap_template = + qdict_haskey(options, QCOW2_OPT_OVERLAP) || + qdict_haskey(options, QCOW2_OPT_OVERLAP_TEMPLATE); + bool has_new_total_cache_size = + qdict_haskey(options, QCOW2_OPT_CACHE_SIZE); + bool has_all_cache_options; + + /* New overlap template overrides all old overlap options */ + if (has_new_overlap_template) { + qdict_del(old_options, QCOW2_OPT_OVERLAP); + qdict_del(old_options, QCOW2_OPT_OVERLAP_TEMPLATE); + qdict_del(old_options, QCOW2_OPT_OVERLAP_MAIN_HEADER); + qdict_del(old_options, QCOW2_OPT_OVERLAP_ACTIVE_L1); + qdict_del(old_options, QCOW2_OPT_OVERLAP_ACTIVE_L2); + qdict_del(old_options, QCOW2_OPT_OVERLAP_REFCOUNT_TABLE); + qdict_del(old_options, QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK); + qdict_del(old_options, QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE); + qdict_del(old_options, QCOW2_OPT_OVERLAP_INACTIVE_L1); + qdict_del(old_options, QCOW2_OPT_OVERLAP_INACTIVE_L2); + } + + /* New total cache size overrides all old options */ + if (qdict_haskey(options, QCOW2_OPT_CACHE_SIZE)) { + qdict_del(old_options, QCOW2_OPT_L2_CACHE_SIZE); + qdict_del(old_options, QCOW2_OPT_REFCOUNT_CACHE_SIZE); + } + + qdict_join(options, old_options, false); + + /* + * If after merging all cache size options are set, an old total size is + * overwritten. Do keep all options, however, if all three are new. The + * resulting error message is what we want to happen. + */ + has_all_cache_options = + qdict_haskey(options, QCOW2_OPT_CACHE_SIZE) || + qdict_haskey(options, QCOW2_OPT_L2_CACHE_SIZE) || + qdict_haskey(options, QCOW2_OPT_REFCOUNT_CACHE_SIZE); + + if (has_all_cache_options && !has_new_total_cache_size) { + qdict_del(options, QCOW2_OPT_CACHE_SIZE); + } +} + static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { @@ -3145,6 +3191,7 @@ BlockDriver bdrv_qcow2 = { .bdrv_reopen_prepare = qcow2_reopen_prepare, .bdrv_reopen_commit = qcow2_reopen_commit, .bdrv_reopen_abort = qcow2_reopen_abort, + .bdrv_join_options = qcow2_join_options, .bdrv_create = qcow2_create, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_co_get_block_status = qcow2_co_get_block_status, diff --git a/include/block/block_int.h b/include/block/block_int.h index 66e208d..c2ce965 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -121,6 +121,7 @@ struct BlockDriver { BlockReopenQueue *queue, Error **errp); void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state); void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state); + void (*bdrv_join_options)(QDict *options, QDict *old_options); int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags, Error **errp);